From c819a7a71eadc7fa1ec58d71dfef6e37cbc4187a Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 26 Nov 2021 12:07:23 +0100 Subject: Fix MDEV-27055 (regression of MDEV-24493) --- storage/connect/odbconn.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 8ff8d3a84e1..9175a4c9053 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -1422,7 +1422,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) PGLOBAL& g = m_G; void *buffer; bool b; - UWORD n; + UWORD n, k; SWORD len, tp, ncol = 0; ODBCCOL *colp; RETCODE rc; @@ -1489,15 +1489,16 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) } else { do { rc = SQLExecDirect(hstmt, (PUCHAR)sql, SQL_NTS); - } while (rc == SQL_STILL_EXECUTING); + } while (rc == SQL_STILL_EXECUTING); if (!Check(rc)) ThrowDBX(rc, "SQLExecDirect", hstmt); do { rc = SQLNumResultCols(hstmt, &ncol); - } while (rc == SQL_STILL_EXECUTING); + } while (rc == SQL_STILL_EXECUTING); + k = 0; // used for column number } // endif Srcdef for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext()) @@ -1519,18 +1520,23 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) sprintf(m_G->Message, MSG(INV_COLUMN_TYPE), colp->GetResultType(), SVP(colp->GetName())); ThrowDBX(m_G->Message); - } // endif tp + } // endif tp + + if (m_Tdb->Srcdef) + k = colp->GetIndex(); + else + k++; if (trace(1)) htrc("Binding col=%u type=%d buf=%p len=%d slen=%p\n", - n, tp, buffer, len, colp->GetStrLen()); + k, tp, buffer, len, colp->GetStrLen()); - rc = SQLBindCol(hstmt, colp->GetIndex(), tp, buffer, len, colp->GetStrLen()); + rc = SQLBindCol(hstmt, k, tp, buffer, len, colp->GetStrLen()); if (!Check(rc)) ThrowDBX(rc, "SQLBindCol", hstmt); - } // endif pcol + } // endif colp } catch(DBX *x) { if (trace(1)) -- cgit v1.2.1 From 42fea34d4a9f4ed1ae87cf8494f07bcdfcc49e83 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 20 Dec 2021 19:55:00 -0800 Subject: MDEV-27262 Unexpected index intersection with full index scan for an index If when extracting a range condition for an index from the WHERE condition Range Optimizer sees that the range condition covers the whole index then such condition should be discarded because it cannot be used in any range scan. In some cases Range Optimizer really does it, but there remained some conditions for which it was not done. As a result the optimizer could produce index merge plans with the full index scan for one of the indexes participating in the index merge. This could be observed in one of the test cases from index_merge1.inc where a plan with index_merge_sort_union was produced and in the test case reported for this bug where a plan with index_merge_sort_intersect was produced. In both cases one of two index scans participating in index merge ran over the whole index. The patch slightly changes the original above mentioned test case from index_merge1.inc to be able to produce an intended plan employing index_merge_sort_union. The original query was left to show that index merge is not used for it anymore. It should be noted that for the plan with index_merge_sort_intersect could be chosen for execution only due to a defect in the InnoDB code that returns wrong estimates for the cardinality of big ranges. This bug led to serious problems in 10.4+ where the optimization using Rowid filters is employed (see mdev-26446). Approved by Sergey Petrunia --- mysql-test/include/index_merge1.inc | 14 ++++- mysql-test/r/index_merge_myisam.result | 18 +++++- mysql-test/r/range_innodb.result | 105 +++++++++++++++++++++++++++++++++ mysql-test/t/range_innodb.test | 93 +++++++++++++++++++++++++++++ sql/opt_range.cc | 19 +++++- 5 files changed, 243 insertions(+), 6 deletions(-) diff --git a/mysql-test/include/index_merge1.inc b/mysql-test/include/index_merge1.inc index b168a767d7c..ebadb5077ae 100644 --- a/mysql-test/include/index_merge1.inc +++ b/mysql-test/include/index_merge1.inc @@ -150,12 +150,22 @@ explain select * from t0 where (((key3 <7 and key7 < 6) or key5 < 2) and (key5 < 5 or key6 < 6)); explain select * from t0 where - ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4)) + ((key3 < 4 or key5 < 4) and (key1 < 4 or key2 < 4)) or ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where - ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4)) + ((key3 < 4 or key5 < 4) and (key1 < 4 or key2 < 4)) + or + ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); + +explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where + ((key3 < 5 or key5 < 4) and (key1 < 4 or key2 < 4)) + or + ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); + +explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where + ((key3 < 10 or key5 < 4) and (key1 < 4 or key2 < 4)) or ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result index 5a23092457d..a3e9e4f5881 100644 --- a/mysql-test/r/index_merge_myisam.result +++ b/mysql-test/r/index_merge_myisam.result @@ -173,17 +173,29 @@ or id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7 i3,i5 4,4 NULL 11 Using sort_union(i3,i5); Using where explain select * from t0 where -((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4)) +((key3 < 4 or key5 < 4) and (key1 < 4 or key2 < 4)) or ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t0 ALL i1,i2,i3,i5,i6 NULL NULL NULL 1024 Using where explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where -((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4)) +((key3 < 4 or key5 < 4) and (key1 < 4 or key2 < 4)) +or +((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 4,4 NULL 1024 Using sort_union(i3,i5); Using where +explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where +((key3 < 5 or key5 < 4) and (key1 < 4 or key2 < 4)) or ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 0,4 NULL 1024 Using sort_union(i3,i5); Using where +1 SIMPLE t0 ALL i1,i2,i3,i5,i6 NULL NULL NULL 1024 Using where +explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where +((key3 < 10 or key5 < 4) and (key1 < 4 or key2 < 4)) +or +((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6)); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL i1,i2,i3,i5,i6 NULL NULL NULL 1024 Using where select * from t0 where key1 < 5 or key8 < 4 order by key1; key1 key2 key3 key4 key5 key6 key7 key8 1 1 1 1 1 1 1 1023 diff --git a/mysql-test/r/range_innodb.result b/mysql-test/r/range_innodb.result index f2349f26571..df111bc05be 100644 --- a/mysql-test/r/range_innodb.result +++ b/mysql-test/r/range_innodb.result @@ -108,3 +108,108 @@ DROP TABLE t0,t1; SET @@GLOBAL.debug_dbug = @saved_dbug; set @@optimizer_switch= @optimizer_switch_save; # End of 10.1 tests +# +# MDEV-27262: Index intersection with full scan over an index +# +CREATE TABLE t1 ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +p char(32) DEFAULT NULL, +es tinyint(3) unsigned NOT NULL DEFAULT 0, +er tinyint(3) unsigned NOT NULL DEFAULT 0, +x mediumint(8) unsigned NOT NULL DEFAULT 0, +PRIMARY KEY (id), +INDEX es (es), +INDEX x (x), +INDEX er (er,x), +INDEX p (p) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +insert into t1(es,er) select 0, 1 from seq_1_to_45; +insert into t1(es,er) select 0, 2 from seq_1_to_49; +insert into t1(es,er) select 0, 3 from seq_1_to_951; +insert into t1(es,er) select 0, 3 from seq_1_to_1054; +insert into t1(es,er) select 0, 6 from seq_1_to_25; +insert into t1(es,er) select 0, 11 from seq_1_to_1; +insert into t1(es,er) select 1, 1 from seq_1_to_45; +insert into t1(es,er) select 1, 2 from seq_1_to_16; +insert into t1(es,er) select 1, 3 from seq_1_to_511; +insert into t1(es,er) select 1, 4 from seq_1_to_687; +insert into t1(es,er) select 1, 6 from seq_1_to_50; +insert into t1(es,er) select 1, 7 from seq_1_to_4; +insert into t1(es,er) select 1, 11 from seq_1_to_1; +insert into t1(es,er) select 2, 1 from seq_1_to_82; +insert into t1(es,er) select 2, 2 from seq_1_to_82; +insert into t1(es,er) select 2, 3 from seq_1_to_1626; +insert into t1(es,er) select 2, 4 from seq_1_to_977; +insert into t1(es,er) select 2, 6 from seq_1_to_33; +insert into t1(es,er) select 2, 11 from seq_1_to_1; +insert into t1(es,er) select 3, 1 from seq_1_to_245; +insert into t1(es,er) select 3, 2 from seq_1_to_81; +insert into t1(es,er) select 3, 3 from seq_1_to_852; +insert into t1(es,er) select 3, 4 from seq_1_to_2243; +insert into t1(es,er) select 3, 6 from seq_1_to_44; +insert into t1(es,er) select 3, 11 from seq_1_to_1; +insert into t1(es,er) select 4, 1 from seq_1_to_91; +insert into t1(es,er) select 4, 2 from seq_1_to_83; +insert into t1(es,er) select 4, 3 from seq_1_to_297; +insert into t1(es,er) select 4, 4 from seq_1_to_2456; +insert into t1(es,er) select 4, 6 from seq_1_to_19; +insert into t1(es,er) select 4, 11 from seq_1_to_1; +update t1 set p='foobar'; +update t1 set x=0; +set @save_isp=@@innodb_stats_persistent; +set global innodb_stats_persistent= 1; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +set optimizer_switch='index_merge_sort_intersection=on'; +SELECT * FROM t1 +WHERE ((p = 'foo' AND er != 4) OR er = 4 ) AND (es >= 4) LIMIT 2; +id p es er x +14645 foobar 4 4 0 +14646 foobar 4 4 0 +EXPLAIN EXTENDED SELECT * FROM t1 +WHERE ((p = 'foo' AND er != 4) OR er = 4 ) AND (es >= 4) LIMIT 2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range es,er,p es 1 NULL # 100.00 Using index condition; Using where +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`p` AS `p`,`test`.`t1`.`es` AS `es`,`test`.`t1`.`er` AS `er`,`test`.`t1`.`x` AS `x` from `test`.`t1` where (`test`.`t1`.`p` = 'foo' and `test`.`t1`.`er` <> 4 or `test`.`t1`.`er` = 4) and `test`.`t1`.`es` >= 4 limit 2 +set optimizer_switch='index_merge_sort_intersection=off'; +SELECT * FROM t1 +WHERE ((p = 'foo' AND er != 4) OR er = 4 ) AND (es >= 4) LIMIT 2; +id p es er x +14645 foobar 4 4 0 +14646 foobar 4 4 0 +EXPLAIN EXTENDED SELECT * FROM t1 +WHERE ((p = 'foo' AND er != 4) OR er = 4 ) AND (es >= 4) LIMIT 2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range es,er,p es 1 NULL # 100.00 Using index condition; Using where +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`p` AS `p`,`test`.`t1`.`es` AS `es`,`test`.`t1`.`er` AS `er`,`test`.`t1`.`x` AS `x` from `test`.`t1` where (`test`.`t1`.`p` = 'foo' and `test`.`t1`.`er` <> 4 or `test`.`t1`.`er` = 4) and `test`.`t1`.`es` >= 4 limit 2 +set optimizer_switch='index_merge_sort_intersection=on'; +SELECT * FROM t1 +WHERE ((p = 'foo' AND er < 6) OR er >=2 ) AND (es >= 4) LIMIT 2; +id p es er x +14007 foobar 4 2 0 +14008 foobar 4 2 0 +EXPLAIN EXTENDED SELECT * FROM t1 +WHERE ((p = 'foo' AND er < 6) OR er >=2 ) AND (es >= 4) LIMIT 2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range es,er,p es 1 NULL # 100.00 Using index condition; Using where +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`p` AS `p`,`test`.`t1`.`es` AS `es`,`test`.`t1`.`er` AS `er`,`test`.`t1`.`x` AS `x` from `test`.`t1` where (`test`.`t1`.`p` = 'foo' and `test`.`t1`.`er` < 6 or `test`.`t1`.`er` >= 2) and `test`.`t1`.`es` >= 4 limit 2 +set optimizer_switch='index_merge_sort_intersection=off'; +SELECT * FROM t1 +WHERE ((p = 'foo' AND er < 6) OR er >=2 ) AND (es >= 4) LIMIT 2; +id p es er x +14007 foobar 4 2 0 +14008 foobar 4 2 0 +EXPLAIN EXTENDED SELECT * FROM t1 +WHERE ((p = 'foo' AND er < 6) OR er >=2 ) AND (es >= 4) LIMIT 2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range es,er,p es 1 NULL # 100.00 Using index condition; Using where +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`p` AS `p`,`test`.`t1`.`es` AS `es`,`test`.`t1`.`er` AS `er`,`test`.`t1`.`x` AS `x` from `test`.`t1` where (`test`.`t1`.`p` = 'foo' and `test`.`t1`.`er` < 6 or `test`.`t1`.`er` >= 2) and `test`.`t1`.`es` >= 4 limit 2 +set optimizer_switch='index_merge_sort_intersection=default'; +set global innodb_stats_persistent= @save_isp; +DROP TABLE t1; +# End of 10.2 tests diff --git a/mysql-test/t/range_innodb.test b/mysql-test/t/range_innodb.test index 428e5c26e5c..b8a6a7c960c 100644 --- a/mysql-test/t/range_innodb.test +++ b/mysql-test/t/range_innodb.test @@ -116,3 +116,96 @@ SET @@GLOBAL.debug_dbug = @saved_dbug; set @@optimizer_switch= @optimizer_switch_save; --echo # End of 10.1 tests + +--echo # +--echo # MDEV-27262: Index intersection with full scan over an index +--echo # + +--source include/have_sequence.inc + +CREATE TABLE t1 ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + p char(32) DEFAULT NULL, + es tinyint(3) unsigned NOT NULL DEFAULT 0, + er tinyint(3) unsigned NOT NULL DEFAULT 0, + x mediumint(8) unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (id), + INDEX es (es), + INDEX x (x), + INDEX er (er,x), + INDEX p (p) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +insert into t1(es,er) select 0, 1 from seq_1_to_45; +insert into t1(es,er) select 0, 2 from seq_1_to_49; +insert into t1(es,er) select 0, 3 from seq_1_to_951; +insert into t1(es,er) select 0, 3 from seq_1_to_1054; +insert into t1(es,er) select 0, 6 from seq_1_to_25; +insert into t1(es,er) select 0, 11 from seq_1_to_1; +insert into t1(es,er) select 1, 1 from seq_1_to_45; +insert into t1(es,er) select 1, 2 from seq_1_to_16; +insert into t1(es,er) select 1, 3 from seq_1_to_511; +insert into t1(es,er) select 1, 4 from seq_1_to_687; +insert into t1(es,er) select 1, 6 from seq_1_to_50; +insert into t1(es,er) select 1, 7 from seq_1_to_4; +insert into t1(es,er) select 1, 11 from seq_1_to_1; +insert into t1(es,er) select 2, 1 from seq_1_to_82; +insert into t1(es,er) select 2, 2 from seq_1_to_82; +insert into t1(es,er) select 2, 3 from seq_1_to_1626; +insert into t1(es,er) select 2, 4 from seq_1_to_977; +insert into t1(es,er) select 2, 6 from seq_1_to_33; +insert into t1(es,er) select 2, 11 from seq_1_to_1; +insert into t1(es,er) select 3, 1 from seq_1_to_245; +insert into t1(es,er) select 3, 2 from seq_1_to_81; +insert into t1(es,er) select 3, 3 from seq_1_to_852; +insert into t1(es,er) select 3, 4 from seq_1_to_2243; +insert into t1(es,er) select 3, 6 from seq_1_to_44; +insert into t1(es,er) select 3, 11 from seq_1_to_1; +insert into t1(es,er) select 4, 1 from seq_1_to_91; +insert into t1(es,er) select 4, 2 from seq_1_to_83; +insert into t1(es,er) select 4, 3 from seq_1_to_297; +insert into t1(es,er) select 4, 4 from seq_1_to_2456; +insert into t1(es,er) select 4, 6 from seq_1_to_19; +insert into t1(es,er) select 4, 11 from seq_1_to_1; +update t1 set p='foobar'; +update t1 set x=0; +set @save_isp=@@innodb_stats_persistent; +set global innodb_stats_persistent= 1; +analyze table t1; + +let $q= +SELECT * FROM t1 + WHERE ((p = 'foo' AND er != 4) OR er = 4 ) AND (es >= 4) LIMIT 2; + +set optimizer_switch='index_merge_sort_intersection=on'; +eval $q; +--replace_column 9 # +eval EXPLAIN EXTENDED $q; + +set optimizer_switch='index_merge_sort_intersection=off'; +# execution of $q and explain for it led to an assertion failure in 10.4 +# (with the optimizer switch rowid_filter set to 'on') +eval $q; +--replace_column 9 # +eval EXPLAIN EXTENDED $q; + +let $q= +SELECT * FROM t1 + WHERE ((p = 'foo' AND er < 6) OR er >=2 ) AND (es >= 4) LIMIT 2; + +set optimizer_switch='index_merge_sort_intersection=on'; +eval $q; +--replace_column 9 # +eval EXPLAIN EXTENDED $q; + +set optimizer_switch='index_merge_sort_intersection=off'; +eval $q; +--replace_column 9 # +eval EXPLAIN EXTENDED $q; + +set optimizer_switch='index_merge_sort_intersection=default'; + +set global innodb_stats_persistent= @save_isp; +DROP TABLE t1; + +--echo # End of 10.2 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index f3f184367c9..89ee8cf98e1 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -9329,7 +9329,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) uint max_part_no= MY_MAX(key1->max_part_no, key2->max_part_no); - for (key2=key2->first(); key2; ) + for (key2=key2->first(); ; ) { /* key1 consists of one or more ranges. tmp is the range currently @@ -9343,6 +9343,16 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) ^ tmp */ + if (key1->min_flag & NO_MIN_RANGE && + key1->max_flag & NO_MAX_RANGE) + { + if (key1->maybe_flag) + return new SEL_ARG(SEL_ARG::MAYBE_KEY); + return 0; // Always true OR + } + if (!key2) + break; + SEL_ARG *tmp=key1->find_range(key2); /* @@ -9413,6 +9423,13 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) key2->copy_min(tmp); if (!(key1=key1->tree_delete(tmp))) { // Only one key in tree + if (key2->min_flag & NO_MIN_RANGE && + key2->max_flag & NO_MAX_RANGE) + { + if (key2->maybe_flag) + return new SEL_ARG(SEL_ARG::MAYBE_KEY); + return 0; // Always true OR + } key1=key2; key1->make_root(); key2=key2_next; -- cgit v1.2.1 From 4daf9d7c3ee05baf7643f3a866e6d3828e1bb93b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 27 Dec 2021 14:47:47 +0100 Subject: MDEV-27364 Build from 10.2-10.4 srpm fails on RHEL8 family due to discrepancy in jemalloc requirements pass jemalloc requirement down to srpm build --- cmake/cpack_rpm.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index eacb6310ece..63186e625bf 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -333,6 +333,7 @@ ENDMACRO() ADDIF(CMAKE_BUILD_TYPE) ADDIF(BUILD_CONFIG) ADDIF(WITH_SSL) +ADDIF(WITH_JEMALLOC) ENDIF() ENDIF(RPM) -- cgit v1.2.1 From fad1d15326651a92895c799829ff66edc37fc20f Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Wed, 15 Dec 2021 13:59:38 +0530 Subject: MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' failed in Diagnostics_area::set_ok_status in my_ok from mysql_sql_stmt_prepare Analysis: Before PREPARE is executed, binlog_format is STATEMENT. This PREPARE had SET STATEMENT which sets binlog_format to ROW. Now after PREPARE is done we reset the binlog_format (back to STATEMENT). But we have temporary table, it doesn't let changing binlog_format=ROW to binlog_format=STATEMENT and gives error which goes unreported. This unreported error eventually causes assertion failure. Fix: Change return type for LEX::restore_set_statement_var() to bool and make it return error state. --- .../extra/binlog_tests/mysqlbinlog_row_engine.inc | 25 +++++++++++++++++++++ .../binlog/r/binlog_mysqlbinlog_row_innodb.result | 20 +++++++++++++++++ .../binlog/r/binlog_mysqlbinlog_row_myisam.result | 26 ++++++++++++++++++++++ sql/sql_lex.cc | 7 +++--- sql/sql_lex.h | 2 +- sql/sql_prepare.cc | 2 +- 6 files changed, 77 insertions(+), 5 deletions(-) diff --git a/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc b/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc index ce919550b51..874be1dac61 100644 --- a/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc +++ b/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc @@ -1921,3 +1921,28 @@ let $MYSQLD_DATADIR= `select @@datadir`; DROP TABLE t1; +--echo # +--echo # Beginning of 10.2 test +--echo # +--echo # MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK && +--echo # is_bulk_op())' failed in Diagnostics_area::set_ok_status in my_ok +--echo # from mysql_sql_stmt_prepare +--echo # + +CREATE TEMPORARY TABLE a (c INT) ENGINE=InnoDB; +CREATE TABLE b (c INT) ENGINE=InnoDB; + +--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR +PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT * FROM b'; + +DROP TABLE b; +DROP TEMPORARY TABLE a; + +CREATE TEMPORARY TABLE t (c INT); +--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR +PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT 1'; +DROP TEMPORARY TABLE t; + +--echo # +--echo # End of 10.2 test +--echo # diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result index 388bec68db7..cfd89c661dc 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result @@ -6352,3 +6352,23 @@ ROLLBACK /* added by mysqlbinlog */; # Cleanup. # DROP TABLE t1; +# +# Beginning of 10.2 test +# +# MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK && +# is_bulk_op())' failed in Diagnostics_area::set_ok_status in my_ok +# from mysql_sql_stmt_prepare +# +CREATE TEMPORARY TABLE a (c INT) ENGINE=InnoDB; +CREATE TABLE b (c INT) ENGINE=InnoDB; +PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT * FROM b'; +ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables +DROP TABLE b; +DROP TEMPORARY TABLE a; +CREATE TEMPORARY TABLE t (c INT); +PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT 1'; +ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables +DROP TEMPORARY TABLE t; +# +# End of 10.2 test +# diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result index 44dbbba8eab..77bb25e5971 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result @@ -6393,3 +6393,29 @@ ROLLBACK /* added by mysqlbinlog */; # Cleanup. # DROP TABLE t1; +# +# Beginning of 10.2 test +# +# MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK && +# is_bulk_op())' failed in Diagnostics_area::set_ok_status in my_ok +# from mysql_sql_stmt_prepare +# +CREATE TEMPORARY TABLE a (c INT) ENGINE=InnoDB; +Warnings: +Warning 1286 Unknown storage engine 'InnoDB' +Warning 1266 Using storage engine MyISAM for table 'a' +CREATE TABLE b (c INT) ENGINE=InnoDB; +Warnings: +Warning 1286 Unknown storage engine 'InnoDB' +Warning 1266 Using storage engine MyISAM for table 'b' +PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT * FROM b'; +ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables +DROP TABLE b; +DROP TEMPORARY TABLE a; +CREATE TEMPORARY TABLE t (c INT); +PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT 1'; +ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables +DROP TEMPORARY TABLE t; +# +# End of 10.2 test +# diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ed0b4b36553..125bbfe1bfd 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4766,18 +4766,19 @@ void LEX::free_arena_for_set_stmt() DBUG_VOID_RETURN; } -void LEX::restore_set_statement_var() +bool LEX::restore_set_statement_var() { + bool err= false; DBUG_ENTER("LEX::restore_set_statement_var"); if (!old_var_list.is_empty()) { DBUG_PRINT("info", ("vars: %d", old_var_list.elements)); - sql_set_variables(thd, &old_var_list, false); + err= sql_set_variables(thd, &old_var_list, false); old_var_list.empty(); free_arena_for_set_stmt(); } DBUG_ASSERT(!is_arena_for_set_stmt()); - DBUG_VOID_RETURN; + DBUG_RETURN(err); } /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index bdf52e8ef7b..5585a95f67f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3094,7 +3094,7 @@ public: int print_explain(select_result_sink *output, uint8 explain_flags, bool is_analyze, bool *printed_anything); - void restore_set_statement_var(); + bool restore_set_statement_var(); void init_last_field(Column_definition *field, const char *name, CHARSET_INFO *cs); void set_last_field_type(const Lex_field_type_st &type); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9339cb925e5..bb1a99d9eef 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4283,7 +4283,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) Restore original values of variables modified on handling SET STATEMENT clause. */ - thd->lex->restore_set_statement_var(); + error|= thd->lex->restore_set_statement_var(); /* The order is important */ lex->unit.cleanup(); -- cgit v1.2.1 From 189bf300cae5bbf147b780d6191f7fef6ad58678 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 29 Dec 2021 14:54:34 +0400 Subject: MDEV-21639 DEFAULT(col) evaluates to a bad value in WHERE clause The problem happened because Item_default_value did not overload properly the val_xxx_result() family methods. This change backports the patch for: MDEV-24958 Server crashes in my_strtod / Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob) which earlier fixed the problem in 10.3. --- mysql-test/r/func_default.result | 121 +++++++++++++++++++++++++++++++++++++++ mysql-test/t/func_default.test | 102 ++++++++++++++++++++++++++++++++- sql/item.cc | 42 ++++++++++++++ sql/item.h | 10 ++++ 4 files changed, 272 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_default.result b/mysql-test/r/func_default.result index 9699f0795e3..8721270ca1c 100644 --- a/mysql-test/r/func_default.result +++ b/mysql-test/r/func_default.result @@ -29,6 +29,9 @@ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL; ERROR HY000: Field 'mi' doesn't have a default value DROP TABLE t1; +# +# Start of 10.2 tests +# set timestamp=unix_timestamp('2001-01-01 10:20:30.123456'); create table t1 (a int default 1, b int default (a+1), c varchar(100) default 'foo', d text default 'bar', @@ -40,3 +43,121 @@ default(a) default(b) default(c) default(d) default(e) default(f) 1 2 foo bar 2001-01-01 10:20:30 2001-01-01 10:20:30.120000 1 11 foo bar 2001-01-01 10:20:30 2001-01-01 10:20:30.120000 drop table t1; +# +# MDEV-21639 DEFAULT(col) evaluates to a bad value in WHERE clause +# +CREATE TABLE t1 (a BIGINT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END = 10 AS ce +FROM t1; +a DEFAULT(a) c ce +10000 10 10 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10; +a +10000 +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END = 10 AS ce +FROM t1; +a DEFAULT(a) c ce +10000 10 10 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10; +a +10000 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(10,0) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END = 10 AS ce +FROM t1; +a DEFAULT(a) c ce +10000 10 10 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10; +a +10000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(32) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END = '10' AS ce +FROM t1; +a DEFAULT(a) c ce +10000 10 10 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10'; +a +10000 +DROP TABLE t1; +CREATE TABLE t1 (a DATE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,DATE'2001-01-01'))); +INSERT INTO t1 VALUES ('2000-01-01'); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END = '2001-01-01' AS ce +FROM t1; +a DEFAULT(a) c ce +2000-01-01 2001-01-01 2001-01-01 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01'; +a +2000-01-01 +DROP TABLE t1; +CREATE TABLE t1 (a TIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,TIME'10:20:30'))); +INSERT INTO t1 VALUES ('10:00:00'); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END = '10:20:30' AS ce +FROM t1; +a DEFAULT(a) c ce +10:00:00 10:20:30 10:20:30 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10:20:30'; +a +10:00:00 +DROP TABLE t1; +CREATE TABLE t1 (a DATETIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),TIMESTAMP'2001-01-01 10:20:30'))); +INSERT INTO t1 VALUES ('2000-01-01 10:00:00'); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END = '2001-01-01 10:20:30' AS ce +FROM t1; +a DEFAULT(a) c ce +2000-01-01 10:00:00 2001-01-01 10:20:30 2001-01-01 10:20:30 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01 10:20:30'; +a +2000-01-01 10:00:00 +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),FALSE))); +INSERT INTO t1 VALUES (10); +SELECT +a, +DEFAULT(a), +CASE WHEN a THEN DEFAULT(a) END AS c, +CASE WHEN a THEN DEFAULT(a) END IS FALSE AS ce +FROM t1; +a DEFAULT(a) c ce +10 0 0 1 +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END IS FALSE; +a +10 +DROP TABLE t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/func_default.test b/mysql-test/t/func_default.test index 332bfca021f..cba7842c68f 100644 --- a/mysql-test/t/func_default.test +++ b/mysql-test/t/func_default.test @@ -34,9 +34,9 @@ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL; DROP TABLE t1; -# -# 10.2 tests -# +--echo # +--echo # Start of 10.2 tests +--echo # set timestamp=unix_timestamp('2001-01-01 10:20:30.123456'); create table t1 (a int default 1, b int default (a+1), @@ -46,3 +46,99 @@ insert t1 () values (); insert t1 (a) values (10); select default(a),default(b),default(c),default(d),default(e),default(f) from t1; drop table t1; + +--echo # +--echo # MDEV-21639 DEFAULT(col) evaluates to a bad value in WHERE clause +--echo # + +CREATE TABLE t1 (a BIGINT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END = 10 AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10; +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END = 10 AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(10,0) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END = 10 AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(32) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10))); +INSERT INTO t1 VALUES (10000); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END = '10' AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10'; +DROP TABLE t1; + +CREATE TABLE t1 (a DATE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,DATE'2001-01-01'))); +INSERT INTO t1 VALUES ('2000-01-01'); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END = '2001-01-01' AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01'; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,TIME'10:20:30'))); +INSERT INTO t1 VALUES ('10:00:00'); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END = '10:20:30' AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10:20:30'; +DROP TABLE t1; + +CREATE TABLE t1 (a DATETIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),TIMESTAMP'2001-01-01 10:20:30'))); +INSERT INTO t1 VALUES ('2000-01-01 10:00:00'); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END = '2001-01-01 10:20:30' AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01 10:20:30'; +DROP TABLE t1; + +CREATE TABLE t1 (a INT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),FALSE))); +INSERT INTO t1 VALUES (10); +SELECT + a, + DEFAULT(a), + CASE WHEN a THEN DEFAULT(a) END AS c, + CASE WHEN a THEN DEFAULT(a) END IS FALSE AS ce +FROM t1; +SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END IS FALSE; +DROP TABLE t1; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/item.cc b/sql/item.cc index 3ff0219c3b3..a5b313b786d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9165,6 +9165,48 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) &view_error_processor); } +double Item_default_value::val_result() +{ + calculate(); + return Item_field::val_result(); +} + +longlong Item_default_value::val_int_result() +{ + calculate(); + return Item_field::val_int_result(); +} + +String *Item_default_value::str_result(String* tmp) +{ + calculate(); + return Item_field::str_result(tmp); +} + +bool Item_default_value::val_bool_result() +{ + calculate(); + return Item_field::val_bool_result(); +} + +bool Item_default_value::is_null_result() +{ + calculate(); + return Item_field::is_null_result(); +} + +my_decimal *Item_default_value::val_decimal_result(my_decimal *decimal_value) +{ + calculate(); + return Item_field::val_decimal_result(decimal_value); +} + +bool Item_default_value::get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate) +{ + calculate(); + return Item_field::get_date_result(ltime, fuzzydate); +} + table_map Item_default_value::used_tables() const { if (!field || !field->default_value) diff --git a/sql/item.h b/sql/item.h index 2a904c1691a..997352ef27a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5478,6 +5478,16 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal *decimal_value); bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate); + + /* Result variants */ + double val_result(); + longlong val_int_result(); + String *str_result(String* tmp); + my_decimal *val_decimal_result(my_decimal *val); + bool val_bool_result(); + bool is_null_result(); + bool get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate); + bool send(Protocol *protocol, String *buffer); int save_in_field(Field *field_arg, bool no_conversions); bool save_in_param(THD *thd, Item_param *param) -- cgit v1.2.1 From 546520042f91e1b8ddc0af04a24629b3ceffbc87 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 29 Dec 2021 23:04:13 +0400 Subject: MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string Adding 10.2 specific tests only. No code changes. The problem was earlier fixed by MDEV-21580 and MDEV-22715. --- mysql-test/r/order_by.result | 23 +++++++++++++++++++++++ mysql-test/t/order_by.test | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 39b4e25d670..d1f2d067643 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -3485,4 +3485,27 @@ b a 40 1 30 4 drop table t1,t2; +# +# MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string +# +SET sql_mode=''; +SET @@SESSION.max_sort_length=4; +Warnings: +Warning 1292 Truncated incorrect max_sort_length value: '4' +CREATE TABLE t1 (c TIMESTAMP(1)); +INSERT INTO t1 VALUES(0); +DELETE FROM t1 ORDER BY c; +DROP TABLE t1; +SET @@SESSION.max_sort_length=DEFAULT; +SET sql_mode=DEFAULT; +SET sql_mode=''; +SET @@SESSION.max_sort_length=1; +Warnings: +Warning 1292 Truncated incorrect max_sort_length value: '1' +CREATE TEMPORARY TABLE t1 (c DATETIME); +INSERT INTO t1 VALUES(0); +DELETE FROM t1 ORDER BY c; +DROP TABLE t1; +SET @@SESSION.max_sort_length=DEFAULT; +SET sql_mode=DEFAULT; # End of 10.2 tests diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 4e50fc5b3c6..7cb24b7d03b 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -2309,4 +2309,27 @@ explain (select b,a from t2 order by a limit 3) order by b desc; drop table t1,t2; +--echo # +--echo # MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string +--echo # + +SET sql_mode=''; +SET @@SESSION.max_sort_length=4; +CREATE TABLE t1 (c TIMESTAMP(1)); +INSERT INTO t1 VALUES(0); +DELETE FROM t1 ORDER BY c; +DROP TABLE t1; +SET @@SESSION.max_sort_length=DEFAULT; +SET sql_mode=DEFAULT; + +SET sql_mode=''; +SET @@SESSION.max_sort_length=1; +CREATE TEMPORARY TABLE t1 (c DATETIME); +INSERT INTO t1 VALUES(0); +DELETE FROM t1 ORDER BY c; +DROP TABLE t1; +SET @@SESSION.max_sort_length=DEFAULT; +SET sql_mode=DEFAULT; + + --echo # End of 10.2 tests -- cgit v1.2.1 From 5d57e04b27d0e69081b63b9e382cc3d9dc4480c0 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 30 Dec 2021 16:45:37 +1100 Subject: MDEV-27386: cpack rpm libsepol installed detects verison incorrectly ... when two packages are installed. (fc35 with i686 and x86_64 packages of libsepol installed). $ rpm -q --qf "%{VERSION}" libsepol 3.33.3 Restricting the version to the current achitecture generates a much more obtainable version dependency. $ rpm -q --qf "%{VERSION}" libsepol.x86_64 3.3 This make dependency resolution easier preventing: $ sudo dnf localinstall MariaDB-server-10.8.0-1.fc35.x86_64.rpm ... Last metadata expiration check: 2:06:49 ago on Thu 30 Dec 2021 14:02:32. Error: Problem 1: conflicting requests - nothing provides libsepol >= 3.33.3 needed by MariaDB-server-10.8.0-1.fc35.x86_64 The CMAKE_SYSTEM_PROCESSOR is used in the generation of architecture filenames so its preduent to just use the same version. --- support-files/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index 810e0127202..028201cb1b1 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -88,7 +88,7 @@ IF(UNIX) INSTALL(FILES ${out} DESTINATION ${inst_location}/policy/selinux COMPONENT SupportFiles) ENDFOREACH() IF(RPM) - EXECUTE_PROCESS(COMMAND rpm -q --qf "%{VERSION}" libsepol + EXECUTE_PROCESS(COMMAND rpm -q --qf "%{VERSION}" libsepol."${CMAKE_SYSTEM_PROCESSOR}" OUTPUT_VARIABLE LIBSEPOL_VERSION RESULT_VARIABLE err) IF (NOT err) SET(CPACK_RPM_server_PACKAGE_REQUIRES -- cgit v1.2.1 From 452c9a4d72c18a19136a91f4d59ee60eedd486be Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Fri, 24 Dec 2021 14:00:47 +0530 Subject: MDEV-26698: Incorrect row number upon INSERT .. SELECT from the same table: rows are counted twice Analysis: When the table we are trying to insert into and the SELECT table are same for INSERT ... SELECT, rows from the SELECT table are copied into internal temporary table and then to the INSERT table. We only want to count the rows when we start inserting into the table. Fix: Reset the counter to 1 before starting to copy from internal temporary table to select table and then increment the counter. --- mysql-test/r/insert_select.result | 19 +++ mysql-test/t/insert_select.test | 25 +++ sql/sql_select.cc | 19 ++- .../mysql-test/rocksdb/r/col_opt_not_null.result | 174 ++++++++++----------- .../mysql-test/rocksdb/r/col_opt_null.result | 174 ++++++++++----------- .../mysql-test/rocksdb/r/col_opt_unsigned.result | 96 ++++++------ .../rocksdb/mysql-test/rocksdb/r/type_char.result | 18 +-- .../rocksdb/mysql-test/rocksdb/r/type_int.result | 128 +++++++-------- .../mysql-test/rocksdb/r/type_varbinary.result | 14 +- .../mysql-test/rocksdb/r/type_varchar.result | 14 +- 10 files changed, 365 insertions(+), 316 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index b86c859d0bd..26076eec068 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -865,3 +865,22 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1, t2; End of 5.5 tests +# +# Beginning of 10.2 test +# +# MDEV-26698: Incorrect row number upon INSERT .. SELECT from the same +# table: rows are counted twice +# +CREATE TABLE t1(a TINYINT); +INSERT INTO t1 VALUES (1), (100); +INSERT INTO t1 SELECT a*2 FROM t1; +Warnings: +Warning 1264 Out of range value for column 'a' at row 2 +TRUNCATE TABLE t1; +# using ORDER BY +INSERT INTO t1 VALUES(1), (2), (100), (3); +INSERT INTO t1 SELECT a*2 FROM t1 ORDER BY a; +Warnings: +Warning 1264 Out of range value for column 'a' at row 4 +DROP TABLE t1; +# End of 10.2 test diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 27a831fbe3f..e577f29fd92 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -435,3 +435,28 @@ show create table t2; drop table t1, t2; --echo End of 5.5 tests + +--echo # +--echo # Beginning of 10.2 test +--echo # +--echo # MDEV-26698: Incorrect row number upon INSERT .. SELECT from the same +--echo # table: rows are counted twice +--echo # + +CREATE TABLE t1(a TINYINT); + +INSERT INTO t1 VALUES (1), (100); + +INSERT INTO t1 SELECT a*2 FROM t1; + +TRUNCATE TABLE t1; + +--echo # using ORDER BY + +INSERT INTO t1 VALUES(1), (2), (100), (3); + +INSERT INTO t1 SELECT a*2 FROM t1 ORDER BY a; + +DROP TABLE t1; + +--echo # End of 10.2 test diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a331f4f3dbc..a7e2ac4e374 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -19146,11 +19146,8 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, */ if (shortcut_for_distinct && found_records != join->found_records) DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); - } - else - { - join->thd->get_stmt_da()->inc_current_row_for_warning(); - join_tab->read_record.unlock_row(join_tab); + + DBUG_RETURN(NESTED_LOOP_OK); } } else @@ -19160,9 +19157,11 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, with the beginning coinciding with the current partial join. */ join->join_examined_rows++; - join->thd->get_stmt_da()->inc_current_row_for_warning(); - join_tab->read_record.unlock_row(join_tab); } + + join->thd->get_stmt_da()->inc_current_row_for_warning(); + join_tab->read_record.unlock_row(join_tab); + DBUG_RETURN(NESTED_LOOP_OK); } @@ -26945,6 +26944,12 @@ AGGR_OP::end_send() table->reginfo.lock_type= TL_UNLOCK; bool in_first_read= true; + + /* + Reset the counter before copying rows from internal temporary table to + INSERT table. + */ + join_tab->join->thd->get_stmt_da()->reset_current_row_for_warning(); while (rc == NESTED_LOOP_OK) { int error; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/col_opt_not_null.result b/storage/rocksdb/mysql-test/rocksdb/r/col_opt_not_null.result index 64d87b7116d..0aa604178cc 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/col_opt_not_null.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/col_opt_not_null.result @@ -157,13 +157,13 @@ Warning 1265 Data truncated for column 'v64' at row 1 Warning 1265 Data truncated for column 'v65000' at row 1 INSERT INTO t1 (v0,v1,v64,v65000) SELECT v65000, v65000, CONCAT('a',v65000), CONCAT(v65000,v1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'v0' at row 5 -Warning 1265 Data truncated for column 'v1' at row 5 -Warning 1265 Data truncated for column 'v64' at row 5 -Warning 1265 Data truncated for column 'v0' at row 6 -Warning 1265 Data truncated for column 'v1' at row 6 -Warning 1265 Data truncated for column 'v64' at row 6 -Warning 1265 Data truncated for column 'v65000' at row 6 +Warning 1265 Data truncated for column 'v0' at row 2 +Warning 1265 Data truncated for column 'v1' at row 2 +Warning 1265 Data truncated for column 'v64' at row 2 +Warning 1265 Data truncated for column 'v0' at row 3 +Warning 1265 Data truncated for column 'v1' at row 3 +Warning 1265 Data truncated for column 'v64' at row 3 +Warning 1265 Data truncated for column 'v65000' at row 3 SELECT HEX(v0), HEX(v1), HEX(v64), LENGTH(HEX(v65000)) FROM t1; HEX(v0) HEX(v1) HEX(v64) LENGTH(HEX(v65000)) 0 @@ -675,15 +675,15 @@ Warning 1265 Data truncated for column 'c20' at row 1 Warning 1265 Data truncated for column 'c255' at row 1 INSERT INTO t1 (c,c0,c1,c20,c255) SELECT c255, c255, c255, c255, CONCAT('a',c255,c1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'c' at row 5 -Warning 1265 Data truncated for column 'c0' at row 5 -Warning 1265 Data truncated for column 'c1' at row 5 -Warning 1265 Data truncated for column 'c20' at row 5 -Warning 1265 Data truncated for column 'c' at row 6 -Warning 1265 Data truncated for column 'c0' at row 6 -Warning 1265 Data truncated for column 'c1' at row 6 -Warning 1265 Data truncated for column 'c20' at row 6 -Warning 1265 Data truncated for column 'c255' at row 6 +Warning 1265 Data truncated for column 'c' at row 2 +Warning 1265 Data truncated for column 'c0' at row 2 +Warning 1265 Data truncated for column 'c1' at row 2 +Warning 1265 Data truncated for column 'c20' at row 2 +Warning 1265 Data truncated for column 'c' at row 3 +Warning 1265 Data truncated for column 'c0' at row 3 +Warning 1265 Data truncated for column 'c1' at row 3 +Warning 1265 Data truncated for column 'c20' at row 3 +Warning 1265 Data truncated for column 'c255' at row 3 SELECT c,c0,c1,c20,c255 FROM t1; c c0 c1 c20 c255 @@ -845,13 +845,13 @@ Warning 1265 Data truncated for column 'v64' at row 1 Warning 1265 Data truncated for column 'v65000' at row 1 INSERT INTO t1 (v0,v1,v64,v65000) SELECT v65000, v65000, CONCAT('a',v65000), CONCAT(v65000,v1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'v0' at row 5 -Warning 1265 Data truncated for column 'v1' at row 5 -Warning 1265 Data truncated for column 'v64' at row 5 -Warning 1265 Data truncated for column 'v65000' at row 5 -Warning 1265 Data truncated for column 'v0' at row 6 -Warning 1265 Data truncated for column 'v1' at row 6 -Warning 1265 Data truncated for column 'v64' at row 6 +Warning 1265 Data truncated for column 'v0' at row 2 +Warning 1265 Data truncated for column 'v1' at row 2 +Warning 1265 Data truncated for column 'v64' at row 2 +Warning 1265 Data truncated for column 'v65000' at row 2 +Warning 1265 Data truncated for column 'v0' at row 3 +Warning 1265 Data truncated for column 'v1' at row 3 +Warning 1265 Data truncated for column 'v64' at row 3 SELECT v0, v1, v64, LENGTH(v65000) FROM t1; v0 v1 v64 LENGTH(v65000) 0 @@ -2038,70 +2038,70 @@ Warning 1264 Out of range value for column 'b1' at row 1 Warning 1264 Out of range value for column 'b20' at row 1 INSERT INTO t1 (i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20) SELECT b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b FROM t1 WHERE b IN (-9223372036854775808,9223372036854775807,18446744073709551615); Warnings: -Warning 1264 Out of range value for column 'i' at row 8 -Warning 1264 Out of range value for column 'i0' at row 8 -Warning 1264 Out of range value for column 'i1' at row 8 -Warning 1264 Out of range value for column 'i20' at row 8 -Warning 1264 Out of range value for column 't' at row 8 -Warning 1264 Out of range value for column 't0' at row 8 -Warning 1264 Out of range value for column 't1' at row 8 -Warning 1264 Out of range value for column 't20' at row 8 -Warning 1264 Out of range value for column 's' at row 8 -Warning 1264 Out of range value for column 's0' at row 8 -Warning 1264 Out of range value for column 's1' at row 8 -Warning 1264 Out of range value for column 's20' at row 8 -Warning 1264 Out of range value for column 'm' at row 8 -Warning 1264 Out of range value for column 'm0' at row 8 -Warning 1264 Out of range value for column 'm1' at row 8 -Warning 1264 Out of range value for column 'm20' at row 8 -Warning 1264 Out of range value for column 'i' at row 9 -Warning 1264 Out of range value for column 'i0' at row 9 -Warning 1264 Out of range value for column 'i1' at row 9 -Warning 1264 Out of range value for column 'i20' at row 9 -Warning 1264 Out of range value for column 't' at row 9 -Warning 1264 Out of range value for column 't0' at row 9 -Warning 1264 Out of range value for column 't1' at row 9 -Warning 1264 Out of range value for column 't20' at row 9 -Warning 1264 Out of range value for column 's' at row 9 -Warning 1264 Out of range value for column 's0' at row 9 -Warning 1264 Out of range value for column 's1' at row 9 -Warning 1264 Out of range value for column 's20' at row 9 -Warning 1264 Out of range value for column 'm' at row 9 -Warning 1264 Out of range value for column 'm0' at row 9 -Warning 1264 Out of range value for column 'm1' at row 9 -Warning 1264 Out of range value for column 'm20' at row 9 -Warning 1264 Out of range value for column 'i' at row 10 -Warning 1264 Out of range value for column 'i0' at row 10 -Warning 1264 Out of range value for column 'i1' at row 10 -Warning 1264 Out of range value for column 'i20' at row 10 -Warning 1264 Out of range value for column 't' at row 10 -Warning 1264 Out of range value for column 't0' at row 10 -Warning 1264 Out of range value for column 't1' at row 10 -Warning 1264 Out of range value for column 't20' at row 10 -Warning 1264 Out of range value for column 's' at row 10 -Warning 1264 Out of range value for column 's0' at row 10 -Warning 1264 Out of range value for column 's1' at row 10 -Warning 1264 Out of range value for column 's20' at row 10 -Warning 1264 Out of range value for column 'm' at row 10 -Warning 1264 Out of range value for column 'm0' at row 10 -Warning 1264 Out of range value for column 'm1' at row 10 -Warning 1264 Out of range value for column 'm20' at row 10 -Warning 1264 Out of range value for column 'i' at row 11 -Warning 1264 Out of range value for column 'i0' at row 11 -Warning 1264 Out of range value for column 'i1' at row 11 -Warning 1264 Out of range value for column 'i20' at row 11 -Warning 1264 Out of range value for column 't' at row 11 -Warning 1264 Out of range value for column 't0' at row 11 -Warning 1264 Out of range value for column 't1' at row 11 -Warning 1264 Out of range value for column 't20' at row 11 -Warning 1264 Out of range value for column 's' at row 11 -Warning 1264 Out of range value for column 's0' at row 11 -Warning 1264 Out of range value for column 's1' at row 11 -Warning 1264 Out of range value for column 's20' at row 11 -Warning 1264 Out of range value for column 'm' at row 11 -Warning 1264 Out of range value for column 'm0' at row 11 -Warning 1264 Out of range value for column 'm1' at row 11 -Warning 1264 Out of range value for column 'm20' at row 11 +Warning 1264 Out of range value for column 'i' at row 1 +Warning 1264 Out of range value for column 'i0' at row 1 +Warning 1264 Out of range value for column 'i1' at row 1 +Warning 1264 Out of range value for column 'i20' at row 1 +Warning 1264 Out of range value for column 't' at row 1 +Warning 1264 Out of range value for column 't0' at row 1 +Warning 1264 Out of range value for column 't1' at row 1 +Warning 1264 Out of range value for column 't20' at row 1 +Warning 1264 Out of range value for column 's' at row 1 +Warning 1264 Out of range value for column 's0' at row 1 +Warning 1264 Out of range value for column 's1' at row 1 +Warning 1264 Out of range value for column 's20' at row 1 +Warning 1264 Out of range value for column 'm' at row 1 +Warning 1264 Out of range value for column 'm0' at row 1 +Warning 1264 Out of range value for column 'm1' at row 1 +Warning 1264 Out of range value for column 'm20' at row 1 +Warning 1264 Out of range value for column 'i' at row 2 +Warning 1264 Out of range value for column 'i0' at row 2 +Warning 1264 Out of range value for column 'i1' at row 2 +Warning 1264 Out of range value for column 'i20' at row 2 +Warning 1264 Out of range value for column 't' at row 2 +Warning 1264 Out of range value for column 't0' at row 2 +Warning 1264 Out of range value for column 't1' at row 2 +Warning 1264 Out of range value for column 't20' at row 2 +Warning 1264 Out of range value for column 's' at row 2 +Warning 1264 Out of range value for column 's0' at row 2 +Warning 1264 Out of range value for column 's1' at row 2 +Warning 1264 Out of range value for column 's20' at row 2 +Warning 1264 Out of range value for column 'm' at row 2 +Warning 1264 Out of range value for column 'm0' at row 2 +Warning 1264 Out of range value for column 'm1' at row 2 +Warning 1264 Out of range value for column 'm20' at row 2 +Warning 1264 Out of range value for column 'i' at row 3 +Warning 1264 Out of range value for column 'i0' at row 3 +Warning 1264 Out of range value for column 'i1' at row 3 +Warning 1264 Out of range value for column 'i20' at row 3 +Warning 1264 Out of range value for column 't' at row 3 +Warning 1264 Out of range value for column 't0' at row 3 +Warning 1264 Out of range value for column 't1' at row 3 +Warning 1264 Out of range value for column 't20' at row 3 +Warning 1264 Out of range value for column 's' at row 3 +Warning 1264 Out of range value for column 's0' at row 3 +Warning 1264 Out of range value for column 's1' at row 3 +Warning 1264 Out of range value for column 's20' at row 3 +Warning 1264 Out of range value for column 'm' at row 3 +Warning 1264 Out of range value for column 'm0' at row 3 +Warning 1264 Out of range value for column 'm1' at row 3 +Warning 1264 Out of range value for column 'm20' at row 3 +Warning 1264 Out of range value for column 'i' at row 4 +Warning 1264 Out of range value for column 'i0' at row 4 +Warning 1264 Out of range value for column 'i1' at row 4 +Warning 1264 Out of range value for column 'i20' at row 4 +Warning 1264 Out of range value for column 't' at row 4 +Warning 1264 Out of range value for column 't0' at row 4 +Warning 1264 Out of range value for column 't1' at row 4 +Warning 1264 Out of range value for column 't20' at row 4 +Warning 1264 Out of range value for column 's' at row 4 +Warning 1264 Out of range value for column 's0' at row 4 +Warning 1264 Out of range value for column 's1' at row 4 +Warning 1264 Out of range value for column 's20' at row 4 +Warning 1264 Out of range value for column 'm' at row 4 +Warning 1264 Out of range value for column 'm0' at row 4 +Warning 1264 Out of range value for column 'm1' at row 4 +Warning 1264 Out of range value for column 'm20' at row 4 SELECT i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20 FROM t1; i i0 i1 i20 t t0 t1 t20 s s0 s1 s20 m m0 m1 m20 b b0 b1 b20 -2147483648 -2147483648 -2147483648 -2147483648 -128 -128 -128 -128 -32768 -32768 -32768 -32768 -8388608 -8388608 -8388608 -8388608 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808 diff --git a/storage/rocksdb/mysql-test/rocksdb/r/col_opt_null.result b/storage/rocksdb/mysql-test/rocksdb/r/col_opt_null.result index ba651fcbb14..dbc569432a8 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/col_opt_null.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/col_opt_null.result @@ -146,13 +146,13 @@ Warning 1265 Data truncated for column 'v64' at row 1 Warning 1265 Data truncated for column 'v65000' at row 1 INSERT INTO t1 (v0,v1,v64,v65000) SELECT v65000, v65000, CONCAT('a',v65000), CONCAT(v65000,v1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'v0' at row 5 -Warning 1265 Data truncated for column 'v1' at row 5 -Warning 1265 Data truncated for column 'v64' at row 5 -Warning 1265 Data truncated for column 'v0' at row 6 -Warning 1265 Data truncated for column 'v1' at row 6 -Warning 1265 Data truncated for column 'v64' at row 6 -Warning 1265 Data truncated for column 'v65000' at row 6 +Warning 1265 Data truncated for column 'v0' at row 2 +Warning 1265 Data truncated for column 'v1' at row 2 +Warning 1265 Data truncated for column 'v64' at row 2 +Warning 1265 Data truncated for column 'v0' at row 3 +Warning 1265 Data truncated for column 'v1' at row 3 +Warning 1265 Data truncated for column 'v64' at row 3 +Warning 1265 Data truncated for column 'v65000' at row 3 SELECT HEX(v0), HEX(v1), HEX(v64), LENGTH(HEX(v65000)) FROM t1; HEX(v0) HEX(v1) HEX(v64) LENGTH(HEX(v65000)) 0 @@ -587,15 +587,15 @@ Warning 1265 Data truncated for column 'c20' at row 1 Warning 1265 Data truncated for column 'c255' at row 1 INSERT INTO t1 (c,c0,c1,c20,c255) SELECT c255, c255, c255, c255, CONCAT('a',c255,c1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'c' at row 5 -Warning 1265 Data truncated for column 'c0' at row 5 -Warning 1265 Data truncated for column 'c1' at row 5 -Warning 1265 Data truncated for column 'c20' at row 5 -Warning 1265 Data truncated for column 'c' at row 6 -Warning 1265 Data truncated for column 'c0' at row 6 -Warning 1265 Data truncated for column 'c1' at row 6 -Warning 1265 Data truncated for column 'c20' at row 6 -Warning 1265 Data truncated for column 'c255' at row 6 +Warning 1265 Data truncated for column 'c' at row 2 +Warning 1265 Data truncated for column 'c0' at row 2 +Warning 1265 Data truncated for column 'c1' at row 2 +Warning 1265 Data truncated for column 'c20' at row 2 +Warning 1265 Data truncated for column 'c' at row 3 +Warning 1265 Data truncated for column 'c0' at row 3 +Warning 1265 Data truncated for column 'c1' at row 3 +Warning 1265 Data truncated for column 'c20' at row 3 +Warning 1265 Data truncated for column 'c255' at row 3 SELECT c,c0,c1,c20,c255 FROM t1; c c0 c1 c20 c255 @@ -746,13 +746,13 @@ Warning 1265 Data truncated for column 'v64' at row 1 Warning 1265 Data truncated for column 'v65000' at row 1 INSERT INTO t1 (v0,v1,v64,v65000) SELECT v65000, v65000, CONCAT('a',v65000), CONCAT(v65000,v1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'v0' at row 5 -Warning 1265 Data truncated for column 'v1' at row 5 -Warning 1265 Data truncated for column 'v64' at row 5 -Warning 1265 Data truncated for column 'v65000' at row 5 -Warning 1265 Data truncated for column 'v0' at row 6 -Warning 1265 Data truncated for column 'v1' at row 6 -Warning 1265 Data truncated for column 'v64' at row 6 +Warning 1265 Data truncated for column 'v0' at row 2 +Warning 1265 Data truncated for column 'v1' at row 2 +Warning 1265 Data truncated for column 'v64' at row 2 +Warning 1265 Data truncated for column 'v65000' at row 2 +Warning 1265 Data truncated for column 'v0' at row 3 +Warning 1265 Data truncated for column 'v1' at row 3 +Warning 1265 Data truncated for column 'v64' at row 3 SELECT v0, v1, v64, LENGTH(v65000) FROM t1; v0 v1 v64 LENGTH(v65000) 0 @@ -1803,70 +1803,70 @@ Warning 1264 Out of range value for column 'b1' at row 1 Warning 1264 Out of range value for column 'b20' at row 1 INSERT INTO t1 (i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20) SELECT b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b FROM t1 WHERE b IN (-9223372036854775808,9223372036854775807,18446744073709551615); Warnings: -Warning 1264 Out of range value for column 'i' at row 8 -Warning 1264 Out of range value for column 'i0' at row 8 -Warning 1264 Out of range value for column 'i1' at row 8 -Warning 1264 Out of range value for column 'i20' at row 8 -Warning 1264 Out of range value for column 't' at row 8 -Warning 1264 Out of range value for column 't0' at row 8 -Warning 1264 Out of range value for column 't1' at row 8 -Warning 1264 Out of range value for column 't20' at row 8 -Warning 1264 Out of range value for column 's' at row 8 -Warning 1264 Out of range value for column 's0' at row 8 -Warning 1264 Out of range value for column 's1' at row 8 -Warning 1264 Out of range value for column 's20' at row 8 -Warning 1264 Out of range value for column 'm' at row 8 -Warning 1264 Out of range value for column 'm0' at row 8 -Warning 1264 Out of range value for column 'm1' at row 8 -Warning 1264 Out of range value for column 'm20' at row 8 -Warning 1264 Out of range value for column 'i' at row 9 -Warning 1264 Out of range value for column 'i0' at row 9 -Warning 1264 Out of range value for column 'i1' at row 9 -Warning 1264 Out of range value for column 'i20' at row 9 -Warning 1264 Out of range value for column 't' at row 9 -Warning 1264 Out of range value for column 't0' at row 9 -Warning 1264 Out of range value for column 't1' at row 9 -Warning 1264 Out of range value for column 't20' at row 9 -Warning 1264 Out of range value for column 's' at row 9 -Warning 1264 Out of range value for column 's0' at row 9 -Warning 1264 Out of range value for column 's1' at row 9 -Warning 1264 Out of range value for column 's20' at row 9 -Warning 1264 Out of range value for column 'm' at row 9 -Warning 1264 Out of range value for column 'm0' at row 9 -Warning 1264 Out of range value for column 'm1' at row 9 -Warning 1264 Out of range value for column 'm20' at row 9 -Warning 1264 Out of range value for column 'i' at row 10 -Warning 1264 Out of range value for column 'i0' at row 10 -Warning 1264 Out of range value for column 'i1' at row 10 -Warning 1264 Out of range value for column 'i20' at row 10 -Warning 1264 Out of range value for column 't' at row 10 -Warning 1264 Out of range value for column 't0' at row 10 -Warning 1264 Out of range value for column 't1' at row 10 -Warning 1264 Out of range value for column 't20' at row 10 -Warning 1264 Out of range value for column 's' at row 10 -Warning 1264 Out of range value for column 's0' at row 10 -Warning 1264 Out of range value for column 's1' at row 10 -Warning 1264 Out of range value for column 's20' at row 10 -Warning 1264 Out of range value for column 'm' at row 10 -Warning 1264 Out of range value for column 'm0' at row 10 -Warning 1264 Out of range value for column 'm1' at row 10 -Warning 1264 Out of range value for column 'm20' at row 10 -Warning 1264 Out of range value for column 'i' at row 11 -Warning 1264 Out of range value for column 'i0' at row 11 -Warning 1264 Out of range value for column 'i1' at row 11 -Warning 1264 Out of range value for column 'i20' at row 11 -Warning 1264 Out of range value for column 't' at row 11 -Warning 1264 Out of range value for column 't0' at row 11 -Warning 1264 Out of range value for column 't1' at row 11 -Warning 1264 Out of range value for column 't20' at row 11 -Warning 1264 Out of range value for column 's' at row 11 -Warning 1264 Out of range value for column 's0' at row 11 -Warning 1264 Out of range value for column 's1' at row 11 -Warning 1264 Out of range value for column 's20' at row 11 -Warning 1264 Out of range value for column 'm' at row 11 -Warning 1264 Out of range value for column 'm0' at row 11 -Warning 1264 Out of range value for column 'm1' at row 11 -Warning 1264 Out of range value for column 'm20' at row 11 +Warning 1264 Out of range value for column 'i' at row 1 +Warning 1264 Out of range value for column 'i0' at row 1 +Warning 1264 Out of range value for column 'i1' at row 1 +Warning 1264 Out of range value for column 'i20' at row 1 +Warning 1264 Out of range value for column 't' at row 1 +Warning 1264 Out of range value for column 't0' at row 1 +Warning 1264 Out of range value for column 't1' at row 1 +Warning 1264 Out of range value for column 't20' at row 1 +Warning 1264 Out of range value for column 's' at row 1 +Warning 1264 Out of range value for column 's0' at row 1 +Warning 1264 Out of range value for column 's1' at row 1 +Warning 1264 Out of range value for column 's20' at row 1 +Warning 1264 Out of range value for column 'm' at row 1 +Warning 1264 Out of range value for column 'm0' at row 1 +Warning 1264 Out of range value for column 'm1' at row 1 +Warning 1264 Out of range value for column 'm20' at row 1 +Warning 1264 Out of range value for column 'i' at row 2 +Warning 1264 Out of range value for column 'i0' at row 2 +Warning 1264 Out of range value for column 'i1' at row 2 +Warning 1264 Out of range value for column 'i20' at row 2 +Warning 1264 Out of range value for column 't' at row 2 +Warning 1264 Out of range value for column 't0' at row 2 +Warning 1264 Out of range value for column 't1' at row 2 +Warning 1264 Out of range value for column 't20' at row 2 +Warning 1264 Out of range value for column 's' at row 2 +Warning 1264 Out of range value for column 's0' at row 2 +Warning 1264 Out of range value for column 's1' at row 2 +Warning 1264 Out of range value for column 's20' at row 2 +Warning 1264 Out of range value for column 'm' at row 2 +Warning 1264 Out of range value for column 'm0' at row 2 +Warning 1264 Out of range value for column 'm1' at row 2 +Warning 1264 Out of range value for column 'm20' at row 2 +Warning 1264 Out of range value for column 'i' at row 3 +Warning 1264 Out of range value for column 'i0' at row 3 +Warning 1264 Out of range value for column 'i1' at row 3 +Warning 1264 Out of range value for column 'i20' at row 3 +Warning 1264 Out of range value for column 't' at row 3 +Warning 1264 Out of range value for column 't0' at row 3 +Warning 1264 Out of range value for column 't1' at row 3 +Warning 1264 Out of range value for column 't20' at row 3 +Warning 1264 Out of range value for column 's' at row 3 +Warning 1264 Out of range value for column 's0' at row 3 +Warning 1264 Out of range value for column 's1' at row 3 +Warning 1264 Out of range value for column 's20' at row 3 +Warning 1264 Out of range value for column 'm' at row 3 +Warning 1264 Out of range value for column 'm0' at row 3 +Warning 1264 Out of range value for column 'm1' at row 3 +Warning 1264 Out of range value for column 'm20' at row 3 +Warning 1264 Out of range value for column 'i' at row 4 +Warning 1264 Out of range value for column 'i0' at row 4 +Warning 1264 Out of range value for column 'i1' at row 4 +Warning 1264 Out of range value for column 'i20' at row 4 +Warning 1264 Out of range value for column 't' at row 4 +Warning 1264 Out of range value for column 't0' at row 4 +Warning 1264 Out of range value for column 't1' at row 4 +Warning 1264 Out of range value for column 't20' at row 4 +Warning 1264 Out of range value for column 's' at row 4 +Warning 1264 Out of range value for column 's0' at row 4 +Warning 1264 Out of range value for column 's1' at row 4 +Warning 1264 Out of range value for column 's20' at row 4 +Warning 1264 Out of range value for column 'm' at row 4 +Warning 1264 Out of range value for column 'm0' at row 4 +Warning 1264 Out of range value for column 'm1' at row 4 +Warning 1264 Out of range value for column 'm20' at row 4 SELECT i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20 FROM t1; i i0 i1 i20 t t0 t1 t20 s s0 s1 s20 m m0 m1 m20 b b0 b1 b20 -2147483648 -2147483648 -2147483648 -2147483648 -128 -128 -128 -128 -32768 -32768 -32768 -32768 -8388608 -8388608 -8388608 -8388608 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808 diff --git a/storage/rocksdb/mysql-test/rocksdb/r/col_opt_unsigned.result b/storage/rocksdb/mysql-test/rocksdb/r/col_opt_unsigned.result index b931743d59a..ee82ca45efe 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/col_opt_unsigned.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/col_opt_unsigned.result @@ -656,54 +656,54 @@ Warning 1264 Out of range value for column 'b1' at row 1 Warning 1264 Out of range value for column 'b20' at row 1 INSERT INTO t1 (i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20) SELECT b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b FROM t1 WHERE b IN (-9223372036854775808,9223372036854775807,18446744073709551615); Warnings: -Warning 1264 Out of range value for column 'i' at row 8 -Warning 1264 Out of range value for column 'i0' at row 8 -Warning 1264 Out of range value for column 'i1' at row 8 -Warning 1264 Out of range value for column 'i20' at row 8 -Warning 1264 Out of range value for column 't' at row 8 -Warning 1264 Out of range value for column 't0' at row 8 -Warning 1264 Out of range value for column 't1' at row 8 -Warning 1264 Out of range value for column 't20' at row 8 -Warning 1264 Out of range value for column 's' at row 8 -Warning 1264 Out of range value for column 's0' at row 8 -Warning 1264 Out of range value for column 's1' at row 8 -Warning 1264 Out of range value for column 's20' at row 8 -Warning 1264 Out of range value for column 'm' at row 8 -Warning 1264 Out of range value for column 'm0' at row 8 -Warning 1264 Out of range value for column 'm1' at row 8 -Warning 1264 Out of range value for column 'm20' at row 8 -Warning 1264 Out of range value for column 'i' at row 9 -Warning 1264 Out of range value for column 'i0' at row 9 -Warning 1264 Out of range value for column 'i1' at row 9 -Warning 1264 Out of range value for column 'i20' at row 9 -Warning 1264 Out of range value for column 't' at row 9 -Warning 1264 Out of range value for column 't0' at row 9 -Warning 1264 Out of range value for column 't1' at row 9 -Warning 1264 Out of range value for column 't20' at row 9 -Warning 1264 Out of range value for column 's' at row 9 -Warning 1264 Out of range value for column 's0' at row 9 -Warning 1264 Out of range value for column 's1' at row 9 -Warning 1264 Out of range value for column 's20' at row 9 -Warning 1264 Out of range value for column 'm' at row 9 -Warning 1264 Out of range value for column 'm0' at row 9 -Warning 1264 Out of range value for column 'm1' at row 9 -Warning 1264 Out of range value for column 'm20' at row 9 -Warning 1264 Out of range value for column 'i' at row 10 -Warning 1264 Out of range value for column 'i0' at row 10 -Warning 1264 Out of range value for column 'i1' at row 10 -Warning 1264 Out of range value for column 'i20' at row 10 -Warning 1264 Out of range value for column 't' at row 10 -Warning 1264 Out of range value for column 't0' at row 10 -Warning 1264 Out of range value for column 't1' at row 10 -Warning 1264 Out of range value for column 't20' at row 10 -Warning 1264 Out of range value for column 's' at row 10 -Warning 1264 Out of range value for column 's0' at row 10 -Warning 1264 Out of range value for column 's1' at row 10 -Warning 1264 Out of range value for column 's20' at row 10 -Warning 1264 Out of range value for column 'm' at row 10 -Warning 1264 Out of range value for column 'm0' at row 10 -Warning 1264 Out of range value for column 'm1' at row 10 -Warning 1264 Out of range value for column 'm20' at row 10 +Warning 1264 Out of range value for column 'i' at row 1 +Warning 1264 Out of range value for column 'i0' at row 1 +Warning 1264 Out of range value for column 'i1' at row 1 +Warning 1264 Out of range value for column 'i20' at row 1 +Warning 1264 Out of range value for column 't' at row 1 +Warning 1264 Out of range value for column 't0' at row 1 +Warning 1264 Out of range value for column 't1' at row 1 +Warning 1264 Out of range value for column 't20' at row 1 +Warning 1264 Out of range value for column 's' at row 1 +Warning 1264 Out of range value for column 's0' at row 1 +Warning 1264 Out of range value for column 's1' at row 1 +Warning 1264 Out of range value for column 's20' at row 1 +Warning 1264 Out of range value for column 'm' at row 1 +Warning 1264 Out of range value for column 'm0' at row 1 +Warning 1264 Out of range value for column 'm1' at row 1 +Warning 1264 Out of range value for column 'm20' at row 1 +Warning 1264 Out of range value for column 'i' at row 2 +Warning 1264 Out of range value for column 'i0' at row 2 +Warning 1264 Out of range value for column 'i1' at row 2 +Warning 1264 Out of range value for column 'i20' at row 2 +Warning 1264 Out of range value for column 't' at row 2 +Warning 1264 Out of range value for column 't0' at row 2 +Warning 1264 Out of range value for column 't1' at row 2 +Warning 1264 Out of range value for column 't20' at row 2 +Warning 1264 Out of range value for column 's' at row 2 +Warning 1264 Out of range value for column 's0' at row 2 +Warning 1264 Out of range value for column 's1' at row 2 +Warning 1264 Out of range value for column 's20' at row 2 +Warning 1264 Out of range value for column 'm' at row 2 +Warning 1264 Out of range value for column 'm0' at row 2 +Warning 1264 Out of range value for column 'm1' at row 2 +Warning 1264 Out of range value for column 'm20' at row 2 +Warning 1264 Out of range value for column 'i' at row 3 +Warning 1264 Out of range value for column 'i0' at row 3 +Warning 1264 Out of range value for column 'i1' at row 3 +Warning 1264 Out of range value for column 'i20' at row 3 +Warning 1264 Out of range value for column 't' at row 3 +Warning 1264 Out of range value for column 't0' at row 3 +Warning 1264 Out of range value for column 't1' at row 3 +Warning 1264 Out of range value for column 't20' at row 3 +Warning 1264 Out of range value for column 's' at row 3 +Warning 1264 Out of range value for column 's0' at row 3 +Warning 1264 Out of range value for column 's1' at row 3 +Warning 1264 Out of range value for column 's20' at row 3 +Warning 1264 Out of range value for column 'm' at row 3 +Warning 1264 Out of range value for column 'm0' at row 3 +Warning 1264 Out of range value for column 'm1' at row 3 +Warning 1264 Out of range value for column 'm20' at row 3 SELECT i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20 FROM t1; i i0 i1 i20 t t0 t1 t20 s s0 s1 s20 m m0 m1 m20 b b0 b1 b20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_char.result b/storage/rocksdb/mysql-test/rocksdb/r/type_char.result index 1786dfae1e7..b35b5cb1832 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/type_char.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/type_char.result @@ -29,15 +29,15 @@ Warning 1265 Data truncated for column 'c20' at row 1 Warning 1265 Data truncated for column 'c255' at row 1 INSERT INTO t1 (c,c0,c1,c20,c255) SELECT c255, c255, c255, c255, CONCAT('a',c255,c1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'c' at row 5 -Warning 1265 Data truncated for column 'c0' at row 5 -Warning 1265 Data truncated for column 'c1' at row 5 -Warning 1265 Data truncated for column 'c20' at row 5 -Warning 1265 Data truncated for column 'c' at row 6 -Warning 1265 Data truncated for column 'c0' at row 6 -Warning 1265 Data truncated for column 'c1' at row 6 -Warning 1265 Data truncated for column 'c20' at row 6 -Warning 1265 Data truncated for column 'c255' at row 6 +Warning 1265 Data truncated for column 'c' at row 2 +Warning 1265 Data truncated for column 'c0' at row 2 +Warning 1265 Data truncated for column 'c1' at row 2 +Warning 1265 Data truncated for column 'c20' at row 2 +Warning 1265 Data truncated for column 'c' at row 3 +Warning 1265 Data truncated for column 'c0' at row 3 +Warning 1265 Data truncated for column 'c1' at row 3 +Warning 1265 Data truncated for column 'c20' at row 3 +Warning 1265 Data truncated for column 'c255' at row 3 SELECT c,c0,c1,c20,c255 FROM t1; c c0 c1 c20 c255 diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_int.result b/storage/rocksdb/mysql-test/rocksdb/r/type_int.result index 306042912d0..b949a723f22 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/type_int.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/type_int.result @@ -129,70 +129,70 @@ Warning 1264 Out of range value for column 'b1' at row 1 Warning 1264 Out of range value for column 'b20' at row 1 INSERT INTO t1 (i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20) SELECT b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b FROM t1 WHERE b IN (-9223372036854775808,9223372036854775807,18446744073709551615); Warnings: -Warning 1264 Out of range value for column 'i' at row 8 -Warning 1264 Out of range value for column 'i0' at row 8 -Warning 1264 Out of range value for column 'i1' at row 8 -Warning 1264 Out of range value for column 'i20' at row 8 -Warning 1264 Out of range value for column 't' at row 8 -Warning 1264 Out of range value for column 't0' at row 8 -Warning 1264 Out of range value for column 't1' at row 8 -Warning 1264 Out of range value for column 't20' at row 8 -Warning 1264 Out of range value for column 's' at row 8 -Warning 1264 Out of range value for column 's0' at row 8 -Warning 1264 Out of range value for column 's1' at row 8 -Warning 1264 Out of range value for column 's20' at row 8 -Warning 1264 Out of range value for column 'm' at row 8 -Warning 1264 Out of range value for column 'm0' at row 8 -Warning 1264 Out of range value for column 'm1' at row 8 -Warning 1264 Out of range value for column 'm20' at row 8 -Warning 1264 Out of range value for column 'i' at row 9 -Warning 1264 Out of range value for column 'i0' at row 9 -Warning 1264 Out of range value for column 'i1' at row 9 -Warning 1264 Out of range value for column 'i20' at row 9 -Warning 1264 Out of range value for column 't' at row 9 -Warning 1264 Out of range value for column 't0' at row 9 -Warning 1264 Out of range value for column 't1' at row 9 -Warning 1264 Out of range value for column 't20' at row 9 -Warning 1264 Out of range value for column 's' at row 9 -Warning 1264 Out of range value for column 's0' at row 9 -Warning 1264 Out of range value for column 's1' at row 9 -Warning 1264 Out of range value for column 's20' at row 9 -Warning 1264 Out of range value for column 'm' at row 9 -Warning 1264 Out of range value for column 'm0' at row 9 -Warning 1264 Out of range value for column 'm1' at row 9 -Warning 1264 Out of range value for column 'm20' at row 9 -Warning 1264 Out of range value for column 'i' at row 10 -Warning 1264 Out of range value for column 'i0' at row 10 -Warning 1264 Out of range value for column 'i1' at row 10 -Warning 1264 Out of range value for column 'i20' at row 10 -Warning 1264 Out of range value for column 't' at row 10 -Warning 1264 Out of range value for column 't0' at row 10 -Warning 1264 Out of range value for column 't1' at row 10 -Warning 1264 Out of range value for column 't20' at row 10 -Warning 1264 Out of range value for column 's' at row 10 -Warning 1264 Out of range value for column 's0' at row 10 -Warning 1264 Out of range value for column 's1' at row 10 -Warning 1264 Out of range value for column 's20' at row 10 -Warning 1264 Out of range value for column 'm' at row 10 -Warning 1264 Out of range value for column 'm0' at row 10 -Warning 1264 Out of range value for column 'm1' at row 10 -Warning 1264 Out of range value for column 'm20' at row 10 -Warning 1264 Out of range value for column 'i' at row 11 -Warning 1264 Out of range value for column 'i0' at row 11 -Warning 1264 Out of range value for column 'i1' at row 11 -Warning 1264 Out of range value for column 'i20' at row 11 -Warning 1264 Out of range value for column 't' at row 11 -Warning 1264 Out of range value for column 't0' at row 11 -Warning 1264 Out of range value for column 't1' at row 11 -Warning 1264 Out of range value for column 't20' at row 11 -Warning 1264 Out of range value for column 's' at row 11 -Warning 1264 Out of range value for column 's0' at row 11 -Warning 1264 Out of range value for column 's1' at row 11 -Warning 1264 Out of range value for column 's20' at row 11 -Warning 1264 Out of range value for column 'm' at row 11 -Warning 1264 Out of range value for column 'm0' at row 11 -Warning 1264 Out of range value for column 'm1' at row 11 -Warning 1264 Out of range value for column 'm20' at row 11 +Warning 1264 Out of range value for column 'i' at row 1 +Warning 1264 Out of range value for column 'i0' at row 1 +Warning 1264 Out of range value for column 'i1' at row 1 +Warning 1264 Out of range value for column 'i20' at row 1 +Warning 1264 Out of range value for column 't' at row 1 +Warning 1264 Out of range value for column 't0' at row 1 +Warning 1264 Out of range value for column 't1' at row 1 +Warning 1264 Out of range value for column 't20' at row 1 +Warning 1264 Out of range value for column 's' at row 1 +Warning 1264 Out of range value for column 's0' at row 1 +Warning 1264 Out of range value for column 's1' at row 1 +Warning 1264 Out of range value for column 's20' at row 1 +Warning 1264 Out of range value for column 'm' at row 1 +Warning 1264 Out of range value for column 'm0' at row 1 +Warning 1264 Out of range value for column 'm1' at row 1 +Warning 1264 Out of range value for column 'm20' at row 1 +Warning 1264 Out of range value for column 'i' at row 2 +Warning 1264 Out of range value for column 'i0' at row 2 +Warning 1264 Out of range value for column 'i1' at row 2 +Warning 1264 Out of range value for column 'i20' at row 2 +Warning 1264 Out of range value for column 't' at row 2 +Warning 1264 Out of range value for column 't0' at row 2 +Warning 1264 Out of range value for column 't1' at row 2 +Warning 1264 Out of range value for column 't20' at row 2 +Warning 1264 Out of range value for column 's' at row 2 +Warning 1264 Out of range value for column 's0' at row 2 +Warning 1264 Out of range value for column 's1' at row 2 +Warning 1264 Out of range value for column 's20' at row 2 +Warning 1264 Out of range value for column 'm' at row 2 +Warning 1264 Out of range value for column 'm0' at row 2 +Warning 1264 Out of range value for column 'm1' at row 2 +Warning 1264 Out of range value for column 'm20' at row 2 +Warning 1264 Out of range value for column 'i' at row 3 +Warning 1264 Out of range value for column 'i0' at row 3 +Warning 1264 Out of range value for column 'i1' at row 3 +Warning 1264 Out of range value for column 'i20' at row 3 +Warning 1264 Out of range value for column 't' at row 3 +Warning 1264 Out of range value for column 't0' at row 3 +Warning 1264 Out of range value for column 't1' at row 3 +Warning 1264 Out of range value for column 't20' at row 3 +Warning 1264 Out of range value for column 's' at row 3 +Warning 1264 Out of range value for column 's0' at row 3 +Warning 1264 Out of range value for column 's1' at row 3 +Warning 1264 Out of range value for column 's20' at row 3 +Warning 1264 Out of range value for column 'm' at row 3 +Warning 1264 Out of range value for column 'm0' at row 3 +Warning 1264 Out of range value for column 'm1' at row 3 +Warning 1264 Out of range value for column 'm20' at row 3 +Warning 1264 Out of range value for column 'i' at row 4 +Warning 1264 Out of range value for column 'i0' at row 4 +Warning 1264 Out of range value for column 'i1' at row 4 +Warning 1264 Out of range value for column 'i20' at row 4 +Warning 1264 Out of range value for column 't' at row 4 +Warning 1264 Out of range value for column 't0' at row 4 +Warning 1264 Out of range value for column 't1' at row 4 +Warning 1264 Out of range value for column 't20' at row 4 +Warning 1264 Out of range value for column 's' at row 4 +Warning 1264 Out of range value for column 's0' at row 4 +Warning 1264 Out of range value for column 's1' at row 4 +Warning 1264 Out of range value for column 's20' at row 4 +Warning 1264 Out of range value for column 'm' at row 4 +Warning 1264 Out of range value for column 'm0' at row 4 +Warning 1264 Out of range value for column 'm1' at row 4 +Warning 1264 Out of range value for column 'm20' at row 4 SELECT i,i0,i1,i20,t,t0,t1,t20,s,s0,s1,s20,m,m0,m1,m20,b,b0,b1,b20 FROM t1; i i0 i1 i20 t t0 t1 t20 s s0 s1 s20 m m0 m1 m20 b b0 b1 b20 -2147483648 -2147483648 -2147483648 -2147483648 -128 -128 -128 -128 -32768 -32768 -32768 -32768 -8388608 -8388608 -8388608 -8388608 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808 diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_varbinary.result b/storage/rocksdb/mysql-test/rocksdb/r/type_varbinary.result index 6de8c0331cd..090a9dbb4e2 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/type_varbinary.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/type_varbinary.result @@ -65,13 +65,13 @@ Warning 1265 Data truncated for column 'v64' at row 1 Warning 1265 Data truncated for column 'v65000' at row 1 INSERT INTO t1 (v0,v1,v64,v65000) SELECT v65000, v65000, CONCAT('a',v65000), CONCAT(v65000,v1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'v0' at row 5 -Warning 1265 Data truncated for column 'v1' at row 5 -Warning 1265 Data truncated for column 'v64' at row 5 -Warning 1265 Data truncated for column 'v0' at row 6 -Warning 1265 Data truncated for column 'v1' at row 6 -Warning 1265 Data truncated for column 'v64' at row 6 -Warning 1265 Data truncated for column 'v65000' at row 6 +Warning 1265 Data truncated for column 'v0' at row 2 +Warning 1265 Data truncated for column 'v1' at row 2 +Warning 1265 Data truncated for column 'v64' at row 2 +Warning 1265 Data truncated for column 'v0' at row 3 +Warning 1265 Data truncated for column 'v1' at row 3 +Warning 1265 Data truncated for column 'v64' at row 3 +Warning 1265 Data truncated for column 'v65000' at row 3 SELECT HEX(v0), HEX(v1), HEX(v64), LENGTH(HEX(v65000)) FROM t1; HEX(v0) HEX(v1) HEX(v64) LENGTH(HEX(v65000)) 0 diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result b/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result index a7e086fde66..ec5dc214b80 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result @@ -110,13 +110,13 @@ Warning 1265 Data truncated for column 'v64' at row 1 Warning 1265 Data truncated for column 'v65000' at row 1 INSERT INTO t1 (v0,v1,v64,v65000) SELECT v65000, v65000, CONCAT('a',v65000), CONCAT(v65000,v1) FROM t1; Warnings: -Warning 1265 Data truncated for column 'v0' at row 5 -Warning 1265 Data truncated for column 'v1' at row 5 -Warning 1265 Data truncated for column 'v64' at row 5 -Warning 1265 Data truncated for column 'v65000' at row 5 -Warning 1265 Data truncated for column 'v0' at row 6 -Warning 1265 Data truncated for column 'v1' at row 6 -Warning 1265 Data truncated for column 'v64' at row 6 +Warning 1265 Data truncated for column 'v0' at row 2 +Warning 1265 Data truncated for column 'v1' at row 2 +Warning 1265 Data truncated for column 'v64' at row 2 +Warning 1265 Data truncated for column 'v65000' at row 2 +Warning 1265 Data truncated for column 'v0' at row 3 +Warning 1265 Data truncated for column 'v1' at row 3 +Warning 1265 Data truncated for column 'v64' at row 3 SELECT v0, v1, v64, LENGTH(v65000) FROM t1; v0 v1 v64 LENGTH(v65000) 0 -- cgit v1.2.1 From 96de6bfd5e0d08bd99a47e8a3d60b1c2900a38f8 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 27 Dec 2021 11:53:14 -0700 Subject: MDEV-16091: Seconds_Behind_Master spikes to millions of seconds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: ======== A slave’s relay log format description event is used when calculating Seconds_Behind_Master (SBM). This forces the SBM value to spike when processing these events, as their creation date is set to the timestamp that the IO thread begins. Solution: ======== When the slave generates a format description event, mark the event as a relay log event so it does not update the rli->last_master_timestamp variable. Reviewed By: ============ Andrei Elkin --- .../rpl/r/rpl_seconds_behind_master_spike.result | 41 +++++++++++ .../rpl/t/rpl_seconds_behind_master_spike.test | 86 ++++++++++++++++++++++ sql/log.cc | 1 + sql/slave.cc | 9 +++ 4 files changed, 137 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result create mode 100644 mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test diff --git a/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result new file mode 100644 index 00000000000..d164ea5434f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result @@ -0,0 +1,41 @@ +include/master-slave.inc +[connection master] +connection slave; +include/stop_slave.inc +SET @save_dbug= @@GLOBAL.debug_dbug; +SET @@global.debug_dbug="+d,pause_sql_thread_on_fde"; +include/start_slave.inc +# Future events must be logged at least 2 seconds after +# the slave starts +connection master; +# Write events to ensure slave will be consistent with master +create table t1 (a int); +insert into t1 values (1); +# Flush logs on master forces slave to generate a Format description +# event in its relay log +flush logs; +connection slave; +# Ignore FDEs that happen before the CREATE/INSERT commands +SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; +SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; +SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; +SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; +# On the next FDE, the slave should have the master CREATE/INSERT events +SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; +select count(*)=1 from t1; +count(*)=1 +1 +# The relay log FDE has been processed - here we check to ensure it was +# not considered in Seconds_Behind_Master calculation +connection slave1; +# Safely resume slave SQL thread +SET @@global.debug_dbug=''; +SET DEBUG_SYNC='pause_sql_thread_on_fde CLEAR'; +SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; +SET DEBUG_SYNC='RESET'; +connection master; +DROP TABLE t1; +connection slave; +connection slave; +SET @@global.debug_dbug=$save_dbug; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test new file mode 100644 index 00000000000..36ddbd0dc9f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test @@ -0,0 +1,86 @@ +# +# Purpose: +# This test validates that a slave's relay log format description event is +# not used to calculate the Seconds_Behind_Master time displayed by +# SHOW SLAVE STATUS. +# +# Methodology: +# Ensure that a slave's reported Seconds_Behind_Master does not point before +# a time in which we can prove that it has progressed beyond. The slave's +# relay log events are created using the timestamp at which the IO thread was +# created. Therefore, after starting the slave's IO thread, we sleep so any +# proceeding events are forced to have later timestamps. After sleeping, we run +# MDL statements on the master and save the time at which they are binlogged. +# Once the slave executes these MDL commands, we have proven that the slave has +# caught up to this saved timestamp. At this point, if the value of +# Seconds_Behind_Master points before the time in which the MDL events were +# logged, it is invalid. +# +# References: +# MDEV-16091: Seconds_Behind_Master spikes to millions of seconds +# +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection slave +--source include/stop_slave.inc +SET @save_dbug= @@GLOBAL.debug_dbug; +SET @@global.debug_dbug="+d,pause_sql_thread_on_fde"; +--source include/start_slave.inc + +--let $sleep_time=2 +--echo # Future events must be logged at least $sleep_time seconds after +--echo # the slave starts +--sleep $sleep_time + +--connection master +--echo # Write events to ensure slave will be consistent with master +create table t1 (a int); +insert into t1 values (1); +--let $t_master_events_logged= `SELECT UNIX_TIMESTAMP()` + +--echo # Flush logs on master forces slave to generate a Format description +--echo # event in its relay log +flush logs; + +--connection slave +--echo # Ignore FDEs that happen before the CREATE/INSERT commands +SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; +SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; +SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; +SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; + +--echo # On the next FDE, the slave should have the master CREATE/INSERT events +SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; +select count(*)=1 from t1; + +--echo # The relay log FDE has been processed - here we check to ensure it was +--echo # not considered in Seconds_Behind_Master calculation +--connection slave1 +let $sbm= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1); +--let $t_now= `SELECT UNIX_TIMESTAMP()` + +if(`select $sbm > $t_now - $t_master_events_logged`) +{ + die "A relay log event was incorrectly used to set Seconds_Behind_Master"; +} + +--echo # Safely resume slave SQL thread +SET @@global.debug_dbug=''; +SET DEBUG_SYNC='pause_sql_thread_on_fde CLEAR'; +SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; + +# Reset last sql_thread_continue signal +SET DEBUG_SYNC='RESET'; + +# Cleanup +--connection master +DROP TABLE t1; +--save_master_pos +--sync_slave_with_master + +--connection slave +SET @@global.debug_dbug=$save_dbug; + +--source include/rpl_end.inc diff --git a/sql/log.cc b/sql/log.cc index 895eeec454b..d94f87b90b5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3463,6 +3463,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, opt_slave_sql_verify_checksum ? (enum_binlog_checksum_alg) binlog_checksum_options : BINLOG_CHECKSUM_ALG_OFF; s.checksum_alg= relay_log_checksum_alg; + s.set_relay_log_event(); } else s.checksum_alg= (enum_binlog_checksum_alg)binlog_checksum_options; diff --git a/sql/slave.cc b/sql/slave.cc index 761fdbe807a..2ff1a0490e9 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4033,6 +4033,15 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, #endif /* WITH_WSREP */ thread_safe_increment64(&rli->executed_entries); + DBUG_EXECUTE_IF( + "pause_sql_thread_on_fde", + if (ev && typ == FORMAT_DESCRIPTION_EVENT) { + DBUG_ASSERT(!debug_sync_set_action( + thd, + STRING_WITH_LEN( + "now SIGNAL paused_on_fde WAIT_FOR sql_thread_continue"))); + }); + DBUG_RETURN(exec_res); } mysql_mutex_unlock(&rli->data_lock); -- cgit v1.2.1 From e3b9efb33019971e086eb9ca257d369a5208ccf6 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 6 Jan 2022 18:14:21 +0100 Subject: Fix incompatibility SRCDEF && MEMORY=2 for ODBC JDBC tables --- storage/connect/tabext.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index 698f792b1f4..9e8154cd233 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -142,8 +142,14 @@ bool EXTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Username = GetStringCatInfo(g, "User", NULL); Password = GetStringCatInfo(g, "Password", NULL); - if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) + // Memory was Boolean, it is now integer + if (!(Memory = GetIntCatInfo("Memory", 0))) + Memory = GetBoolCatInfo("Memory", false) ? 1 : 0; + + if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) { Read_Only = true; + if (Memory == 2) Memory = 1; + } // endif Srcdef Qrystr = GetStringCatInfo(g, "Query_String", "?"); Sep = GetStringCatInfo(g, "Separator", NULL); @@ -166,10 +172,6 @@ bool EXTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) if (Catfunc == FNC_TABLE) Tabtyp = GetStringCatInfo(g, "Tabtype", NULL); - // Memory was Boolean, it is now integer - if (!(Memory = GetIntCatInfo("Memory", 0))) - Memory = GetBoolCatInfo("Memory", false) ? 1 : 0; - Pseudo = 2; // FILID is Ok but not ROWID return false; } // end of DefineAM -- cgit v1.2.1 From 28a4836e2b1437e61cce4a7e39272dcd9f845103 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 7 Jan 2022 11:13:34 +0100 Subject: Windows, CI : run mtr in buildbot_suites.bat with --parallel=auto --- mysql-test/collections/buildbot_suites.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/collections/buildbot_suites.bat b/mysql-test/collections/buildbot_suites.bat index 445d81e4fd1..434482abbee 100644 --- a/mysql-test/collections/buildbot_suites.bat +++ b/mysql-test/collections/buildbot_suites.bat @@ -1,4 +1,4 @@ -perl mysql-test-run.pl --verbose-restart --force --suite-timeout=120 --max-test-fail=10 --retry=3 --parallel=4 --suite=^ +perl mysql-test-run.pl --verbose-restart --force --suite-timeout=120 --max-test-fail=10 --retry=3 --parallel=auto --suite=^ vcol,gcol,perfschema,^ main,^ innodb,^ -- cgit v1.2.1 From d821feddac744c97486e662f4c7f6d00119595a0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 7 Jan 2022 13:51:07 +0100 Subject: MDEV-14938 make buildbot to include galera into bintars allow injecting extra files into the bintar --- CMakeLists.txt | 1 + cmake/cpack_tgz.cmake | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 cmake/cpack_tgz.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 67216e0e443..8eadfc20f07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -394,6 +394,7 @@ IF(WITH_UNIT_TESTS) ENDIF() ENDIF() +INCLUDE(cpack_tgz) INCLUDE(cpack_rpm) INCLUDE(cpack_deb) diff --git a/cmake/cpack_tgz.cmake b/cmake/cpack_tgz.cmake new file mode 100644 index 00000000000..7dd9f397189 --- /dev/null +++ b/cmake/cpack_tgz.cmake @@ -0,0 +1,10 @@ +IF(NOT RPM AND NOT DEB) + # + # use -DEXTRA_FILES='/path/to/file=where/to/install;/bin/dd=bin;...' + # + FOREACH(f ${EXTRA_FILES}) + STRING(REGEX REPLACE "=.*$" "" from ${f}) + STRING(REGEX REPLACE "^.*=" "" to ${f}) + INSTALL(PROGRAMS ${from} DESTINATION ${to}) + ENDFOREACH() +ENDIF() -- cgit v1.2.1 From 8d8af31ab0d1eba72c47feaffeb9d3ceb9a94f7b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 7 Jan 2022 20:19:45 +0100 Subject: Windows, CI - workaround hardcoded limits for mtr --parallel=auto --- mysql-test/collections/buildbot_suites.bat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/collections/buildbot_suites.bat b/mysql-test/collections/buildbot_suites.bat index 434482abbee..1dcc912d862 100644 --- a/mysql-test/collections/buildbot_suites.bat +++ b/mysql-test/collections/buildbot_suites.bat @@ -1,4 +1,5 @@ -perl mysql-test-run.pl --verbose-restart --force --suite-timeout=120 --max-test-fail=10 --retry=3 --parallel=auto --suite=^ +if "%MTR_PARALLEL%"=="" set MTR_PARALLEL=%NUMBER_OF_PROCESSORS% +perl mysql-test-run.pl --verbose-restart --force --suite-timeout=120 --max-test-fail=10 --retry=3 --suite=^ vcol,gcol,perfschema,^ main,^ innodb,^ -- cgit v1.2.1 From 3fb3acf58e029203ec04c21a689181d38c50ce82 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sat, 8 Jan 2022 23:16:19 +0100 Subject: Windows, appveyor - use Cygwin's bison again The bug that made build stuck in bison call seems to have disappeared with image update --- appveyor.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e8902eec589..4825518cc76 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,15 +1,5 @@ -init: - # Install bison - - choco feature disable --name showDownloadProgress - - choco install -y winflexbison - - C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe --version - version: build-{build}~branch-{branch} -cache: - - C:\ProgramData\chocolatey\bin -> appveyor.yml - - C:\ProgramData\chocolatey\lib -> appveyor.yml - clone_depth: 1 build_script: @@ -27,7 +17,7 @@ build_script: - set BUILD_TYPE=MinSizeRel - set GENERATOR=-GNinja - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" - - cmake -E time cmake %GENERATOR% .. -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DMYSQL_MAINTAINER_MODE=ERR -DFAST_BUILD=1 -DBISON_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DPLUGIN_PERFSCHEMA=NO -DPLUGIN_FEEDBACK=NO + - cmake -E time cmake %GENERATOR% .. -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DMYSQL_MAINTAINER_MODE=ERR -DFAST_BUILD=1 -DBISON_EXECUTABLE=C:\cygwin64\bin\bison.exe -DPLUGIN_PERFSCHEMA=NO -DPLUGIN_FEEDBACK=NO - set /A jobs=2*%NUMBER_OF_PROCESSORS% - cmake -E time cmake --build . -j %jobs% --config %BUILD_TYPE% --target minbuild -- cgit v1.2.1 From 555a53f10d85198d6e58e599983265b14e0d6797 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sat, 8 Sep 2018 16:18:42 +0100 Subject: Windows : fix broken build with OpenSSL --- include/ssl_compat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ssl_compat.h b/include/ssl_compat.h index 2777ae94527..c94b9671d5f 100644 --- a/include/ssl_compat.h +++ b/include/ssl_compat.h @@ -30,9 +30,9 @@ #define EVP_CIPHER_CTX_SIZE 176 #define EVP_MD_CTX_SIZE 48 #undef EVP_MD_CTX_init -#define EVP_MD_CTX_init(X) do { bzero((X), EVP_MD_CTX_SIZE); EVP_MD_CTX_reset(X); } while(0) +#define EVP_MD_CTX_init(X) do { memset((X), 0, EVP_MD_CTX_SIZE); EVP_MD_CTX_reset(X); } while(0) #undef EVP_CIPHER_CTX_init -#define EVP_CIPHER_CTX_init(X) do { bzero((X), EVP_CIPHER_CTX_SIZE); EVP_CIPHER_CTX_reset(X); } while(0) +#define EVP_CIPHER_CTX_init(X) do { memset((X), 0, EVP_CIPHER_CTX_SIZE); EVP_CIPHER_CTX_reset(X); } while(0) /* Macros below are deprecated. OpenSSL 1.1 may define them or not, -- cgit v1.2.1 From 80d33261ea1a731f228b712b0e763740f87b89be Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sun, 9 Jan 2022 12:39:15 +0100 Subject: Windows, appveyor - use VS2022 --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4825518cc76..650f5ec4dab 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ build_script: - cd _build - set BUILD_TYPE=MinSizeRel - set GENERATOR=-GNinja - - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" + - call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -E time cmake %GENERATOR% .. -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DMYSQL_MAINTAINER_MODE=ERR -DFAST_BUILD=1 -DBISON_EXECUTABLE=C:\cygwin64\bin\bison.exe -DPLUGIN_PERFSCHEMA=NO -DPLUGIN_FEEDBACK=NO - set /A jobs=2*%NUMBER_OF_PROCESSORS% - cmake -E time cmake --build . -j %jobs% --config %BUILD_TYPE% --target minbuild @@ -27,4 +27,4 @@ test_script: - set /A parallel=4*%NUMBER_OF_PROCESSORS% - perl mysql-test-run.pl --force --max-test-fail=10 --retry=2 -parallel=%parallel% --testcase-timeout=4 --suite=main --skip-test-list=unstable-tests --mysqld=--loose-innodb-flush-log-at-trx-commit=2 -image: Visual Studio 2019 +image: Visual Studio 2022 -- cgit v1.2.1 From d6ee351bbb66b023e8c477b039aa469b053f84ad Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 5 Jan 2022 20:23:52 -0800 Subject: Revert "MDEV-24454 Crash at change_item_tree" This patch reverts the fixes of the bugs MDEV-24454 and MDEV-25631 from the commit 3690c549c6e72646ba74f6b4c83813ee4ac3aea4. It leaves the changes in plugin/feedback/feedback.cc and corresponding test files introduced in this commit intact. Proper fixes for the bug MDEV-24454 and MDEV-25631 will follow immediately. --- mysql-test/r/view.result | 43 -------------------- mysql-test/t/view.test | 50 ----------------------- sql/item.cc | 104 ++++++++++++++++------------------------------- sql/item.h | 1 - sql/item_subselect.cc | 3 +- sql/item_sum.cc | 8 ++-- sql/sql_base.cc | 1 - sql/sql_prepare.cc | 2 +- 8 files changed, 39 insertions(+), 173 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 001d26fc466..d278eb1f870 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -6833,49 +6833,6 @@ sum(z) DROP TABLE t1; DROP VIEW v1; # -# MDEV-24454: Crash at change_item_tree -# -CREATE TABLE t1(f0 INT); -CREATE VIEW v1 AS -SELECT -f0 AS f1 -FROM t1; -CREATE VIEW v2 AS -SELECT -(SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ') -FROM v1 n) AS f2, -GROUP_CONCAT('' SEPARATOR ', ') AS f3 -FROM v1; -CREATE VIEW v3 AS -SELECT 1 as f4 FROM v2; -CREATE PROCEDURE p1() -SELECT * FROM v3; -CALL p1(); -f4 -1 -CALL p1(); -f4 -1 -drop procedure p1; -drop view v1,v2,v3; -drop table t1; -# -# MDEV-25631: Crash in st_select_lex::mark_as_dependent with -# VIEW, aggregate and subquery -# -CREATE TABLE t1 (i1 int); -insert into t1 values (1),(2),(3); -CREATE VIEW v1 AS -SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b))); -SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ; -ERROR 21000: Subquery returns more than 1 row -delete from t1 where i1 > 1; -SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ; -1 -1 -drop view v1; -drop table t1; -# # MDEV-26299: Some views force server (and mysqldump) to generate # invalid SQL for their definitions # diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index e6e6ccce8bd..4fb1806fac9 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -6559,56 +6559,6 @@ SELECT sum(z) FROM v1; DROP TABLE t1; DROP VIEW v1; ---echo # ---echo # MDEV-24454: Crash at change_item_tree ---echo # - -CREATE TABLE t1(f0 INT); - -CREATE VIEW v1 AS -SELECT - f0 AS f1 -FROM t1; - -CREATE VIEW v2 AS -SELECT - (SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ') - FROM v1 n) AS f2, - GROUP_CONCAT('' SEPARATOR ', ') AS f3 -FROM v1; - -CREATE VIEW v3 AS -SELECT 1 as f4 FROM v2; - -CREATE PROCEDURE p1() - SELECT * FROM v3; - -CALL p1(); -CALL p1(); - -drop procedure p1; -drop view v1,v2,v3; -drop table t1; - ---echo # ---echo # MDEV-25631: Crash in st_select_lex::mark_as_dependent with ---echo # VIEW, aggregate and subquery ---echo # - -CREATE TABLE t1 (i1 int); -insert into t1 values (1),(2),(3); #not important -CREATE VIEW v1 AS - SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b))); - ---error ER_SUBQUERY_NO_1_ROW -SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ; -delete from t1 where i1 > 1; -SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ; - -drop view v1; -drop table t1; - - --echo # --echo # MDEV-26299: Some views force server (and mysqldump) to generate --echo # invalid SQL for their definitions diff --git a/sql/item.cc b/sql/item.cc index a5b313b786d..2317d54d3e5 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -61,12 +61,11 @@ bool cmp_items(Item *a, Item *b) /** Set max_sum_func_level if it is needed */ -inline void set_max_sum_func_level(SELECT_LEX *select) +inline void set_max_sum_func_level(THD *thd, SELECT_LEX *select) { - LEX *lex_s= select->parent_lex; - if (lex_s->in_sum_func && - lex_s->in_sum_func->nest_level >= select->nest_level) - set_if_bigger(lex_s->in_sum_func->max_sum_func_level, + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= select->nest_level) + set_if_bigger(thd->lex->in_sum_func->max_sum_func_level, select->nest_level - 1); } @@ -781,7 +780,6 @@ Item_ident::Item_ident(THD *thd, Name_resolution_context *context_arg, { name = (char*) field_name_arg; name_length= name ? strlen(name) : 0; - DBUG_ASSERT(!context || context->select_lex); } @@ -796,7 +794,6 @@ Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg, const char *field_name_ar { name = (char*) field_name_arg; name_length= name ? strlen(name) : 0; - DBUG_ASSERT(!context || context->select_lex); } @@ -818,9 +815,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item) cached_table(item->cached_table), depended_from(item->depended_from), can_be_depended(item->can_be_depended) -{ - DBUG_ASSERT(!context || context->select_lex); -} +{} void Item_ident::cleanup() { @@ -5162,14 +5157,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) */ Name_resolution_context *last_checked_context= context; Item **ref= (Item **) not_found_item; - /* - There are cases when name resolution context is absent (when we are not - doing name resolution), but here the name resolution context should - be present because we are doing name resolution - */ - DBUG_ASSERT(context); - SELECT_LEX *current_sel= context->select_lex; - LEX *lex_s= context->select_lex->parent_lex; + SELECT_LEX *current_sel= thd->lex->current_select; Name_resolution_context *outer_context= 0; SELECT_LEX *select= 0; /* Currently derived tables cannot be correlated */ @@ -5270,18 +5258,18 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) return -1; thd->change_item_tree(reference, rf); select->inner_refs_list.push_back(rf, thd->mem_root); - rf->in_sum_func= lex_s->in_sum_func; + rf->in_sum_func= thd->lex->in_sum_func; } /* A reference is resolved to a nest level that's outer or the same as the nest level of the enclosing set function : adjust the value of max_arg_level for the function if it's needed. */ - if (lex_s->in_sum_func && - lex_s->in_sum_func->nest_level >= select->nest_level) + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= select->nest_level) { Item::Type ref_type= (*reference)->type(); - set_if_bigger(lex_s->in_sum_func->max_arg_level, + set_if_bigger(thd->lex->in_sum_func->max_arg_level, select->nest_level); set_field(*from_field); fixed= 1; @@ -5302,10 +5290,10 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? (Item_ident*) (*reference) : 0), false); - if (lex_s->in_sum_func && - lex_s->in_sum_func->nest_level >= select->nest_level) + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= select->nest_level) { - set_if_bigger(lex_s->in_sum_func->max_arg_level, + set_if_bigger(thd->lex->in_sum_func->max_arg_level, select->nest_level); } /* @@ -5397,7 +5385,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) { outer_context->select_lex->inner_refs_list.push_back((Item_outer_ref*)rf, thd->mem_root); - ((Item_outer_ref*)rf)->in_sum_func= lex_s->in_sum_func; + ((Item_outer_ref*)rf)->in_sum_func= thd->lex->in_sum_func; } thd->change_item_tree(reference, rf); /* @@ -5412,7 +5400,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) We can not "move" aggregate function in the place where its arguments are not defined. */ - set_max_sum_func_level(select); + set_max_sum_func_level(thd, select); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, rf, rf, false); @@ -5425,7 +5413,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) We can not "move" aggregate function in the place where its arguments are not defined. */ - set_max_sum_func_level(select); + set_max_sum_func_level(thd, select); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, this, (Item_ident*)*reference, false); @@ -5502,20 +5490,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) DBUG_ASSERT(fixed == 0); Field *from_field= (Field *)not_found_field; bool outer_fixed= false; - SELECT_LEX *select; - LEX *lex_s; - if (context) - { - select= context->select_lex; - lex_s= context->select_lex->parent_lex; - } - else - { - // No real name resolution, used somewhere in SP - DBUG_ASSERT(field); - select= NULL; - lex_s= NULL; - } + SELECT_LEX *select= thd->lex->current_select; if (!field) // If field is not checked { @@ -5576,7 +5551,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) We can not "move" aggregate function in the place where its arguments are not defined. */ - set_max_sum_func_level(select); + set_max_sum_func_level(thd, select); set_field(new_field); depended_from= (*((Item_field**)res))->depended_from; return 0; @@ -5605,7 +5580,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) We can not "move" aggregate function in the place where its arguments are not defined. */ - set_max_sum_func_level(select); + set_max_sum_func_level(thd, select); return FALSE; } } @@ -5642,11 +5617,10 @@ bool Item_field::fix_fields(THD *thd, Item **reference) goto mark_non_agg_field; } - if (lex_s && - lex_s->in_sum_func && - lex_s->in_sum_func->nest_level == + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level == select->nest_level) - set_if_bigger(lex_s->in_sum_func->max_arg_level, + set_if_bigger(thd->lex->in_sum_func->max_arg_level, select->nest_level); /* if it is not expression from merged VIEW we will set this field. @@ -5712,9 +5686,8 @@ bool Item_field::fix_fields(THD *thd, Item **reference) if (field->vcol_info) fix_session_vcol_expr_for_read(thd, field, field->vcol_info); if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && - !outer_fixed && + !outer_fixed && !thd->lex->in_sum_func && select && - !lex_s->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS && select->join) { @@ -5749,13 +5722,13 @@ mark_non_agg_field: */ select_lex= context->select_lex; } - if (!lex_s || !lex_s->in_sum_func) + if (!thd->lex->in_sum_func) select_lex->set_non_agg_field_used(true); else { if (outer_fixed) - lex_s->in_sum_func->outer_fields.push_back(this, thd->mem_root); - else if (lex_s->in_sum_func->nest_level != + thd->lex->in_sum_func->outer_fields.push_back(this, thd->mem_root); + else if (thd->lex->in_sum_func->nest_level != select->nest_level) select_lex->set_non_agg_field_used(true); } @@ -7248,12 +7221,6 @@ Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel) return NULL; } -Item *Item_ident::derived_field_transformer_for_having(THD *thd, uchar *arg) -{ - st_select_lex *sel= (st_select_lex *)arg; - context= &sel->context; - return this; -} Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg) { @@ -7273,13 +7240,12 @@ Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg) Item *Item_direct_view_ref::derived_field_transformer_for_having(THD *thd, uchar *arg) { - st_select_lex *sel= (st_select_lex *)arg; - context= &sel->context; if ((*ref)->marker & SUBSTITUTION_FL) { this->marker|= SUBSTITUTION_FL; return this; } + st_select_lex *sel= (st_select_lex *)arg; table_map tab_map= sel->master_unit()->derived->table->map; if ((item_equal && !(item_equal->used_tables() & tab_map)) || !item_equal) @@ -7575,9 +7541,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) { enum_parsing_place place= NO_MATTER; DBUG_ASSERT(fixed == 0); - - SELECT_LEX *current_sel= context->select_lex; - LEX *lex_s= context->select_lex->parent_lex; + SELECT_LEX *current_sel= thd->lex->current_select; if (set_properties_only) { @@ -7738,10 +7702,10 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) the nest level of the enclosing set function : adjust the value of max_arg_level for the function if it's needed. */ - if (lex_s->in_sum_func && - lex_s->in_sum_func->nest_level >= + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= last_checked_context->select_lex->nest_level) - set_if_bigger(lex_s->in_sum_func->max_arg_level, + set_if_bigger(thd->lex->in_sum_func->max_arg_level, last_checked_context->select_lex->nest_level); return FALSE; } @@ -7761,10 +7725,10 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) the nest level of the enclosing set function : adjust the value of max_arg_level for the function if it's needed. */ - if (lex_s->in_sum_func && - lex_s->in_sum_func->nest_level >= + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= last_checked_context->select_lex->nest_level) - set_if_bigger(lex_s->in_sum_func->max_arg_level, + set_if_bigger(thd->lex->in_sum_func->max_arg_level, last_checked_context->select_lex->nest_level); } } diff --git a/sql/item.h b/sql/item.h index 997352ef27a..086d85e989f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2630,7 +2630,6 @@ public: Collect outer references */ virtual bool collect_outer_ref_processor(void *arg); - Item *derived_field_transformer_for_having(THD *thd, uchar *arg); friend bool insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, const char *table_name, List_iterator *it, diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3f9a760ce09..25621dfe104 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -5190,9 +5190,8 @@ bool subselect_hash_sj_engine::make_semi_join_conds() NULL, TL_READ); tmp_table_ref->table= tmp_table; - context= new (thd->mem_root) Name_resolution_context; + context= new Name_resolution_context; context->init(); - context->select_lex= item_in->unit->first_select(); context->first_name_resolution_table= context->last_name_resolution_table= tmp_table_ref; semi_join_conds_context= context; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f20be3b5226..dd65f04a652 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -68,7 +68,6 @@ size_t Item_sum::ram_limitation(THD *thd) bool Item_sum::init_sum_func_check(THD *thd) { SELECT_LEX *curr_sel= thd->lex->current_select; - LEX *lex_s= (curr_sel ? curr_sel->parent_lex : thd->lex); if (curr_sel && !curr_sel->name_visibility_map) { for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select()) @@ -83,9 +82,9 @@ bool Item_sum::init_sum_func_check(THD *thd) return TRUE; } /* Set a reference to the nesting set function if there is any */ - in_sum_func= lex_s->in_sum_func; + in_sum_func= thd->lex->in_sum_func; /* Save a pointer to object to be used in items for nested set functions */ - lex_s->in_sum_func= this; + thd->lex->in_sum_func= this; nest_level= thd->lex->current_select->nest_level; ref_by= 0; aggr_level= -1; @@ -152,7 +151,6 @@ bool Item_sum::init_sum_func_check(THD *thd) bool Item_sum::check_sum_func(THD *thd, Item **ref) { SELECT_LEX *curr_sel= thd->lex->current_select; - LEX *lex_s= curr_sel->parent_lex; nesting_map allow_sum_func= (thd->lex->allow_sum_func & curr_sel->name_visibility_map); bool invalid= FALSE; @@ -312,7 +310,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) } aggr_sel->set_agg_func_used(true); update_used_tables(); - lex_s->in_sum_func= in_sum_func; + thd->lex->in_sum_func= in_sum_func; return FALSE; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5173df260d5..9a66b27a454 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6440,7 +6440,6 @@ set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref) if (!(context= new (thd->mem_root) Name_resolution_context)) return TRUE; context->init(); - context->select_lex= table_ref->select_lex; context->first_name_resolution_table= context->last_name_resolution_table= table_ref; item->context= context; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index bb1a99d9eef..64e4cd30561 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3060,7 +3060,6 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) } for (; sl; sl= sl->next_select_in_list()) { - sl->parent_lex->in_sum_func= NULL; if (sl->changed_elements & TOUCHED_SEL_COND) { /* remove option which was put by mysql_explain_union() */ @@ -3191,6 +3190,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) lex->result->set_thd(thd); } lex->allow_sum_func= 0; + lex->in_sum_func= NULL; DBUG_VOID_RETURN; } -- cgit v1.2.1 From 6dec0332fbdb6ca58c46284c7139735f137e2a81 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 5 Jan 2022 22:36:20 -0800 Subject: MDEV-25086 Stored Procedure Crashes Server The cause of this bug is the same as of the bug MDEV-24454. This bug manifested itself at the second execution of the queries that contained a set function whose only argument was outer reference to a column of a mergeable view or derived table or CTE. The first execution of such query worked fine, but the second execution of the query caused a crash of the server because the aggregation select for the used set function was determined incorrectly at the name resolution phase of the second execution. --- mysql-test/r/derived_view.result | 130 +++++++++++++++++++++++++++++++++++++++ mysql-test/t/derived_view.test | 111 +++++++++++++++++++++++++++++++++ sql/item.cc | 3 +- 3 files changed, 243 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index d8ee508f5db..0c045e39271 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -3456,4 +3456,134 @@ a 3 drop view v1; drop table t1; +# +# MDEV-24454 Second execution of SELECT containing set function +# MDEV-25086: whose only argument is an outer reference to a column +# of mergeable view/derived/table/CTE +# +create table t1 (a int); +create table t2 (b int); +insert into t1 values (3), (1), (3); +insert into t2 values (70), (30), (70); +create view v1 as select * from t2; +prepare stmt from " +select (select sum(b) from t1 where a=1) as r from v1; +"; +execute stmt; +r +170 +execute stmt; +r +170 +deallocate prepare stmt; +prepare stmt from " +select (select sum(b) from t1 where a=1) as r from (select * from t2) dt; +"; +execute stmt; +r +170 +execute stmt; +r +170 +deallocate prepare stmt; +prepare stmt from " +with cte as (select * from t2) +select (select sum(b) from t1 where a=1) as r from cte; +"; +execute stmt; +r +170 +execute stmt; +r +170 +deallocate prepare stmt; +prepare stmt from " +select (select sum(b) from t1 where a=1) as r +from (select * from v1 where b > 50) dt; +"; +execute stmt; +r +140 +execute stmt; +r +140 +deallocate prepare stmt; +prepare stmt from " +select (select sum(b) from t1 where a=1) as r +from (select * from (select * from t2) dt1 where b > 50) dt; +"; +execute stmt; +r +140 +execute stmt; +r +140 +deallocate prepare stmt; +prepare stmt from " +with cte as (select * from (select * from t2) dt1 where b > 50) +select (select sum(b) from t1 where a=1) as r from cte; +"; +execute stmt; +r +140 +execute stmt; +r +140 +deallocate prepare stmt; +create procedure sp1() +begin +select (select sum(b) from t1 where a=1) as r from v1; +end | +call sp1(); +r +170 +call sp1(); +r +170 +drop procedure sp1; +create procedure sp1() +begin +select (select sum(b) from t1 where a=1) as r from (select * from t2) dt; +end | +call sp1(); +r +170 +call sp1(); +r +170 +drop procedure sp1; +create procedure sp1() +begin +with cte as (select * from t2) +select (select sum(b) from t1 where a=1) as r from cte; +end | +call sp1(); +r +170 +call sp1(); +r +170 +drop procedure sp1; +drop view v1; +drop table t1,t2; +CREATE TABLE t1(f0 INT); +INSERT INTO t1 VALUES (3); +CREATE VIEW v1 AS SELECT f0 AS f1 FROM t1; +CREATE VIEW v2 AS +SELECT +(SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ') FROM v1 n) AS f2, +GROUP_CONCAT('aa' SEPARATOR ', ') AS f3 +FROM v1; +CREATE VIEW v3 AS SELECT * FROM v2; +CREATE PROCEDURE p1() +SELECT * FROM v3; +CALL p1(); +f2 f3 +3 aa +CALL p1(); +f2 f3 +3 aa +DROP PROCEDURE p1; +DROP VIEW v1,v2,v3; +DROP TABLE t1; # End of 10.2 tests diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index 89ada40e84c..0f3d9b224ba 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -2265,4 +2265,115 @@ select * from ((select a from t1 limit 2) order by a desc) dt; drop view v1; drop table t1; +--echo # +--echo # MDEV-24454 Second execution of SELECT containing set function +--echo # MDEV-25086: whose only argument is an outer reference to a column +--echo # of mergeable view/derived/table/CTE +--echo # + +create table t1 (a int); +create table t2 (b int); +insert into t1 values (3), (1), (3); +insert into t2 values (70), (30), (70); +create view v1 as select * from t2; + +prepare stmt from " +select (select sum(b) from t1 where a=1) as r from v1; +"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +prepare stmt from " +select (select sum(b) from t1 where a=1) as r from (select * from t2) dt; +"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +prepare stmt from " +with cte as (select * from t2) +select (select sum(b) from t1 where a=1) as r from cte; +"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +prepare stmt from " +select (select sum(b) from t1 where a=1) as r +from (select * from v1 where b > 50) dt; +"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +prepare stmt from " +select (select sum(b) from t1 where a=1) as r +from (select * from (select * from t2) dt1 where b > 50) dt; +"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +prepare stmt from " +with cte as (select * from (select * from t2) dt1 where b > 50) +select (select sum(b) from t1 where a=1) as r from cte; +"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +--delimiter | +create procedure sp1() +begin +select (select sum(b) from t1 where a=1) as r from v1; +end | +--delimiter ; +call sp1(); +call sp1(); +drop procedure sp1; + +--delimiter | +create procedure sp1() +begin +select (select sum(b) from t1 where a=1) as r from (select * from t2) dt; +end | +--delimiter ; +call sp1(); +call sp1(); +drop procedure sp1; + +--delimiter | +create procedure sp1() +begin +with cte as (select * from t2) +select (select sum(b) from t1 where a=1) as r from cte; +end | +--delimiter ; +call sp1(); +call sp1(); +drop procedure sp1; + +drop view v1; +drop table t1,t2; + +CREATE TABLE t1(f0 INT); +INSERT INTO t1 VALUES (3); +CREATE VIEW v1 AS SELECT f0 AS f1 FROM t1; +CREATE VIEW v2 AS +SELECT + (SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ') FROM v1 n) AS f2, + GROUP_CONCAT('aa' SEPARATOR ', ') AS f3 +FROM v1; +CREATE VIEW v3 AS SELECT * FROM v2; + +CREATE PROCEDURE p1() + SELECT * FROM v3; +CALL p1(); +CALL p1(); + +DROP PROCEDURE p1; +DROP VIEW v1,v2,v3; +DROP TABLE t1; + --echo # End of 10.2 tests diff --git a/sql/item.cc b/sql/item.cc index 2317d54d3e5..32bcd282401 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5617,7 +5617,8 @@ bool Item_field::fix_fields(THD *thd, Item **reference) goto mark_non_agg_field; } - if (thd->lex->in_sum_func && + if (!thd->lex->current_select->no_wrap_view_item && + thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level == select->nest_level) set_if_bigger(thd->lex->in_sum_func->max_arg_level, -- cgit v1.2.1 From 7692cec5b0811c09f09b1f6215fc07163ad0db3a Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 6 Jan 2022 00:31:42 -0800 Subject: MDEV-25631 Crash executing query with VIEW, aggregate and subquery This bug could cause a crash of the server for queries with a derived table whose specification contained the set function using a subquery over a view as its only argument. The crash could happen if the specification of the view contained an outer reference. In this case the aggregation select could be determined incorrectly. The crash also could be observed if a CTE is used instead of the view, but only for queries having at least two references to the CTE. --- mysql-test/r/view.result | 18 ++++++++++++++++++ mysql-test/t/view.test | 20 ++++++++++++++++++++ sql/item.cc | 5 +++++ 3 files changed, 43 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index d278eb1f870..4edbabf11cc 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -6844,5 +6844,23 @@ drop view v1; CREATE VIEW v1 AS select `t1`.`12345678901234567890123456789012345678901234567890123456789012345` AS `Name_exp_1` from (select '12345678901234567890123456789012345678901234567890123456789012345') `t1`; drop view v1; # +# MDEV-25631: view with outer reference in select used +# as argument of set function +# +create table t1 (c int); +insert into t1 values (1); +create view v1 as select c from t1 where (select t1.c from t1 t) = 1; +select * from (select sum((select * from v1)) as r) dt; +r +1 +with cte as (select c from t1 where (select t1.c from t1 t) = 1) +select * from (select sum((select * from cte)) as r) dt1 +union +select * from (select sum((select * from cte)) as r) dt2; +r +1 +drop view v1; +drop table t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 4fb1806fac9..6265a514783 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -6575,8 +6575,28 @@ drop view v1; eval CREATE VIEW v1 AS $definition; + drop view v1; +--echo # +--echo # MDEV-25631: view with outer reference in select used +--echo # as argument of set function +--echo # + +create table t1 (c int); +insert into t1 values (1); +create view v1 as select c from t1 where (select t1.c from t1 t) = 1; + +select * from (select sum((select * from v1)) as r) dt; + +with cte as (select c from t1 where (select t1.c from t1 t) = 1) +select * from (select sum((select * from cte)) as r) dt1 +union +select * from (select sum((select * from cte)) as r) dt2; + +drop view v1; +drop table t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 32bcd282401..6e5d2ee45a2 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5266,6 +5266,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) max_arg_level for the function if it's needed. */ if (thd->lex->in_sum_func && + thd->lex == context->select_lex->parent_lex && thd->lex->in_sum_func->nest_level >= select->nest_level) { Item::Type ref_type= (*reference)->type(); @@ -5291,6 +5292,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) (Item_ident*) (*reference) : 0), false); if (thd->lex->in_sum_func && + thd->lex == context->select_lex->parent_lex && thd->lex->in_sum_func->nest_level >= select->nest_level) { set_if_bigger(thd->lex->in_sum_func->max_arg_level, @@ -5619,6 +5621,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) if (!thd->lex->current_select->no_wrap_view_item && thd->lex->in_sum_func && + thd->lex == select->parent_lex && thd->lex->in_sum_func->nest_level == select->nest_level) set_if_bigger(thd->lex->in_sum_func->max_arg_level, @@ -7704,6 +7707,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) max_arg_level for the function if it's needed. */ if (thd->lex->in_sum_func && + thd->lex == context->select_lex->parent_lex && thd->lex->in_sum_func->nest_level >= last_checked_context->select_lex->nest_level) set_if_bigger(thd->lex->in_sum_func->max_arg_level, @@ -7727,6 +7731,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) max_arg_level for the function if it's needed. */ if (thd->lex->in_sum_func && + thd->lex == context->select_lex->parent_lex && thd->lex->in_sum_func->nest_level >= last_checked_context->select_lex->nest_level) set_if_bigger(thd->lex->in_sum_func->max_arg_level, -- cgit v1.2.1 From 89c870b2b4b0003c592887253d165b10569749a3 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Tue, 11 Jan 2022 11:50:29 +0700 Subject: MDEV-20325: Assertion `outer_context || !*from_field || *from_field == not_found_field' failed in Item_field::fix_outer_field | `!derived->is_excluded()' failed in TABLE_LIST::set_check_materialized | SIGEGV in st_select_lex::mark_as_dependent (optimized builds) Re-execution of a query containing subquery in the FROM clause results in assert failure in case the query is run as part of a stored routine or as a prepared statement AND derived table merge optimization is off. As an example, the following test case CREATE TABLE t1 (a INT) ; CREATE PROCEDURE sp() SELECT * FROM (SELECT a FROM t1) tb; CALL sp(); SET optimizer_switch='derived_merge=off'; CALL sp(); results in assert failure on the second invocation of the 'sp' stored routine. The reason for assertion failure is that the expression derived->is_excluded() returns the value true where the value false expected. The method is_excluded() returns the value true for a derived table that has been merged to a parent select. Such transformation happens as part of Derived Table Merge Optimization that is performed on first invocation of a stored routine or a prepared statement containing a query with subquery in the FROM clause of the main SELECT. When the same routine or prepared statement is run the second time and Derived Table Merge Optimization is OFF the MariaDB server tries to materialize a derived table specified by the subquery that fails since this subquery has already been merged to the top-most SELECT. This transformation is permanent and can't be reverted. That is the reason why the assert DBUG_ASSERT(!derived->is_excluded()); fails inside the function TABLE_LIST::set_check_materialized(). Similar behaviour can be observed in case a stored routine or prepared statement containing a SELECT statement with subquery in the FROM clause, first is run with the optimizer_switch option set to derived_merge=off and re-run after this option has been switched to derived_merge=on. In this case a derived table for subquery is materialized on the first execution and marked as merged derived table on the second execution that results in error with misleading error message: MariaDB [test]> CALL sp1(); ERROR 1030 (HY000): Got error 1 "Operation not permitted" from storage engine MEMORY To fix the issue, a derived table that has been already optimized shouldn't be re-marked for one more round of optimization. One significant consequence following from suggested change is that the data member TABLE_LIST::derived_type is not updated once the table optimization has been done. This fact should be taken into account when Prepared Statement being handled since once a table listed in a query has been optimized on execution of the statement PREPARE FROM it won't be touched anymore on handling the statement EXECUTE. One side effect caused by this change could be observed for the following test case: CREATE TABLE t1 (s1 INT); CREATE VIEW v1 AS SELECT s1,s2 FROM (SELECT s1 as s2 FROM t1 WHERE s1 <100) x, t1 WHERE t1.s1=x.s2; INSERT INTO v1 (s1) VALUES (-300); PREPARE stmt FROM "INSERT INTO v1 (s1) VALUES (-300)"; EXECUTE stmt; Execution of the above EXECUTE statement results in issuing the error ER_COLUMNACCESS_DENIED_ERROR since table_ref->is_merged_derived() is false and check_column_grant_in_table_ref() called for a temporary table that shouldn't be. To fix this issue the function find_field_in_tables has been modified in such a way that the function check_column_grant_in_table_ref() is not called for a temporary table. --- mysql-test/r/derived.result | 53 +++++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/derived.test | 51 +++++++++++++++++++++++++++++++++++++++++++ sql/sql_base.cc | 2 +- sql/table.cc | 24 ++++++++++++++++++-- 4 files changed, 127 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 2106ba504a9..5085feaaedc 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -1204,5 +1204,58 @@ REPLACE INTO v2 ( SELECT * FROM v4 ) UNION ( SELECT f FROM v2 ); drop view v1,v2,v3,v4; drop table t1,t2,t3; # +# MDEV-20325: Assertion `outer_context || !*from_field || *from_field == not_found_field' failed in Item_field::fix_outer_field | `!derived->is_excluded()' failed in TABLE_LIST::set_check_materialized | SIGEGV in st_select_lex::mark_as_dependent (optimized builds) +# +CREATE TABLE t1 (a INT); +# Check that re-execution of a stored routine containing +# a query with subquery in the FROM clause doesn't result in +# assert failure in case the 'derived_merge' optimizer option +# has been turned on/off +CREATE PROCEDURE sp() SELECT * FROM (SELECT a FROM t1) tb; +CALL sp(); +a +SET optimizer_switch='derived_merge=off'; +# Without the patch the following statement would result in assert +# failure +CALL sp(); +a +# Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=on'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +a +SET optimizer_switch='derived_merge=off'; +# Without the patch the following statement would result in assert +# failure +EXECUTE stmt; +a +DEALLOCATE PREPARE stmt; +# Here check the reverse test case - first turn off the 'derived_merge' +# optimizer option, run the stored routine containing a query with +# subquery in the FROM clause, then turn on the 'derived_merge' +# optimizer option and re-execute the same stored routine to check that +# the routine is finished successfully. +CREATE PROCEDURE sp1() SELECT * FROM (SELECT a FROM t1) tb; +SET optimizer_switch='derived_merge=off'; +CALL sp1(); +a +SET optimizer_switch='derived_merge=on'; +CALL sp1(); +a +# Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=off'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +a +SET optimizer_switch='derived_merge=on'; +# Without the patch the following statement would result in assert +# failure +EXECUTE stmt; +a +DEALLOCATE PREPARE stmt; +DROP PROCEDURE sp; +DROP PROCEDURE sp1; +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 6d9d5e23cf9..c8e6681e80b 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -1036,6 +1036,57 @@ REPLACE INTO v2 ( SELECT * FROM v4 ) UNION ( SELECT f FROM v2 ); drop view v1,v2,v3,v4; drop table t1,t2,t3; +--echo # +--echo # MDEV-20325: Assertion `outer_context || !*from_field || *from_field == not_found_field' failed in Item_field::fix_outer_field | `!derived->is_excluded()' failed in TABLE_LIST::set_check_materialized | SIGEGV in st_select_lex::mark_as_dependent (optimized builds) +--echo # +CREATE TABLE t1 (a INT); + +--echo # Check that re-execution of a stored routine containing +--echo # a query with subquery in the FROM clause doesn't result in +--echo # assert failure in case the 'derived_merge' optimizer option +--echo # has been turned on/off +CREATE PROCEDURE sp() SELECT * FROM (SELECT a FROM t1) tb; +CALL sp(); +SET optimizer_switch='derived_merge=off'; +--echo # Without the patch the following statement would result in assert +--echo # failure +CALL sp(); + +--echo # Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=on'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +SET optimizer_switch='derived_merge=off'; +--echo # Without the patch the following statement would result in assert +--echo # failure +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +--echo # Here check the reverse test case - first turn off the 'derived_merge' +--echo # optimizer option, run the stored routine containing a query with +--echo # subquery in the FROM clause, then turn on the 'derived_merge' +--echo # optimizer option and re-execute the same stored routine to check that +--echo # the routine is finished successfully. +CREATE PROCEDURE sp1() SELECT * FROM (SELECT a FROM t1) tb; +SET optimizer_switch='derived_merge=off'; +CALL sp1(); +SET optimizer_switch='derived_merge=on'; +CALL sp1(); + +--echo # Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=off'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +SET optimizer_switch='derived_merge=on'; +--echo # Without the patch the following statement would result in assert +--echo # failure +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +DROP PROCEDURE sp; +DROP PROCEDURE sp1; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9a66b27a454..5345fdbecd0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5980,7 +5980,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TRUE, &(item->cached_field_index)); #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check if there are sufficient access rights to the found field. */ - if (found && check_privileges && + if (found && check_privileges && !is_temporary_table(table_ref) && check_column_grant_in_table_ref(thd, table_ref, name, length)) found= WRONG_GRANT; #endif diff --git a/sql/table.cc b/sql/table.cc index d4f8170e0af..ca6ce02e4f2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8231,6 +8231,24 @@ void TABLE_LIST::wrap_into_nested_join(List &join_list) } +/** + Check whether optimization has been performed and a derived table either + been merged to upper select level or materialized. + + @param table a TABLE_LIST object containing a derived table + + @return true in case the derived table has been merged to surrounding select, + false otherwise +*/ + +static inline bool derived_table_optimization_done(TABLE_LIST *table) +{ + return table->derived && + (table->derived->is_excluded() || + table->is_materialized_derived()); +} + + /** @brief Initialize this derived table/view @@ -8267,13 +8285,15 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) set_multitable(); unit->derived= this; - if (init_view && !view) + if (init_view && !view && + !derived_table_optimization_done(this)) { /* This is all what we can do for a derived table for now. */ set_derived(); } - if (!is_view()) + if (!is_view() && + !derived_table_optimization_done(this)) { /* A subquery might be forced to be materialized due to a side-effect. */ if (!is_materialized_derived() && first_select->is_mergeable() && -- cgit v1.2.1 From d0ca2415242502181ed18c49d83675f17957ce3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 27 Dec 2021 10:22:28 +0200 Subject: MDEV-25472 : Server crashes when wsrep_cluster_address set to unkown address and wsrep_slave_threads to 0 Return failure if we are not connected when slave threads are set --- sql/wsrep_thd.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index ae797c4c712..eecda830023 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -587,9 +587,8 @@ bool wsrep_create_appliers(long threads, bool thread_count_lock) { WSREP_ERROR("Trying to launch slave threads before creating " "connection at '%s'", wsrep_cluster_address); - assert(0); } - return false; + return true; } long wsrep_threads= 0; -- cgit v1.2.1 From c430f612ebf93e0cd2cdcbeaccb3ff06254eb77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 4 Jan 2022 08:20:02 +0200 Subject: MDEV-25856 : SIGSEGV in ha_myisammrg::append_create_info For MERGE-tables we need to init children list before calling show_create_table and then detach children before we continue normal mysql_create_like_table execution. --- .../suite/galera/r/galera_create_table_like.result | 5 +++++ .../suite/galera/t/galera_create_table_like.test | 9 ++++++++ sql/wsrep_mysqld.cc | 25 +++++++++++----------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_create_table_like.result b/mysql-test/suite/galera/r/galera_create_table_like.result index 131ac311bca..128931381d4 100644 --- a/mysql-test/suite/galera/r/galera_create_table_like.result +++ b/mysql-test/suite/galera/r/galera_create_table_like.result @@ -47,3 +47,8 @@ DROP TABLE schema2.real_table2; DROP TABLE schema2.real_table3; DROP SCHEMA schema1; DROP SCHEMA schema2; +use test; +CREATE TEMPORARY TABLE t (c INT) ENGINE=mrg_myisam UNION=(t,t2) insert_method=FIRST; +CREATE TABLE t2 LIKE t; +ERROR HY000: Table 't' is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t; diff --git a/mysql-test/suite/galera/t/galera_create_table_like.test b/mysql-test/suite/galera/t/galera_create_table_like.test index 0e0e8b0ffcf..3cf51521be1 100644 --- a/mysql-test/suite/galera/t/galera_create_table_like.test +++ b/mysql-test/suite/galera/t/galera_create_table_like.test @@ -48,3 +48,12 @@ DROP TABLE schema2.real_table3; DROP SCHEMA schema1; DROP SCHEMA schema2; + +# +# MDEV-25856: SIGSEGV in ha_myisammrg::append_create_info +# +use test; +CREATE TEMPORARY TABLE t (c INT) ENGINE=mrg_myisam UNION=(t,t2) insert_method=FIRST; +--error 1472 +CREATE TABLE t2 LIKE t; +DROP TABLE t; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 4a99f781fdd..b34f6803479 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2876,7 +2876,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, if (create_info->tmp_table()) { /* CREATE TEMPORARY TABLE LIKE must be skipped from replication */ - WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s", + WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s", thd->query()); } else if (!(thd->find_temporary_table(src_table))) @@ -2886,21 +2886,17 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, } else { - /* here we have CREATE TABLE LIKE - the temporary table definition will be needed in slaves to - enable the create to succeed - */ - TABLE_LIST tbl; - bzero((void*) &tbl, sizeof(tbl)); - tbl.db= src_table->db; - tbl.table_name= tbl.alias= src_table->table_name; - tbl.table= src_table->table; + /* Non-MERGE tables ignore this call. */ + if (src_table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST)) + return (true); + char buf[2048]; String query(buf, sizeof(buf), system_charset_info); query.length(0); // Have to zero it since constructor doesn't - (void) show_create_table(thd, &tbl, &query, NULL, WITH_DB_NAME); - WSREP_DEBUG("TMP TABLE: %s", query.ptr()); + int result __attribute__((unused))= + show_create_table(thd, src_table, &query, NULL, WITH_DB_NAME); + WSREP_DEBUG("TMP TABLE: %s ret_code %d", query.ptr(), result); thd->wsrep_TOI_pre_query= query.ptr(); thd->wsrep_TOI_pre_query_len= query.length(); @@ -2909,11 +2905,14 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, thd->wsrep_TOI_pre_query= NULL; thd->wsrep_TOI_pre_query_len= 0; + + /* Non-MERGE tables ignore this call. */ + src_table->table->file->extra(HA_EXTRA_DETACH_CHILDREN); } return(false); -WSREP_ERROR_LABEL: +wsrep_error_label: thd->wsrep_TOI_pre_query= NULL; return (true); } -- cgit v1.2.1 From ce415be29426024474f218bcd9f4be7e45abcf01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 4 Jan 2022 12:01:31 +0200 Subject: MDEV-25549 : Assertion `*new_engine' failed in bool check_engine(THD*, const char*, const char*, HA_CREATE_INFO*) In Galera case we call check_engine that could set create_info->db_type to NULL e.g. if TEMPORARY is not supported by storage engine. Thus, we need to restore it after that call because it is needed later on mysql_create_table that will also call check_engine. --- sql/sql_table.cc | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9556cb9f136..33daa15b9b7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2020, MariaDB + Copyright (c) 2010, 2022, 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 @@ -11036,14 +11036,23 @@ bool Sql_cmd_create_table::execute(THD *thd) tables, like mysql replication does. Also check if the requested engine is allowed/supported. */ - if (WSREP(thd) && - !check_engine(thd, create_table->db, create_table->table_name, - &create_info) && - (!thd->is_current_stmt_binlog_format_row() || - !create_info.tmp_table())) +#ifdef WITH_WSREP + if (WSREP(thd)) { - WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, NULL) + handlerton *orig_ht= create_info.db_type; + if (!check_engine(thd, create_table->db, create_table->table_name, + &create_info) && + (!thd->is_current_stmt_binlog_format_row() || + !create_info.tmp_table())) + { + WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, NULL) + } + // check_engine will set db_type to NULL if e.g. TEMPORARY is + // not supported by the storage engine, this case is checked + // again in mysql_create_table + create_info.db_type= orig_ht; } +#endif /* WITH_WSREP */ /* Regular CREATE TABLE */ res= mysql_create_table(thd, create_table, &create_info, &alter_info); } -- cgit v1.2.1 From e32c21cb93617e082c4669701237199b8718155f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 7 Jan 2022 12:24:19 +0200 Subject: Changing wsrep_slave_threads parameter requires that cluster is connected so moved test here. --- .../galera/r/wsrep_slave_threads_basic.result | 49 ++++++++++++++++++++++ .../suite/galera/t/wsrep_slave_threads_basic.test | 43 +++++++++++++++++++ .../sys_vars/r/wsrep_slave_threads_basic.result | 49 ---------------------- .../sys_vars/t/wsrep_slave_threads_basic.test | 43 ------------------- 4 files changed, 92 insertions(+), 92 deletions(-) create mode 100644 mysql-test/suite/galera/r/wsrep_slave_threads_basic.result create mode 100644 mysql-test/suite/galera/t/wsrep_slave_threads_basic.test delete mode 100644 mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result delete mode 100644 mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test diff --git a/mysql-test/suite/galera/r/wsrep_slave_threads_basic.result b/mysql-test/suite/galera/r/wsrep_slave_threads_basic.result new file mode 100644 index 00000000000..62be5a42416 --- /dev/null +++ b/mysql-test/suite/galera/r/wsrep_slave_threads_basic.result @@ -0,0 +1,49 @@ +# +# wsrep_slave_threads +# +# save the initial value +SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; +# default +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +1 + +# scope +SELECT @@session.wsrep_slave_threads; +ERROR HY000: Variable 'wsrep_slave_threads' is a GLOBAL variable +SET @@global.wsrep_slave_threads=1; +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +1 + +# valid values +SET @@global.wsrep_slave_threads=10; +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +10 +SET @@global.wsrep_slave_threads=0; +Warnings: +Warning 1292 Truncated incorrect wsrep_slave_threads value: '0' +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +1 +SET @@global.wsrep_slave_threads=default; +SELECT @global.wsrep_slave_threads; +@global.wsrep_slave_threads +NULL + +# invalid values +SET @@global.wsrep_slave_threads=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_slave_threads' +SET @@global.wsrep_slave_threads='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_slave_threads' +SET @@global.wsrep_slave_threads=-1; +Warnings: +Warning 1292 Truncated incorrect wsrep_slave_threads value: '-1' +SELECT @global.wsrep_slave_threads; +@global.wsrep_slave_threads +NULL + +# restore the initial value +SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; +# End of test diff --git a/mysql-test/suite/galera/t/wsrep_slave_threads_basic.test b/mysql-test/suite/galera/t/wsrep_slave_threads_basic.test new file mode 100644 index 00000000000..ecf159f8365 --- /dev/null +++ b/mysql-test/suite/galera/t/wsrep_slave_threads_basic.test @@ -0,0 +1,43 @@ +--source include/galera_cluster.inc + +--echo # +--echo # wsrep_slave_threads +--echo # + +--echo # save the initial value +SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; + +--echo # default +SELECT @@global.wsrep_slave_threads; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_slave_threads; +SET @@global.wsrep_slave_threads=1; +SELECT @@global.wsrep_slave_threads; + +--echo +--echo # valid values +SET @@global.wsrep_slave_threads=10; +SELECT @@global.wsrep_slave_threads; +SET @@global.wsrep_slave_threads=0; +SELECT @@global.wsrep_slave_threads; +SET @@global.wsrep_slave_threads=default; +SELECT @global.wsrep_slave_threads; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_slave_threads=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_slave_threads='junk'; +# expect warning : Truncated incorrect wsrep_slave_threads value: '-1' +SET @@global.wsrep_slave_threads=-1; +SELECT @global.wsrep_slave_threads; + +--echo +--echo # restore the initial value +SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result b/mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result deleted file mode 100644 index 62be5a42416..00000000000 --- a/mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result +++ /dev/null @@ -1,49 +0,0 @@ -# -# wsrep_slave_threads -# -# save the initial value -SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; -# default -SELECT @@global.wsrep_slave_threads; -@@global.wsrep_slave_threads -1 - -# scope -SELECT @@session.wsrep_slave_threads; -ERROR HY000: Variable 'wsrep_slave_threads' is a GLOBAL variable -SET @@global.wsrep_slave_threads=1; -SELECT @@global.wsrep_slave_threads; -@@global.wsrep_slave_threads -1 - -# valid values -SET @@global.wsrep_slave_threads=10; -SELECT @@global.wsrep_slave_threads; -@@global.wsrep_slave_threads -10 -SET @@global.wsrep_slave_threads=0; -Warnings: -Warning 1292 Truncated incorrect wsrep_slave_threads value: '0' -SELECT @@global.wsrep_slave_threads; -@@global.wsrep_slave_threads -1 -SET @@global.wsrep_slave_threads=default; -SELECT @global.wsrep_slave_threads; -@global.wsrep_slave_threads -NULL - -# invalid values -SET @@global.wsrep_slave_threads=NULL; -ERROR 42000: Incorrect argument type to variable 'wsrep_slave_threads' -SET @@global.wsrep_slave_threads='junk'; -ERROR 42000: Incorrect argument type to variable 'wsrep_slave_threads' -SET @@global.wsrep_slave_threads=-1; -Warnings: -Warning 1292 Truncated incorrect wsrep_slave_threads value: '-1' -SELECT @global.wsrep_slave_threads; -@global.wsrep_slave_threads -NULL - -# restore the initial value -SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; -# End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test b/mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test deleted file mode 100644 index 80b4648982d..00000000000 --- a/mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test +++ /dev/null @@ -1,43 +0,0 @@ ---source include/have_wsrep.inc - ---echo # ---echo # wsrep_slave_threads ---echo # - ---echo # save the initial value -SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; - ---echo # default -SELECT @@global.wsrep_slave_threads; - ---echo ---echo # scope ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -SELECT @@session.wsrep_slave_threads; -SET @@global.wsrep_slave_threads=1; -SELECT @@global.wsrep_slave_threads; - ---echo ---echo # valid values -SET @@global.wsrep_slave_threads=10; -SELECT @@global.wsrep_slave_threads; -SET @@global.wsrep_slave_threads=0; -SELECT @@global.wsrep_slave_threads; -SET @@global.wsrep_slave_threads=default; -SELECT @global.wsrep_slave_threads; - ---echo ---echo # invalid values ---error ER_WRONG_TYPE_FOR_VAR -SET @@global.wsrep_slave_threads=NULL; ---error ER_WRONG_TYPE_FOR_VAR -SET @@global.wsrep_slave_threads='junk'; -# expect warning : Truncated incorrect wsrep_slave_threads value: '-1' -SET @@global.wsrep_slave_threads=-1; -SELECT @global.wsrep_slave_threads; - ---echo ---echo # restore the initial value -SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; - ---echo # End of test -- cgit v1.2.1 From a38b937bf12ab7e39eeda6e6d4da1b426302dc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Sun, 9 Jan 2022 09:37:44 +0200 Subject: MDEV-25201 : Assertion `thd->wsrep_trx_meta.gtid.seqno == (-1)' failed in int wsrep_to_isolation_begin(THD*, const char*, const char*, const TABLE_LIST*, Alter_info*) Test case does not assert anymore but works incorrectly. We should not replicate PREPARE using TOI. --- mysql-test/suite/galera/r/enforce_storage_engine2.result | 1 + mysql-test/suite/galera/r/galera_myisam_transactions.result | 9 +++++++++ mysql-test/suite/galera/t/galera_myisam_transactions.test | 13 +++++++++++++ sql/sql_base.cc | 1 + 4 files changed, 24 insertions(+) diff --git a/mysql-test/suite/galera/r/enforce_storage_engine2.result b/mysql-test/suite/galera/r/enforce_storage_engine2.result index 128994ed221..4b80d335bb0 100644 --- a/mysql-test/suite/galera/r/enforce_storage_engine2.result +++ b/mysql-test/suite/galera/r/enforce_storage_engine2.result @@ -7,6 +7,7 @@ CREATE TABLE t1(i INT) ENGINE=INNODB; CREATE TABLE t2(i INT) ENGINE=MYISAM; Warnings: Note 1266 Using storage engine InnoDB for table 't2' +Note 1266 Using storage engine InnoDB for table 't2' connection node_2; SHOW TABLES; Tables_in_test diff --git a/mysql-test/suite/galera/r/galera_myisam_transactions.result b/mysql-test/suite/galera/r/galera_myisam_transactions.result index 25796c309d1..194af41dd51 100644 --- a/mysql-test/suite/galera/r/galera_myisam_transactions.result +++ b/mysql-test/suite/galera/r/galera_myisam_transactions.result @@ -35,3 +35,12 @@ SELECT COUNT(*) = 0 FROM t2; COUNT(*) = 0 1 DROP TABLE t1, t2, t3; +SET SESSION lock_wait_timeout=2; +SET GLOBAL wsrep_replicate_myisam= ON; +CREATE TEMPORARY TABLE t1 (i INT, PRIMARY KEY pk (i)) ENGINE=MyISAM; +PREPARE stmt FROM "INSERT INTO t1 (id) SELECT * FROM (SELECT 4 AS i) AS y"; +INSERT INTO t1 VALUES(4); +DEALLOCATE PREPARE stmt; +COMMIT; +DROP TABLE t1; +SET GLOBAL wsrep_replicate_myisam=OFF; diff --git a/mysql-test/suite/galera/t/galera_myisam_transactions.test b/mysql-test/suite/galera/t/galera_myisam_transactions.test index 00e0bf3fdca..30677ddbe4d 100644 --- a/mysql-test/suite/galera/t/galera_myisam_transactions.test +++ b/mysql-test/suite/galera/t/galera_myisam_transactions.test @@ -34,3 +34,16 @@ SELECT COUNT(*) = 0 FROM t2; SELECT COUNT(*) = 0 FROM t2; DROP TABLE t1, t2, t3; + +# +# MDEV-25201 : Assertion `thd->wsrep_trx_meta.gtid.seqno == (-1)' failed in int wsrep_to_isolation_begin(THD*, const char*, const char*, const TABLE_LIST*, Alter_info*) +# +SET SESSION lock_wait_timeout=2; +SET GLOBAL wsrep_replicate_myisam= ON; +CREATE TEMPORARY TABLE t1 (i INT, PRIMARY KEY pk (i)) ENGINE=MyISAM; +PREPARE stmt FROM "INSERT INTO t1 (id) SELECT * FROM (SELECT 4 AS i) AS y"; +INSERT INTO t1 VALUES(4); +DEALLOCATE PREPARE stmt; +COMMIT; +DROP TABLE t1; +SET GLOBAL wsrep_replicate_myisam=OFF; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5345fdbecd0..248dedf36e4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4227,6 +4227,7 @@ restart: wsrep_thd_exec_mode(thd) == LOCAL_STATE && !is_stat_table((*start)->db, (*start)->alias) && thd->get_command() != COM_STMT_PREPARE && + !thd->stmt_arena->is_stmt_prepare() && ((thd->lex->sql_command == SQLCOM_INSERT || thd->lex->sql_command == SQLCOM_INSERT_SELECT || thd->lex->sql_command == SQLCOM_REPLACE || -- cgit v1.2.1 From a3267c11fa6dfd950f8da0266b8afe8691809e82 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 11 Jan 2022 17:46:51 +0100 Subject: MDEV-21252 ER_HOST_IS_BLOCKED returns packet sequence 1 instead of 0 Fix regression introduced in MDEV-19893 Some errors must be sent with seqno = 0, e.g those that are detected before server sends its first "welcome" packet (e.g too many connections) This was not taken into account originally in MDEV-19893 fix. We need to check sql_errno, before fixing sequence number, to see if the error we send is really an out-of-bound, e.g a KILL. --- sql/protocol.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index 613668b39a5..3da5d686d1a 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -467,8 +467,12 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, coming from server to have seq_no > 0, due to missing awareness of "out-of-band" operations. Make these clients happy. */ - if (!net->pkt_nr) - net->pkt_nr= 1; + if (!net->pkt_nr && + (sql_errno == ER_CONNECTION_KILLED || sql_errno == ER_SERVER_SHUTDOWN || + sql_errno == ER_QUERY_INTERRUPTED)) + { + net->pkt_nr= 1; + } ret= net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) buff, length); -- cgit v1.2.1 From d7f4fd30f2ec9f2851e434d1922e2e382e6b8c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 14 Jan 2022 15:53:29 +0200 Subject: MDEV-8851 innodb.innodb_information_schema fails sporadically The column INFORMATION_SCHEMA.INNODB_LOCKS.LOCK_DATA would report NULL when the page that contains the locked record does not reside in the buffer pool. Pages may be evicted from the buffer pool due to some background activity, such as the purge of transaction history loading undo log pages to the buffer pool. The regression tests intentionally run with a small buffer pool size setting. To prevent the intermittent test failures, we will filter out the contents of the LOCK_DATA column from the output. --- .../innodb/r/innodb_information_schema.result | 28 +++++++++++----------- .../suite/innodb/t/innodb_information_schema.test | 2 ++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_information_schema.result b/mysql-test/suite/innodb/r/innodb_information_schema.result index 36c76b03bd0..6c15ffb4e79 100644 --- a/mysql-test/suite/innodb/r/innodb_information_schema.result +++ b/mysql-test/suite/innodb/r/innodb_information_schema.result @@ -1,18 +1,18 @@ lock_mode lock_type lock_table lock_index lock_rec lock_data -X RECORD `test`.```t'\"_str` PRIMARY 2 '1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc''''' -X RECORD `test`.```t'\"_str` PRIMARY 2 '1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc''''' -X RECORD `test`.```t'\"_str` PRIMARY 3 '2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""' -X RECORD `test`.```t'\"_str` PRIMARY 3 '2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""' -X RECORD `test`.```t'\"_str` PRIMARY 4 '3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\' -X RECORD `test`.```t'\"_str` PRIMARY 4 '3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\' -X RECORD `test`.```t'\"_str` PRIMARY 5 '4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0' -X RECORD `test`.```t'\"_str` PRIMARY 5 '4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0' -X RECORD `test`.`t_min` PRIMARY 2 -128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0 -X RECORD `test`.`t_min` PRIMARY 2 -128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0 -X RECORD `test`.`t_max` PRIMARY 2 127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615 -X RECORD `test`.`t_max` PRIMARY 2 127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615 -X RECORD `test`.```t'\"_str` PRIMARY 1 supremum pseudo-record -X RECORD `test`.```t'\"_str` PRIMARY 1 supremum pseudo-record +X RECORD `test`.```t'\"_str` PRIMARY 1 # +X RECORD `test`.```t'\"_str` PRIMARY 1 # +X RECORD `test`.```t'\"_str` PRIMARY 2 # +X RECORD `test`.```t'\"_str` PRIMARY 2 # +X RECORD `test`.```t'\"_str` PRIMARY 3 # +X RECORD `test`.```t'\"_str` PRIMARY 3 # +X RECORD `test`.```t'\"_str` PRIMARY 4 # +X RECORD `test`.```t'\"_str` PRIMARY 4 # +X RECORD `test`.```t'\"_str` PRIMARY 5 # +X RECORD `test`.```t'\"_str` PRIMARY 5 # +X RECORD `test`.`t_max` PRIMARY 2 # +X RECORD `test`.`t_max` PRIMARY 2 # +X RECORD `test`.`t_min` PRIMARY 2 # +X RECORD `test`.`t_min` PRIMARY 2 # lock_table COUNT(*) `test`.`t_max` 2 `test`.`t_min` 2 diff --git a/mysql-test/suite/innodb/t/innodb_information_schema.test b/mysql-test/suite/innodb/t/innodb_information_schema.test index da7ee016f29..5bc1115c58e 100644 --- a/mysql-test/suite/innodb/t/innodb_information_schema.test +++ b/mysql-test/suite/innodb/t/innodb_information_schema.test @@ -148,6 +148,8 @@ if (!$success) -- echo Timeout waiting for rows in INNODB_LOCKS to appear } +--replace_column 6 # +--sorted_result SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data; -- cgit v1.2.1 From a88a4336fc4813c33a719db540816659097632c3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 1 Jan 2022 17:19:21 +0100 Subject: mtr failed to detect when a combination is forced mtr detects a forced combination if the command line for a test already includes all options from this combination. options are stored in a perl hash as (key,value) pairs. this breaks if the command line has two options with the same name, like --plugin-load-add=foo --plugin-load-add=bar, and the combination forces plugin foo. In particular, this resulted in warnings when running federated.federatedx_versioning test --- mysql-test/lib/My/Options.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/My/Options.pm b/mysql-test/lib/My/Options.pm index 5827e0666a6..b3ae64cb4c2 100644 --- a/mysql-test/lib/My/Options.pm +++ b/mysql-test/lib/My/Options.pm @@ -142,11 +142,11 @@ sub diff { sub is_subset { my ($set, $subset)= @_; - my %cache = map { _split_option($_) } @$set; + my %cache = map { join('=', _split_option($_)), 1 } @$set; for (@$subset){ my ($name, $value)= _split_option($_); - return 0 unless exists $cache{$name} and $cache{$name} eq $value; + return 0 unless $cache{"$name=$value"}; } return 1; -- cgit v1.2.1 From 3548e80bc49892a574a89986c0b94fa3d85b0534 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 11 Jan 2022 00:35:47 +0100 Subject: MDEV-4621 select returns null for information_schema.statistics.collation field information_schema.statistics.collation column needs OPEN_FULL_TABLE, because it checks index_flags() for HA_READ_ORDER capability. --- mysql-test/r/show.result | 11 +++++++++++ mysql-test/t/show.test | 8 ++++++++ sql/sql_show.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/show.result b/mysql-test/r/show.result index d1b373d8969..4a9e2738346 100644 --- a/mysql-test/r/show.result +++ b/mysql-test/r/show.result @@ -40,5 +40,16 @@ nm varchar(32) YES NULL a int(11) YES NULL drop table t1; # +# MDEV-4621 select returns null for information_schema.statistics.collation field +# +create table t1 (f varchar(64), key(f)); +select index_name, column_name, collation, cardinality from information_schema.STATISTICS where table_schema='test' and table_name='t1'; +index_name column_name collation cardinality +f f A NULL +select index_name, column_name, collation from information_schema.STATISTICS where table_schema='test' and table_name='t1'; +index_name column_name collation +f f A +drop table t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/show.test b/mysql-test/t/show.test index f2f6efc4e45..9b0b58349d5 100644 --- a/mysql-test/t/show.test +++ b/mysql-test/t/show.test @@ -34,6 +34,14 @@ show fields from test.t1 where field in where table_name='t1' group by column_name) dt); drop table t1; +--echo # +--echo # MDEV-4621 select returns null for information_schema.statistics.collation field +--echo # +create table t1 (f varchar(64), key(f)); +select index_name, column_name, collation, cardinality from information_schema.STATISTICS where table_schema='test' and table_name='t1'; +select index_name, column_name, collation from information_schema.STATISTICS where table_schema='test' and table_name='t1'; +drop table t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 710c68d2551..9483db9eff9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8967,7 +8967,7 @@ ST_FIELD_INFO stat_fields_info[]= {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONGLONG, 0, 0, "Seq_in_index", OPEN_FRM_ONLY}, {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name", OPEN_FRM_ONLY}, - {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY}, + {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FULL_TABLE}, {"CARDINALITY", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 1, "Cardinality", OPEN_FULL_TABLE}, {"SUB_PART", 3, MYSQL_TYPE_LONGLONG, 0, 1, "Sub_part", OPEN_FRM_ONLY}, -- cgit v1.2.1 From b5a14f061b9ee3df46bd6b52200e0fcc466d7695 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 13 Jan 2022 18:14:09 +0100 Subject: /usr/lib64/pkgconfig is not owned by MariaDB-devel --- cmake/cpack_rpm.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 63186e625bf..3eb11591875 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -144,6 +144,7 @@ SET(ignored "%ignore ${CMAKE_INSTALL_PREFIX}/lib/systemd/system" "%ignore ${CMAKE_INSTALL_PREFIX}/lib/tmpfiles.d" "%ignore ${CMAKE_INSTALL_PREFIX}/lib64" + "%ignore ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig" "%ignore ${CMAKE_INSTALL_PREFIX}/sbin" "%ignore ${CMAKE_INSTALL_PREFIX}/share" "%ignore ${CMAKE_INSTALL_PREFIX}/share/aclocal" -- cgit v1.2.1 From 746050d02d6b927c59767c8ff121e0d674520f90 Mon Sep 17 00:00:00 2001 From: Alexey Bychko Date: Wed, 12 Jan 2022 20:03:40 +0100 Subject: MDEV-27109 mysql_config mariadb_config lists non existant -lmariadb added dependency devel->shared and conflict with previous versions update C/C 3.1 with the corresponding C/C part of the fix --- cmake/cpack_rpm.cmake | 4 +++- libmariadb | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 3eb11591875..2dabfd480eb 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -27,7 +27,7 @@ SET(CPACK_COMPONENT_BACKUP_GROUP "backup") SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts SupportFiles Development ManPagesDevelopment - ManPagesTest Readme ManPagesClient Test + ManPagesTest Readme ManPagesClient Test Common Client SharedLibraries ClientPlugins backup ) @@ -186,6 +186,8 @@ SETA(CPACK_RPM_devel_PACKAGE_OBSOLETES "MySQL-devel") SETA(CPACK_RPM_devel_PACKAGE_PROVIDES "MySQL-devel") +SETA(CPACK_RPM_devel_PACKAGE_REQUIRES + "MariaDB-shared >= 10.2.42") SETA(CPACK_RPM_server_PACKAGE_OBSOLETES "MariaDB" diff --git a/libmariadb b/libmariadb index 735a7299dba..dde7deee51f 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 735a7299dbae19cc2b82b9697becaf90e9b43047 +Subproject commit dde7deee51fb4bab475a3e78b66d5ef0872a8d98 -- cgit v1.2.1 From 47e18af906f41c3b15796b8d4e6da9b744491b91 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 13 Jan 2022 17:27:28 +0100 Subject: MDEV-27494 Rename .ic files to .inl --- .gitattributes | 2 +- extra/innochecksum.cc | 6 +- mysys_ssl/my_sha.ic | 188 -- mysys_ssl/my_sha.inl | 188 ++ mysys_ssl/my_sha1.cc | 2 +- mysys_ssl/my_sha224.cc | 2 +- mysys_ssl/my_sha256.cc | 2 +- mysys_ssl/my_sha384.cc | 2 +- mysys_ssl/my_sha512.cc | 2 +- sql/sql_plugin.cc | 2 +- sql/sql_plugin_services.ic | 246 --- sql/sql_plugin_services.inl | 246 +++ sql/sys_vars.cc | 2 +- sql/sys_vars.ic | 2527 ------------------------ sql/sys_vars.inl | 2527 ++++++++++++++++++++++++ storage/innobase/buf/buf0buf.cc | 2 +- storage/innobase/fts/fts0fts.cc | 2 +- storage/innobase/include/btr0btr.h | 2 +- storage/innobase/include/btr0btr.ic | 274 --- storage/innobase/include/btr0btr.inl | 274 +++ storage/innobase/include/btr0cur.h | 2 +- storage/innobase/include/btr0cur.ic | 230 --- storage/innobase/include/btr0cur.inl | 230 +++ storage/innobase/include/btr0pcur.h | 2 +- storage/innobase/include/btr0pcur.ic | 657 ------ storage/innobase/include/btr0pcur.inl | 657 ++++++ storage/innobase/include/btr0sea.h | 2 +- storage/innobase/include/btr0sea.ic | 195 -- storage/innobase/include/btr0sea.inl | 195 ++ storage/innobase/include/buf0buddy.h | 2 +- storage/innobase/include/buf0buddy.ic | 139 -- storage/innobase/include/buf0buddy.inl | 139 ++ storage/innobase/include/buf0buf.h | 2 +- storage/innobase/include/buf0buf.ic | 1478 -------------- storage/innobase/include/buf0buf.inl | 1478 ++++++++++++++ storage/innobase/include/buf0flu.h | 2 +- storage/innobase/include/buf0flu.ic | 149 -- storage/innobase/include/buf0flu.inl | 149 ++ storage/innobase/include/data0data.h | 2 +- storage/innobase/include/data0data.ic | 634 ------ storage/innobase/include/data0data.inl | 634 ++++++ storage/innobase/include/data0type.h | 2 +- storage/innobase/include/data0type.ic | 638 ------ storage/innobase/include/data0type.inl | 638 ++++++ storage/innobase/include/dict0boot.h | 2 +- storage/innobase/include/dict0boot.ic | 96 - storage/innobase/include/dict0boot.inl | 96 + storage/innobase/include/dict0crea.h | 2 +- storage/innobase/include/dict0crea.ic | 136 -- storage/innobase/include/dict0crea.inl | 136 ++ storage/innobase/include/dict0dict.h | 2 +- storage/innobase/include/dict0dict.ic | 1545 --------------- storage/innobase/include/dict0dict.inl | 1545 +++++++++++++++ storage/innobase/include/dict0mem.h | 2 +- storage/innobase/include/dict0mem.ic | 78 - storage/innobase/include/dict0mem.inl | 78 + storage/innobase/include/dict0pagecompress.h | 2 +- storage/innobase/include/dict0pagecompress.ic | 81 - storage/innobase/include/dict0pagecompress.inl | 81 + storage/innobase/include/dict0priv.h | 2 +- storage/innobase/include/dict0priv.ic | 126 -- storage/innobase/include/dict0priv.inl | 126 ++ storage/innobase/include/dict0stats.h | 2 +- storage/innobase/include/dict0stats.ic | 221 --- storage/innobase/include/dict0stats.inl | 221 +++ storage/innobase/include/eval0eval.h | 2 +- storage/innobase/include/eval0eval.ic | 253 --- storage/innobase/include/eval0eval.inl | 253 +++ storage/innobase/include/eval0proc.h | 2 +- storage/innobase/include/eval0proc.ic | 88 - storage/innobase/include/eval0proc.inl | 88 + storage/innobase/include/fil0crypt.h | 2 +- storage/innobase/include/fil0crypt.ic | 81 - storage/innobase/include/fil0crypt.inl | 81 + storage/innobase/include/fil0fil.h | 2 +- storage/innobase/include/fil0fil.ic | 128 -- storage/innobase/include/fil0fil.inl | 128 ++ storage/innobase/include/fsp0fsp.h | 2 +- storage/innobase/include/fsp0fsp.ic | 124 -- storage/innobase/include/fsp0fsp.inl | 124 ++ storage/innobase/include/fsp0pagecompress.h | 2 +- storage/innobase/include/fsp0pagecompress.ic | 63 - storage/innobase/include/fsp0pagecompress.inl | 63 + storage/innobase/include/fts0priv.h | 2 +- storage/innobase/include/fts0priv.ic | 121 -- storage/innobase/include/fts0priv.inl | 121 ++ storage/innobase/include/fts0types.h | 2 +- storage/innobase/include/fts0types.ic | 232 --- storage/innobase/include/fts0types.inl | 232 +++ storage/innobase/include/fut0fut.h | 2 +- storage/innobase/include/fut0fut.ic | 68 - storage/innobase/include/fut0fut.inl | 68 + storage/innobase/include/fut0lst.h | 2 +- storage/innobase/include/fut0lst.ic | 169 -- storage/innobase/include/fut0lst.inl | 169 ++ storage/innobase/include/gis0rtree.h | 2 +- storage/innobase/include/gis0rtree.ic | 266 --- storage/innobase/include/gis0rtree.inl | 266 +++ storage/innobase/include/ha0ha.h | 2 +- storage/innobase/include/ha0ha.ic | 242 --- storage/innobase/include/ha0ha.inl | 242 +++ storage/innobase/include/ha0storage.h | 2 +- storage/innobase/include/ha0storage.ic | 144 -- storage/innobase/include/ha0storage.inl | 144 ++ storage/innobase/include/hash0hash.h | 2 +- storage/innobase/include/hash0hash.ic | 277 --- storage/innobase/include/hash0hash.inl | 277 +++ storage/innobase/include/ibuf0ibuf.h | 2 +- storage/innobase/include/ibuf0ibuf.ic | 341 ---- storage/innobase/include/ibuf0ibuf.inl | 341 ++++ storage/innobase/include/lock0lock.h | 2 +- storage/innobase/include/lock0lock.ic | 134 -- storage/innobase/include/lock0lock.inl | 134 ++ storage/innobase/include/lock0priv.h | 2 +- storage/innobase/include/lock0priv.ic | 421 ---- storage/innobase/include/lock0priv.inl | 421 ++++ storage/innobase/include/log0log.h | 2 +- storage/innobase/include/log0log.ic | 484 ----- storage/innobase/include/log0log.inl | 484 +++++ storage/innobase/include/mach0data.h | 2 +- storage/innobase/include/mach0data.ic | 893 --------- storage/innobase/include/mach0data.inl | 893 +++++++++ storage/innobase/include/mem0mem.h | 2 +- storage/innobase/include/mem0mem.ic | 482 ----- storage/innobase/include/mem0mem.inl | 482 +++++ storage/innobase/include/mtr0log.h | 2 +- storage/innobase/include/mtr0log.ic | 248 --- storage/innobase/include/mtr0log.inl | 248 +++ storage/innobase/include/mtr0mtr.h | 2 +- storage/innobase/include/mtr0mtr.ic | 280 --- storage/innobase/include/mtr0mtr.inl | 280 +++ storage/innobase/include/os0file.h | 2 +- storage/innobase/include/os0file.ic | 599 ------ storage/innobase/include/os0file.inl | 599 ++++++ storage/innobase/include/page0cur.h | 2 +- storage/innobase/include/page0cur.ic | 328 --- storage/innobase/include/page0cur.inl | 328 +++ storage/innobase/include/page0page.h | 2 +- storage/innobase/include/page0page.ic | 1062 ---------- storage/innobase/include/page0page.inl | 1062 ++++++++++ storage/innobase/include/page0zip.h | 2 +- storage/innobase/include/page0zip.ic | 447 ----- storage/innobase/include/page0zip.inl | 447 +++++ storage/innobase/include/que0que.h | 2 +- storage/innobase/include/que0que.ic | 293 --- storage/innobase/include/que0que.inl | 293 +++ storage/innobase/include/rem0cmp.h | 2 +- storage/innobase/include/rem0cmp.ic | 108 - storage/innobase/include/rem0cmp.inl | 108 + storage/innobase/include/rem0rec.h | 2 +- storage/innobase/include/rem0rec.ic | 1738 ---------------- storage/innobase/include/rem0rec.inl | 1738 ++++++++++++++++ storage/innobase/include/row0ext.h | 2 +- storage/innobase/include/row0ext.ic | 87 - storage/innobase/include/row0ext.inl | 87 + storage/innobase/include/row0log.h | 2 +- storage/innobase/include/row0log.ic | 84 - storage/innobase/include/row0log.inl | 84 + storage/innobase/include/row0row.h | 2 +- storage/innobase/include/row0row.ic | 224 --- storage/innobase/include/row0row.inl | 224 +++ storage/innobase/include/row0sel.h | 2 +- storage/innobase/include/row0sel.ic | 138 -- storage/innobase/include/row0sel.inl | 138 ++ storage/innobase/include/row0upd.h | 2 +- storage/innobase/include/row0upd.ic | 198 -- storage/innobase/include/row0upd.inl | 198 ++ storage/innobase/include/srv0mon.h | 2 +- storage/innobase/include/srv0mon.ic | 113 -- storage/innobase/include/srv0mon.inl | 113 ++ storage/innobase/include/sync0arr.h | 2 +- storage/innobase/include/sync0arr.ic | 86 - storage/innobase/include/sync0arr.inl | 86 + storage/innobase/include/sync0policy.h | 2 +- storage/innobase/include/sync0policy.ic | 101 - storage/innobase/include/sync0policy.inl | 101 + storage/innobase/include/sync0rw.h | 2 +- storage/innobase/include/sync0rw.ic | 838 -------- storage/innobase/include/sync0rw.inl | 838 ++++++++ storage/innobase/include/trx0purge.h | 2 +- storage/innobase/include/trx0purge.ic | 63 - storage/innobase/include/trx0purge.inl | 63 + storage/innobase/include/trx0rec.h | 2 +- storage/innobase/include/trx0rec.ic | 102 - storage/innobase/include/trx0rec.inl | 102 + storage/innobase/include/trx0roll.h | 2 +- storage/innobase/include/trx0roll.ic | 62 - storage/innobase/include/trx0roll.inl | 62 + storage/innobase/include/trx0rseg.h | 2 +- storage/innobase/include/trx0rseg.ic | 154 -- storage/innobase/include/trx0rseg.inl | 154 ++ storage/innobase/include/trx0sys.h | 2 +- storage/innobase/include/trx0sys.ic | 460 ----- storage/innobase/include/trx0sys.inl | 460 +++++ storage/innobase/include/trx0trx.h | 2 +- storage/innobase/include/trx0trx.ic | 234 --- storage/innobase/include/trx0trx.inl | 234 +++ storage/innobase/include/trx0undo.h | 2 +- storage/innobase/include/trx0undo.ic | 352 ---- storage/innobase/include/trx0undo.inl | 352 ++++ storage/innobase/include/ut0byte.h | 2 +- storage/innobase/include/ut0byte.ic | 173 -- storage/innobase/include/ut0byte.inl | 173 ++ storage/innobase/include/ut0list.h | 2 +- storage/innobase/include/ut0list.ic | 80 - storage/innobase/include/ut0list.inl | 80 + storage/innobase/include/ut0mem.h | 2 +- storage/innobase/include/ut0mem.ic | 318 --- storage/innobase/include/ut0mem.inl | 318 +++ storage/innobase/include/ut0rnd.h | 2 +- storage/innobase/include/ut0rnd.ic | 150 -- storage/innobase/include/ut0rnd.inl | 150 ++ storage/innobase/include/ut0ut.h | 2 +- storage/innobase/include/ut0ut.ic | 143 -- storage/innobase/include/ut0ut.inl | 143 ++ storage/innobase/include/ut0vec.h | 2 +- storage/innobase/include/ut0vec.ic | 348 ---- storage/innobase/include/ut0vec.inl | 348 ++++ strings/ctype-big5.c | 10 +- strings/ctype-cp932.c | 10 +- strings/ctype-euc_kr.c | 10 +- strings/ctype-eucjpms.c | 10 +- strings/ctype-gb2312.c | 10 +- strings/ctype-gbk.c | 10 +- strings/ctype-mb.ic | 263 --- strings/ctype-mb.inl | 263 +++ strings/ctype-sjis.c | 10 +- strings/ctype-ucs2.c | 38 +- strings/ctype-ujis.c | 10 +- strings/ctype-utf8.c | 26 +- strings/strcoll.ic | 338 ---- strings/strcoll.inl | 338 ++++ 232 files changed, 25013 insertions(+), 25013 deletions(-) delete mode 100644 mysys_ssl/my_sha.ic create mode 100644 mysys_ssl/my_sha.inl delete mode 100644 sql/sql_plugin_services.ic create mode 100644 sql/sql_plugin_services.inl delete mode 100644 sql/sys_vars.ic create mode 100644 sql/sys_vars.inl delete mode 100644 storage/innobase/include/btr0btr.ic create mode 100644 storage/innobase/include/btr0btr.inl delete mode 100644 storage/innobase/include/btr0cur.ic create mode 100644 storage/innobase/include/btr0cur.inl delete mode 100644 storage/innobase/include/btr0pcur.ic create mode 100644 storage/innobase/include/btr0pcur.inl delete mode 100644 storage/innobase/include/btr0sea.ic create mode 100644 storage/innobase/include/btr0sea.inl delete mode 100644 storage/innobase/include/buf0buddy.ic create mode 100644 storage/innobase/include/buf0buddy.inl delete mode 100644 storage/innobase/include/buf0buf.ic create mode 100644 storage/innobase/include/buf0buf.inl delete mode 100644 storage/innobase/include/buf0flu.ic create mode 100644 storage/innobase/include/buf0flu.inl delete mode 100644 storage/innobase/include/data0data.ic create mode 100644 storage/innobase/include/data0data.inl delete mode 100644 storage/innobase/include/data0type.ic create mode 100644 storage/innobase/include/data0type.inl delete mode 100644 storage/innobase/include/dict0boot.ic create mode 100644 storage/innobase/include/dict0boot.inl delete mode 100644 storage/innobase/include/dict0crea.ic create mode 100644 storage/innobase/include/dict0crea.inl delete mode 100644 storage/innobase/include/dict0dict.ic create mode 100644 storage/innobase/include/dict0dict.inl delete mode 100644 storage/innobase/include/dict0mem.ic create mode 100644 storage/innobase/include/dict0mem.inl delete mode 100644 storage/innobase/include/dict0pagecompress.ic create mode 100644 storage/innobase/include/dict0pagecompress.inl delete mode 100644 storage/innobase/include/dict0priv.ic create mode 100644 storage/innobase/include/dict0priv.inl delete mode 100644 storage/innobase/include/dict0stats.ic create mode 100644 storage/innobase/include/dict0stats.inl delete mode 100644 storage/innobase/include/eval0eval.ic create mode 100644 storage/innobase/include/eval0eval.inl delete mode 100644 storage/innobase/include/eval0proc.ic create mode 100644 storage/innobase/include/eval0proc.inl delete mode 100644 storage/innobase/include/fil0crypt.ic create mode 100644 storage/innobase/include/fil0crypt.inl delete mode 100644 storage/innobase/include/fil0fil.ic create mode 100644 storage/innobase/include/fil0fil.inl delete mode 100644 storage/innobase/include/fsp0fsp.ic create mode 100644 storage/innobase/include/fsp0fsp.inl delete mode 100644 storage/innobase/include/fsp0pagecompress.ic create mode 100644 storage/innobase/include/fsp0pagecompress.inl delete mode 100644 storage/innobase/include/fts0priv.ic create mode 100644 storage/innobase/include/fts0priv.inl delete mode 100644 storage/innobase/include/fts0types.ic create mode 100644 storage/innobase/include/fts0types.inl delete mode 100644 storage/innobase/include/fut0fut.ic create mode 100644 storage/innobase/include/fut0fut.inl delete mode 100644 storage/innobase/include/fut0lst.ic create mode 100644 storage/innobase/include/fut0lst.inl delete mode 100644 storage/innobase/include/gis0rtree.ic create mode 100644 storage/innobase/include/gis0rtree.inl delete mode 100644 storage/innobase/include/ha0ha.ic create mode 100644 storage/innobase/include/ha0ha.inl delete mode 100644 storage/innobase/include/ha0storage.ic create mode 100644 storage/innobase/include/ha0storage.inl delete mode 100644 storage/innobase/include/hash0hash.ic create mode 100644 storage/innobase/include/hash0hash.inl delete mode 100644 storage/innobase/include/ibuf0ibuf.ic create mode 100644 storage/innobase/include/ibuf0ibuf.inl delete mode 100644 storage/innobase/include/lock0lock.ic create mode 100644 storage/innobase/include/lock0lock.inl delete mode 100644 storage/innobase/include/lock0priv.ic create mode 100644 storage/innobase/include/lock0priv.inl delete mode 100644 storage/innobase/include/log0log.ic create mode 100644 storage/innobase/include/log0log.inl delete mode 100644 storage/innobase/include/mach0data.ic create mode 100644 storage/innobase/include/mach0data.inl delete mode 100644 storage/innobase/include/mem0mem.ic create mode 100644 storage/innobase/include/mem0mem.inl delete mode 100644 storage/innobase/include/mtr0log.ic create mode 100644 storage/innobase/include/mtr0log.inl delete mode 100644 storage/innobase/include/mtr0mtr.ic create mode 100644 storage/innobase/include/mtr0mtr.inl delete mode 100644 storage/innobase/include/os0file.ic create mode 100644 storage/innobase/include/os0file.inl delete mode 100644 storage/innobase/include/page0cur.ic create mode 100644 storage/innobase/include/page0cur.inl delete mode 100644 storage/innobase/include/page0page.ic create mode 100644 storage/innobase/include/page0page.inl delete mode 100644 storage/innobase/include/page0zip.ic create mode 100644 storage/innobase/include/page0zip.inl delete mode 100644 storage/innobase/include/que0que.ic create mode 100644 storage/innobase/include/que0que.inl delete mode 100644 storage/innobase/include/rem0cmp.ic create mode 100644 storage/innobase/include/rem0cmp.inl delete mode 100644 storage/innobase/include/rem0rec.ic create mode 100644 storage/innobase/include/rem0rec.inl delete mode 100644 storage/innobase/include/row0ext.ic create mode 100644 storage/innobase/include/row0ext.inl delete mode 100644 storage/innobase/include/row0log.ic create mode 100644 storage/innobase/include/row0log.inl delete mode 100644 storage/innobase/include/row0row.ic create mode 100644 storage/innobase/include/row0row.inl delete mode 100644 storage/innobase/include/row0sel.ic create mode 100644 storage/innobase/include/row0sel.inl delete mode 100644 storage/innobase/include/row0upd.ic create mode 100644 storage/innobase/include/row0upd.inl delete mode 100644 storage/innobase/include/srv0mon.ic create mode 100644 storage/innobase/include/srv0mon.inl delete mode 100644 storage/innobase/include/sync0arr.ic create mode 100644 storage/innobase/include/sync0arr.inl delete mode 100644 storage/innobase/include/sync0policy.ic create mode 100644 storage/innobase/include/sync0policy.inl delete mode 100644 storage/innobase/include/sync0rw.ic create mode 100644 storage/innobase/include/sync0rw.inl delete mode 100644 storage/innobase/include/trx0purge.ic create mode 100644 storage/innobase/include/trx0purge.inl delete mode 100644 storage/innobase/include/trx0rec.ic create mode 100644 storage/innobase/include/trx0rec.inl delete mode 100644 storage/innobase/include/trx0roll.ic create mode 100644 storage/innobase/include/trx0roll.inl delete mode 100644 storage/innobase/include/trx0rseg.ic create mode 100644 storage/innobase/include/trx0rseg.inl delete mode 100644 storage/innobase/include/trx0sys.ic create mode 100644 storage/innobase/include/trx0sys.inl delete mode 100644 storage/innobase/include/trx0trx.ic create mode 100644 storage/innobase/include/trx0trx.inl delete mode 100644 storage/innobase/include/trx0undo.ic create mode 100644 storage/innobase/include/trx0undo.inl delete mode 100644 storage/innobase/include/ut0byte.ic create mode 100644 storage/innobase/include/ut0byte.inl delete mode 100644 storage/innobase/include/ut0list.ic create mode 100644 storage/innobase/include/ut0list.inl delete mode 100644 storage/innobase/include/ut0mem.ic create mode 100644 storage/innobase/include/ut0mem.inl delete mode 100644 storage/innobase/include/ut0rnd.ic create mode 100644 storage/innobase/include/ut0rnd.inl delete mode 100644 storage/innobase/include/ut0ut.ic create mode 100644 storage/innobase/include/ut0ut.inl delete mode 100644 storage/innobase/include/ut0vec.ic create mode 100644 storage/innobase/include/ut0vec.inl delete mode 100644 strings/ctype-mb.ic create mode 100644 strings/ctype-mb.inl delete mode 100644 strings/strcoll.ic create mode 100644 strings/strcoll.inl diff --git a/.gitattributes b/.gitattributes index 9d638481a84..6d94dc06cd7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -30,6 +30,6 @@ pcre/testdata/greppatN4 -text *.c diff=cpp *.h diff=cpp *.cc diff=cpp -*.ic diff=cpp +*.inl diff=cpp *.cpp diff=cpp *.java diff=cpp diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index f333ec20991..06001fd451b 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -73,9 +73,9 @@ typedef void fil_space_t; #include #ifdef UNIV_NONINL -# include "fsp0fsp.ic" -# include "mach0data.ic" -# include "ut0rnd.ic" +# include "fsp0fsp.inl" +# include "mach0data.inl" +# include "ut0rnd.inl" #endif #ifndef PRIuMAX diff --git a/mysys_ssl/my_sha.ic b/mysys_ssl/my_sha.ic deleted file mode 100644 index 97344dc0415..00000000000 --- a/mysys_ssl/my_sha.ic +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (c) 2012, Oracle and/or its affiliates. - Copyright (c) 2014, 2017, 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, - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ - - -/** - @file - - @brief - Wrapper functions for OpenSSL, YaSSL implementations. Also provides a - Compatibility layer to make available YaSSL's SHAn implementation. -*/ - -#include -#include - -#define HASH_SIZE (NUM > 1 ? NUM/8 : 20) - -#if defined(HAVE_YASSL) -#include "sha.hpp" - -#define xCONTEXT(x) TaoCrypt::SHA ## x -#define yCONTEXT(y) xCONTEXT(y) -#define CONTEXT yCONTEXT(NUM) -#define SHA1 SHA - -static void sha_init(CONTEXT *context) -{ - context->Init(); -} - -/* - this is a variant of sha_init to be used in this file only. - does nothing for yassl, because the context's constructor was called automatically. -*/ -static void sha_init_fast(CONTEXT *context) -{ -} - -static void sha_input(CONTEXT *context, const uchar *buf, unsigned len) -{ - context->Update((const TaoCrypt::byte *) buf, len); -} - -static void sha_result(CONTEXT *context, uchar digest[HASH_SIZE]) -{ - context->Final((TaoCrypt::byte *) digest); -} - -#elif defined(HAVE_OPENSSL) -#include - -#define xCONTEXT(x) SHA ## x ## _CTX -#define yCONTEXT(y) xCONTEXT(y) -#define CONTEXT yCONTEXT(NUM) -#define SHA1_CTX SHA_CTX -#define SHA224_CTX SHA256_CTX -#define SHA384_CTX SHA512_CTX - -#define xSHA_Init(x) SHA ## x ## _Init -#define xSHA_Update(x) SHA ## x ## _Update -#define xSHA_Final(x) SHA ## x ## _Final -#define ySHA_Init(y) xSHA_Init(y) -#define ySHA_Update(y) xSHA_Update(y) -#define ySHA_Final(y) xSHA_Final(y) -#define SHA_Init ySHA_Init(NUM) -#define SHA_Update ySHA_Update(NUM) -#define SHA_Final ySHA_Final(NUM) - -static void sha_init(CONTEXT *context) -{ - SHA_Init(context); -} - -static void sha_init_fast(CONTEXT *context) -{ - sha_init(context); -} - -static void sha_input(CONTEXT *context, const uchar *buf, unsigned len) -{ - SHA_Update(context, buf, len); -} - -static void sha_result(CONTEXT *context, uchar digest[HASH_SIZE]) -{ - SHA_Final(digest, context); -} - -#endif /* HAVE_YASSL */ - -#define xmy_sha_multi(x) my_sha ## x ## _multi -#define xmy_sha_context_size(x) my_sha ## x ## _context_size -#define xmy_sha_init(x) my_sha ## x ## _init -#define xmy_sha_input(x) my_sha ## x ## _input -#define xmy_sha_result(x) my_sha ## x ## _result -#define xmy_sha(x) my_sha ## x -#define ymy_sha_multi(y) xmy_sha_multi(y) -#define ymy_sha_context_size(y) xmy_sha_context_size(y) -#define ymy_sha_init(y) xmy_sha_init(y) -#define ymy_sha_input(y) xmy_sha_input(y) -#define ymy_sha_result(y) xmy_sha_result(y) -#define ymy_sha(y) xmy_sha(y) -#define my_sha_multi ymy_sha_multi(NUM) -#define my_sha_context_size ymy_sha_context_size(NUM) -#define my_sha_init ymy_sha_init(NUM) -#define my_sha_input ymy_sha_input(NUM) -#define my_sha_result ymy_sha_result(NUM) -#define my_sha ymy_sha(NUM) - -/** - Wrapper function to compute SHAn message digest. - - @param digest [out] Computed SHAn digest - @param buf [in] Message to be computed - @param len [in] Length of the message - - @return void -*/ -void my_sha(uchar *digest, const char *buf, size_t len) -{ - CONTEXT context; - - sha_init_fast(&context); - sha_input(&context, (const uchar *)buf, (unsigned int)len); - sha_result(&context, digest); -} - - -/** - Wrapper function to compute SHAn message digest for - two messages in order to emulate shaN(msg1, msg2). - - @param digest [out] Computed SHAn digest - @param buf1 [in] First message - @param len1 [in] Length of first message - @param buf2 [in] Second message - @param len2 [in] Length of second message - - @return void -*/ -void my_sha_multi(uchar *digest, ...) -{ - va_list args; - va_start(args, digest); - - CONTEXT context; - const uchar *str; - - sha_init_fast(&context); - for (str= va_arg(args, const uchar*); str; str= va_arg(args, const uchar*)) - sha_input(&context, str, (uint) va_arg(args, size_t)); - - sha_result(&context, digest); - va_end(args); -} - -size_t my_sha_context_size() -{ - return sizeof(CONTEXT); -} - -void my_sha_init(void *context) -{ - sha_init((CONTEXT *)context); -} - -void my_sha_input(void *context, const uchar *buf, size_t len) -{ - sha_input((CONTEXT *)context, buf, (uint) len); -} - -void my_sha_result(void *context, uchar *digest) -{ - sha_result((CONTEXT *)context, digest); -} diff --git a/mysys_ssl/my_sha.inl b/mysys_ssl/my_sha.inl new file mode 100644 index 00000000000..97344dc0415 --- /dev/null +++ b/mysys_ssl/my_sha.inl @@ -0,0 +1,188 @@ +/* Copyright (c) 2012, Oracle and/or its affiliates. + Copyright (c) 2014, 2017, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + + +/** + @file + + @brief + Wrapper functions for OpenSSL, YaSSL implementations. Also provides a + Compatibility layer to make available YaSSL's SHAn implementation. +*/ + +#include +#include + +#define HASH_SIZE (NUM > 1 ? NUM/8 : 20) + +#if defined(HAVE_YASSL) +#include "sha.hpp" + +#define xCONTEXT(x) TaoCrypt::SHA ## x +#define yCONTEXT(y) xCONTEXT(y) +#define CONTEXT yCONTEXT(NUM) +#define SHA1 SHA + +static void sha_init(CONTEXT *context) +{ + context->Init(); +} + +/* + this is a variant of sha_init to be used in this file only. + does nothing for yassl, because the context's constructor was called automatically. +*/ +static void sha_init_fast(CONTEXT *context) +{ +} + +static void sha_input(CONTEXT *context, const uchar *buf, unsigned len) +{ + context->Update((const TaoCrypt::byte *) buf, len); +} + +static void sha_result(CONTEXT *context, uchar digest[HASH_SIZE]) +{ + context->Final((TaoCrypt::byte *) digest); +} + +#elif defined(HAVE_OPENSSL) +#include + +#define xCONTEXT(x) SHA ## x ## _CTX +#define yCONTEXT(y) xCONTEXT(y) +#define CONTEXT yCONTEXT(NUM) +#define SHA1_CTX SHA_CTX +#define SHA224_CTX SHA256_CTX +#define SHA384_CTX SHA512_CTX + +#define xSHA_Init(x) SHA ## x ## _Init +#define xSHA_Update(x) SHA ## x ## _Update +#define xSHA_Final(x) SHA ## x ## _Final +#define ySHA_Init(y) xSHA_Init(y) +#define ySHA_Update(y) xSHA_Update(y) +#define ySHA_Final(y) xSHA_Final(y) +#define SHA_Init ySHA_Init(NUM) +#define SHA_Update ySHA_Update(NUM) +#define SHA_Final ySHA_Final(NUM) + +static void sha_init(CONTEXT *context) +{ + SHA_Init(context); +} + +static void sha_init_fast(CONTEXT *context) +{ + sha_init(context); +} + +static void sha_input(CONTEXT *context, const uchar *buf, unsigned len) +{ + SHA_Update(context, buf, len); +} + +static void sha_result(CONTEXT *context, uchar digest[HASH_SIZE]) +{ + SHA_Final(digest, context); +} + +#endif /* HAVE_YASSL */ + +#define xmy_sha_multi(x) my_sha ## x ## _multi +#define xmy_sha_context_size(x) my_sha ## x ## _context_size +#define xmy_sha_init(x) my_sha ## x ## _init +#define xmy_sha_input(x) my_sha ## x ## _input +#define xmy_sha_result(x) my_sha ## x ## _result +#define xmy_sha(x) my_sha ## x +#define ymy_sha_multi(y) xmy_sha_multi(y) +#define ymy_sha_context_size(y) xmy_sha_context_size(y) +#define ymy_sha_init(y) xmy_sha_init(y) +#define ymy_sha_input(y) xmy_sha_input(y) +#define ymy_sha_result(y) xmy_sha_result(y) +#define ymy_sha(y) xmy_sha(y) +#define my_sha_multi ymy_sha_multi(NUM) +#define my_sha_context_size ymy_sha_context_size(NUM) +#define my_sha_init ymy_sha_init(NUM) +#define my_sha_input ymy_sha_input(NUM) +#define my_sha_result ymy_sha_result(NUM) +#define my_sha ymy_sha(NUM) + +/** + Wrapper function to compute SHAn message digest. + + @param digest [out] Computed SHAn digest + @param buf [in] Message to be computed + @param len [in] Length of the message + + @return void +*/ +void my_sha(uchar *digest, const char *buf, size_t len) +{ + CONTEXT context; + + sha_init_fast(&context); + sha_input(&context, (const uchar *)buf, (unsigned int)len); + sha_result(&context, digest); +} + + +/** + Wrapper function to compute SHAn message digest for + two messages in order to emulate shaN(msg1, msg2). + + @param digest [out] Computed SHAn digest + @param buf1 [in] First message + @param len1 [in] Length of first message + @param buf2 [in] Second message + @param len2 [in] Length of second message + + @return void +*/ +void my_sha_multi(uchar *digest, ...) +{ + va_list args; + va_start(args, digest); + + CONTEXT context; + const uchar *str; + + sha_init_fast(&context); + for (str= va_arg(args, const uchar*); str; str= va_arg(args, const uchar*)) + sha_input(&context, str, (uint) va_arg(args, size_t)); + + sha_result(&context, digest); + va_end(args); +} + +size_t my_sha_context_size() +{ + return sizeof(CONTEXT); +} + +void my_sha_init(void *context) +{ + sha_init((CONTEXT *)context); +} + +void my_sha_input(void *context, const uchar *buf, size_t len) +{ + sha_input((CONTEXT *)context, buf, (uint) len); +} + +void my_sha_result(void *context, uchar *digest) +{ + sha_result((CONTEXT *)context, digest); +} diff --git a/mysys_ssl/my_sha1.cc b/mysys_ssl/my_sha1.cc index b53e214468d..29563742e6b 100644 --- a/mysys_ssl/my_sha1.cc +++ b/mysys_ssl/my_sha1.cc @@ -15,4 +15,4 @@ #define NUM 1 -#include "my_sha.ic" +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha224.cc b/mysys_ssl/my_sha224.cc index 200b6ed161c..5fffdce7794 100644 --- a/mysys_ssl/my_sha224.cc +++ b/mysys_ssl/my_sha224.cc @@ -15,4 +15,4 @@ #define NUM 224 -#include "my_sha.ic" +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha256.cc b/mysys_ssl/my_sha256.cc index 1562809f91a..59e871de121 100644 --- a/mysys_ssl/my_sha256.cc +++ b/mysys_ssl/my_sha256.cc @@ -15,4 +15,4 @@ #define NUM 256 -#include "my_sha.ic" +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha384.cc b/mysys_ssl/my_sha384.cc index 6bb64470105..40707de0a8d 100644 --- a/mysys_ssl/my_sha384.cc +++ b/mysys_ssl/my_sha384.cc @@ -15,4 +15,4 @@ #define NUM 384 -#include "my_sha.ic" +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha512.cc b/mysys_ssl/my_sha512.cc index 1047d0dbe46..6a5a04d72f0 100644 --- a/mysys_ssl/my_sha512.cc +++ b/mysys_ssl/my_sha512.cc @@ -15,4 +15,4 @@ #define NUM 512 -#include "my_sha.ic" +#include "my_sha.inl" diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 968ec6ac7d4..97bc17042b2 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -215,7 +215,7 @@ static struct /* support for Services */ -#include "sql_plugin_services.ic" +#include "sql_plugin_services.inl" /* A mutex LOCK_plugin must be acquired before accessing the diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic deleted file mode 100644 index 358052132a0..00000000000 --- a/sql/sql_plugin_services.ic +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. - Copyright (c) 2012, 2014, Monty Program Ab - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ - -/* support for Services */ -#include -#include - -struct st_service_ref { - const char *name; - uint version; - void *service; -}; - -static struct my_snprintf_service_st my_snprintf_handler = { - my_snprintf, - my_vsnprintf -}; - -static struct thd_alloc_service_st thd_alloc_handler= { - thd_alloc, - thd_calloc, - thd_strdup, - thd_strmake, - thd_memdup, - thd_make_lex_string -}; - -static struct thd_wait_service_st thd_wait_handler= { - thd_wait_begin, - thd_wait_end -}; - -static struct progress_report_service_st progress_report_handler= { - thd_progress_init, - thd_progress_report, - thd_progress_next_stage, - thd_progress_end, - set_thd_proc_info -}; - -static struct kill_statement_service_st thd_kill_statement_handler= { - thd_kill_level -}; - -static struct thd_timezone_service_st thd_timezone_handler= { - thd_TIME_to_gmt_sec, - thd_gmt_sec_to_TIME -}; - -static struct my_sha2_service_st my_sha2_handler = { - my_sha224, - my_sha224_multi, - my_sha224_context_size, - my_sha224_init, - my_sha224_input, - my_sha224_result, - my_sha256, - my_sha256_multi, - my_sha256_context_size, - my_sha256_init, - my_sha256_input, - my_sha256_result, - my_sha384, - my_sha384_multi, - my_sha384_context_size, - my_sha384_init, - my_sha384_input, - my_sha384_result, - my_sha512, - my_sha512_multi, - my_sha512_context_size, - my_sha512_init, - my_sha512_input, - my_sha512_result, -}; - -static struct my_sha1_service_st my_sha1_handler = { - my_sha1, - my_sha1_multi, - my_sha1_context_size, - my_sha1_init, - my_sha1_input, - my_sha1_result -}; - -static struct my_md5_service_st my_md5_handler = { - my_md5, - my_md5_multi, - my_md5_context_size, - my_md5_init, - my_md5_input, - my_md5_result -}; - -static struct logger_service_st logger_service_handler= { - logger_init_mutexes, - logger_open, - logger_close, - logger_vprintf, - logger_printf, - logger_write, - logger_rotate -}; - -static struct thd_autoinc_service_st thd_autoinc_handler= { - thd_get_autoinc -}; - -static struct thd_rnd_service_st thd_rnd_handler= { - thd_rnd, - thd_create_random_password -}; - -static struct base64_service_st base64_handler= { - my_base64_needed_encoded_length, - my_base64_encode_max_arg_length, - my_base64_needed_decoded_length, - my_base64_decode_max_arg_length, - my_base64_encode, - my_base64_decode -}; - -static struct thd_error_context_service_st thd_error_context_handler= { - thd_get_error_message, - thd_get_error_number, - thd_get_error_row, - thd_inc_error_row, - thd_get_error_context_description -}; - -static struct wsrep_service_st wsrep_handler = { - get_wsrep, - get_wsrep_certify_nonPK, - get_wsrep_debug, - get_wsrep_drupal_282555_workaround, - get_wsrep_recovery, - get_wsrep_load_data_splitting, - get_wsrep_log_conflicts, - get_wsrep_protocol_version, - wsrep_aborting_thd_contains, - wsrep_aborting_thd_enqueue, - wsrep_consistency_check, - wsrep_is_wsrep_xid, - wsrep_lock_rollback, - wsrep_on, - wsrep_post_commit, - wsrep_prepare_key, - wsrep_run_wsrep_commit, - wsrep_thd_LOCK, - wsrep_thd_UNLOCK, - wsrep_thd_awake, - wsrep_thd_conflict_state, - wsrep_thd_conflict_state_str, - wsrep_thd_exec_mode, - wsrep_thd_exec_mode_str, - wsrep_thd_get_conflict_state, - wsrep_thd_is_BF, - wsrep_thd_is_wsrep, - wsrep_thd_query, - wsrep_thd_query_state, - wsrep_thd_query_state_str, - wsrep_thd_retry_counter, - wsrep_thd_set_conflict_state, - wsrep_thd_ignore_table, - wsrep_thd_trx_seqno, - wsrep_thd_ws_handle, - wsrep_set_load_multi_commit, - wsrep_is_load_multi_commit, - wsrep_trx_is_aborting, - wsrep_trx_order_before, - wsrep_unlock_rollback, - wsrep_set_data_home_dir, - wsrep_thd_is_applier, - wsrep_report_bf_lock_wait -}; - -static struct thd_specifics_service_st thd_specifics_handler= -{ - thd_key_create, - thd_key_delete, - thd_getspecific, - thd_setspecific -}; - -static struct encryption_scheme_service_st encryption_scheme_handler= -{ - encryption_scheme_encrypt, - encryption_scheme_decrypt -}; - -static struct my_crypt_service_st crypt_handler= -{ - my_aes_crypt_init, - my_aes_crypt_update, - my_aes_crypt_finish, - my_aes_crypt, - my_aes_get_size, - my_aes_ctx_size, - my_random_bytes -}; - -static struct my_print_error_service_st my_print_error_handler= -{ - my_error, - my_printf_error, - my_printv_error -}; - -static struct st_service_ref list_of_services[]= -{ - { "base64_service", VERSION_base64, &base64_handler }, - { "debug_sync_service", VERSION_debug_sync, 0 }, // updated in plugin_init() - { "encryption_scheme_service", VERSION_encryption_scheme, &encryption_scheme_handler }, - { "encryption_service", VERSION_encryption, &encryption_handler }, - { "logger_service", VERSION_logger, &logger_service_handler }, - { "my_crypt_service", VERSION_my_crypt, &crypt_handler}, - { "my_md5_service", VERSION_my_md5, &my_md5_handler}, - { "my_print_error_service", VERSION_my_print_error, &my_print_error_handler}, - { "my_sha1_service", VERSION_my_sha1, &my_sha1_handler}, - { "my_sha2_service", VERSION_my_sha2, &my_sha2_handler}, - { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, - { "progress_report_service", VERSION_progress_report, &progress_report_handler }, - { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler }, - { "thd_autoinc_service", VERSION_thd_autoinc, &thd_autoinc_handler }, - { "thd_error_context_service", VERSION_thd_error_context, &thd_error_context_handler }, - { "thd_kill_statement_service", VERSION_kill_statement, &thd_kill_statement_handler }, - { "thd_rnd_service", VERSION_thd_rnd, &thd_rnd_handler }, - { "thd_specifics_service", VERSION_thd_specifics, &thd_specifics_handler }, - { "thd_timezone_service", VERSION_thd_timezone, &thd_timezone_handler }, - { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, - { "wsrep_service", VERSION_wsrep, &wsrep_handler } -}; - diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl new file mode 100644 index 00000000000..358052132a0 --- /dev/null +++ b/sql/sql_plugin_services.inl @@ -0,0 +1,246 @@ +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, 2014, Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* support for Services */ +#include +#include + +struct st_service_ref { + const char *name; + uint version; + void *service; +}; + +static struct my_snprintf_service_st my_snprintf_handler = { + my_snprintf, + my_vsnprintf +}; + +static struct thd_alloc_service_st thd_alloc_handler= { + thd_alloc, + thd_calloc, + thd_strdup, + thd_strmake, + thd_memdup, + thd_make_lex_string +}; + +static struct thd_wait_service_st thd_wait_handler= { + thd_wait_begin, + thd_wait_end +}; + +static struct progress_report_service_st progress_report_handler= { + thd_progress_init, + thd_progress_report, + thd_progress_next_stage, + thd_progress_end, + set_thd_proc_info +}; + +static struct kill_statement_service_st thd_kill_statement_handler= { + thd_kill_level +}; + +static struct thd_timezone_service_st thd_timezone_handler= { + thd_TIME_to_gmt_sec, + thd_gmt_sec_to_TIME +}; + +static struct my_sha2_service_st my_sha2_handler = { + my_sha224, + my_sha224_multi, + my_sha224_context_size, + my_sha224_init, + my_sha224_input, + my_sha224_result, + my_sha256, + my_sha256_multi, + my_sha256_context_size, + my_sha256_init, + my_sha256_input, + my_sha256_result, + my_sha384, + my_sha384_multi, + my_sha384_context_size, + my_sha384_init, + my_sha384_input, + my_sha384_result, + my_sha512, + my_sha512_multi, + my_sha512_context_size, + my_sha512_init, + my_sha512_input, + my_sha512_result, +}; + +static struct my_sha1_service_st my_sha1_handler = { + my_sha1, + my_sha1_multi, + my_sha1_context_size, + my_sha1_init, + my_sha1_input, + my_sha1_result +}; + +static struct my_md5_service_st my_md5_handler = { + my_md5, + my_md5_multi, + my_md5_context_size, + my_md5_init, + my_md5_input, + my_md5_result +}; + +static struct logger_service_st logger_service_handler= { + logger_init_mutexes, + logger_open, + logger_close, + logger_vprintf, + logger_printf, + logger_write, + logger_rotate +}; + +static struct thd_autoinc_service_st thd_autoinc_handler= { + thd_get_autoinc +}; + +static struct thd_rnd_service_st thd_rnd_handler= { + thd_rnd, + thd_create_random_password +}; + +static struct base64_service_st base64_handler= { + my_base64_needed_encoded_length, + my_base64_encode_max_arg_length, + my_base64_needed_decoded_length, + my_base64_decode_max_arg_length, + my_base64_encode, + my_base64_decode +}; + +static struct thd_error_context_service_st thd_error_context_handler= { + thd_get_error_message, + thd_get_error_number, + thd_get_error_row, + thd_inc_error_row, + thd_get_error_context_description +}; + +static struct wsrep_service_st wsrep_handler = { + get_wsrep, + get_wsrep_certify_nonPK, + get_wsrep_debug, + get_wsrep_drupal_282555_workaround, + get_wsrep_recovery, + get_wsrep_load_data_splitting, + get_wsrep_log_conflicts, + get_wsrep_protocol_version, + wsrep_aborting_thd_contains, + wsrep_aborting_thd_enqueue, + wsrep_consistency_check, + wsrep_is_wsrep_xid, + wsrep_lock_rollback, + wsrep_on, + wsrep_post_commit, + wsrep_prepare_key, + wsrep_run_wsrep_commit, + wsrep_thd_LOCK, + wsrep_thd_UNLOCK, + wsrep_thd_awake, + wsrep_thd_conflict_state, + wsrep_thd_conflict_state_str, + wsrep_thd_exec_mode, + wsrep_thd_exec_mode_str, + wsrep_thd_get_conflict_state, + wsrep_thd_is_BF, + wsrep_thd_is_wsrep, + wsrep_thd_query, + wsrep_thd_query_state, + wsrep_thd_query_state_str, + wsrep_thd_retry_counter, + wsrep_thd_set_conflict_state, + wsrep_thd_ignore_table, + wsrep_thd_trx_seqno, + wsrep_thd_ws_handle, + wsrep_set_load_multi_commit, + wsrep_is_load_multi_commit, + wsrep_trx_is_aborting, + wsrep_trx_order_before, + wsrep_unlock_rollback, + wsrep_set_data_home_dir, + wsrep_thd_is_applier, + wsrep_report_bf_lock_wait +}; + +static struct thd_specifics_service_st thd_specifics_handler= +{ + thd_key_create, + thd_key_delete, + thd_getspecific, + thd_setspecific +}; + +static struct encryption_scheme_service_st encryption_scheme_handler= +{ + encryption_scheme_encrypt, + encryption_scheme_decrypt +}; + +static struct my_crypt_service_st crypt_handler= +{ + my_aes_crypt_init, + my_aes_crypt_update, + my_aes_crypt_finish, + my_aes_crypt, + my_aes_get_size, + my_aes_ctx_size, + my_random_bytes +}; + +static struct my_print_error_service_st my_print_error_handler= +{ + my_error, + my_printf_error, + my_printv_error +}; + +static struct st_service_ref list_of_services[]= +{ + { "base64_service", VERSION_base64, &base64_handler }, + { "debug_sync_service", VERSION_debug_sync, 0 }, // updated in plugin_init() + { "encryption_scheme_service", VERSION_encryption_scheme, &encryption_scheme_handler }, + { "encryption_service", VERSION_encryption, &encryption_handler }, + { "logger_service", VERSION_logger, &logger_service_handler }, + { "my_crypt_service", VERSION_my_crypt, &crypt_handler}, + { "my_md5_service", VERSION_my_md5, &my_md5_handler}, + { "my_print_error_service", VERSION_my_print_error, &my_print_error_handler}, + { "my_sha1_service", VERSION_my_sha1, &my_sha1_handler}, + { "my_sha2_service", VERSION_my_sha2, &my_sha2_handler}, + { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, + { "progress_report_service", VERSION_progress_report, &progress_report_handler }, + { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler }, + { "thd_autoinc_service", VERSION_thd_autoinc, &thd_autoinc_handler }, + { "thd_error_context_service", VERSION_thd_error_context, &thd_error_context_handler }, + { "thd_kill_statement_service", VERSION_kill_statement, &thd_kill_statement_handler }, + { "thd_rnd_service", VERSION_thd_rnd, &thd_rnd_handler }, + { "thd_specifics_service", VERSION_thd_specifics, &thd_specifics_handler }, + { "thd_timezone_service", VERSION_thd_timezone, &thd_timezone_handler }, + { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, + { "wsrep_service", VERSION_wsrep, &wsrep_handler } +}; + diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index bd4b2fbb062..ee862e4936e 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -34,7 +34,7 @@ #include "sql_plugin.h" // Includes my_global.h #include "sql_priv.h" #include "sql_class.h" // set_var.h: THD -#include "sys_vars.ic" +#include "sys_vars.inl" #include "events.h" #include diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic deleted file mode 100644 index 3c3cfb8c8a6..00000000000 --- a/sql/sys_vars.ic +++ /dev/null @@ -1,2527 +0,0 @@ -/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. - Copyright (c) 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ - -/** - @file - "private" interface to sys_var - server configuration variables. - - This header is included only by the file that contains declarations - of sys_var variables (sys_vars.cc). -*/ - -#include "sys_vars_shared.h" -#include -#include -#include -#include "keycaches.h" -#include "strfunc.h" -#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone -#include "rpl_mi.h" // For Multi-Source Replication -#include "debug_sync.h" - -/* - a set of mostly trivial (as in f(X)=X) defines below to make system variable - declarations more readable -*/ -#define VALID_RANGE(X,Y) X,Y -#define DEFAULT(X) X -#define BLOCK_SIZE(X) X -#define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X) -#define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) -#define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) -#define NO_CMD_LINE CMD_LINE(NO_ARG, sys_var::NO_GETOPT) -#define CMD_LINE_HELP_ONLY CMD_LINE(NO_ARG, sys_var::GETOPT_ONLY_HELP) -/* - the define below means that there's no *second* mutex guard, - LOCK_global_system_variables always guards all system variables -*/ -#define NO_MUTEX_GUARD ((PolyLock*)0) -#define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG -#define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG -#define ON_READ(X) X -#define ON_CHECK(X) X -#define ON_UPDATE(X) X -#define READ_ONLY sys_var::READONLY+ -#define AUTO_SET sys_var::AUTO_SET+ -// this means that Sys_var_charptr initial value was malloc()ed -#define PREALLOCATED sys_var::ALLOCATED+ -#define PARSED_EARLY sys_var::PARSE_EARLY+ -#define NO_SET_STMT sys_var::NO_SET_STATEMENT+ - -/* - Sys_var_bit meaning is reversed, like in - @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS -*/ -#define REVERSE(X) ~(X) -#define DEPRECATED(X) X - -#define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD)) -#define global_var(TYPE) (*(TYPE*)global_var_ptr()) - -#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) -#define GET_HA_ROWS GET_ULL -#else -#define GET_HA_ROWS GET_ULONG -#endif - -/* - special assert for sysvars. Tells the name of the variable, - and fails even in non-debug builds. - - It is supposed to be used *only* in Sys_var* constructors, - and has name_arg hard-coded to prevent incorrect usage. -*/ -#define SYSVAR_ASSERT(X) \ - while(!(X)) \ - { \ - fprintf(stderr, "Sysvar '%s' failed '%s'\n", name_arg, #X); \ - DBUG_ABORT(); \ - exit(255); \ - } - -enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET}; - -static const char *bool_values[3]= {"OFF", "ON", 0}; -TYPELIB bool_typelib={ array_elements(bool_values)-1, "", bool_values, 0 }; - -/** - A small wrapper class to pass getopt arguments as a pair - to the Sys_var_* constructors. It improves type safety and helps - to catch errors in the argument order. -*/ -struct CMD_LINE -{ - int id; - enum get_opt_arg_type arg_type; - CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0) - : id(getopt_id), arg_type(getopt_arg_type) {} -}; - -/** - Sys_var_integer template is used to generate Sys_var_* classes - for variables that represent the value as an integer number. - They are Sys_var_uint, Sys_var_ulong, Sys_var_harows, Sys_var_ulonglong, - Sys_var_int. - - An integer variable has a minimal and maximal values, and a "block_size" - (any valid value of the variable must be divisible by the block_size). - - Class specific constructor arguments: min, max, block_size - Backing store: int, uint, ulong, ha_rows, ulonglong, depending on the class -*/ -template -class Sys_var_integer: public sys_var -{ -public: - Sys_var_integer(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg, - on_check_func, on_update_func, substitute) - { - option.var_type|= ARGT; - option.min_value= min_val; - option.max_value= max_val; - option.block_size= block_size; - if ((option.u_max_value= (uchar**) max_var_ptr())) - { - *((T*) option.u_max_value)= max_val; - } - - global_var(T)= def_val; - SYSVAR_ASSERT(size == sizeof(T)); - SYSVAR_ASSERT(min_val < max_val); - SYSVAR_ASSERT(min_val <= def_val); - SYSVAR_ASSERT(max_val >= def_val); - SYSVAR_ASSERT(block_size > 0); - SYSVAR_ASSERT(def_val % block_size == 0); - } - bool do_check(THD *thd, set_var *var) - { - my_bool fixed= FALSE, unused; - longlong v= var->value->val_int(); - - if ((ARGT == GET_HA_ROWS) || (ARGT == GET_UINT) || - (ARGT == GET_ULONG) || (ARGT == GET_ULL)) - { - ulonglong uv; - - /* - if the value is signed and negative, - and a variable is unsigned, it is set to zero - */ - if ((fixed= (!var->value->unsigned_flag && v < 0))) - uv= 0; - else - uv= v; - - var->save_result.ulonglong_value= - getopt_ull_limit_value(uv, &option, &unused); - - if (max_var_ptr() && (T)var->save_result.ulonglong_value > get_max_var()) - var->save_result.ulonglong_value= get_max_var(); - - fixed= fixed || var->save_result.ulonglong_value != uv; - } - else - { - /* - if the value is unsigned and has the highest bit set - and a variable is signed, it is set to max signed value - */ - if ((fixed= (var->value->unsigned_flag && v < 0))) - v= LONGLONG_MAX; - - var->save_result.longlong_value= - getopt_ll_limit_value(v, &option, &unused); - - if (max_var_ptr() && (T)var->save_result.longlong_value > get_max_var()) - var->save_result.longlong_value= get_max_var(); - - fixed= fixed || var->save_result.longlong_value != v; - } - return throw_bounds_warning(thd, name.str, fixed, - var->value->unsigned_flag, v); - } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, T)= static_cast(var->save_result.ulonglong_value); - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(T)= static_cast(var->save_result.ulonglong_value); - return false; - } - void session_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); } - void global_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= option.def_value; } - private: - T get_max_var() { return *((T*) max_var_ptr()); } - uchar *default_value_ptr(THD *thd) { return (uchar*) &option.def_value; } -}; - -typedef Sys_var_integer Sys_var_int; -typedef Sys_var_integer Sys_var_uint; -typedef Sys_var_integer Sys_var_ulong; -typedef Sys_var_integer Sys_var_harows; -typedef Sys_var_integer Sys_var_ulonglong; -typedef Sys_var_integer Sys_var_long; - - -template<> uchar *Sys_var_int::default_value_ptr(THD *thd) -{ - thd->sys_var_tmp.int_value= (int)option.def_value; - return (uchar*) &thd->sys_var_tmp.int_value; -} - -template<> uchar *Sys_var_uint::default_value_ptr(THD *thd) -{ - thd->sys_var_tmp.uint_value= (uint)option.def_value; - return (uchar*) &thd->sys_var_tmp.uint_value; -} - -template<> uchar *Sys_var_long::default_value_ptr(THD *thd) -{ - thd->sys_var_tmp.long_value= (long)option.def_value; - return (uchar*) &thd->sys_var_tmp.long_value; -} - -template<> uchar *Sys_var_ulong::default_value_ptr(THD *thd) -{ - thd->sys_var_tmp.ulong_value= (ulong)option.def_value; - return (uchar*) &thd->sys_var_tmp.ulong_value; -} - - -/** - Helper class for variables that take values from a TYPELIB -*/ -class Sys_var_typelib: public sys_var -{ -protected: - TYPELIB typelib; - virtual bool check_maximum(THD *thd, set_var *var, - const char *c_val, longlong i_val) - { return FALSE; } -public: - Sys_var_typelib(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, - CMD_LINE getopt, - SHOW_TYPE show_val_type_arg, const char *values[], - ulonglong def_val, PolyLock *lock, - enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func, on_update_function on_update_func, - const char *substitute) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, show_val_type_arg, def_val, lock, - binlog_status_arg, on_check_func, - on_update_func, substitute) - { - for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */; - typelib.name=""; - typelib.type_names= values; - typelib.type_lengths= 0; // only used by Fields_enum and Field_set - option.typelib= &typelib; - } - bool do_check(THD *thd, set_var *var) // works for enums and my_bool - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (var->value->result_type() == STRING_RESULT) - { - if (!(res=var->value->val_str(&str))) - return true; - else - if (!(var->save_result.ulonglong_value= - find_type(&typelib, res->ptr(), res->length(), false))) - return true; - else - var->save_result.ulonglong_value--; - return check_maximum(thd, var, res->ptr(), 0); - } - - longlong tmp=var->value->val_int(); - if (tmp < 0 || tmp >= typelib.count) - return true; - var->save_result.ulonglong_value= tmp; - return check_maximum(thd, var, 0, tmp); - } -}; - -/** - The class for ENUM variables - variables that take one value from a fixed - list of values. - - Class specific constructor arguments: - char* values[] - 0-terminated list of strings of valid values - - Backing store: uint - - @note - Do *not* use "enum FOO" variables as a backing store, there is no - guarantee that sizeof(enum FOO) == sizeof(uint), there is no guarantee - even that sizeof(enum FOO) == sizeof(enum BAR) -*/ -class Sys_var_enum: public Sys_var_typelib -{ -public: - Sys_var_enum(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - const char *values[], uint def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, - SHOW_CHAR, values, def_val, lock, - binlog_status_arg, on_check_func, on_update_func, - substitute) - { - option.var_type|= GET_ENUM; - option.min_value= 0; - option.max_value= ULONG_MAX; - global_var(ulong)= def_val; - if ((option.u_max_value= (uchar**)max_var_ptr())) - { - *((ulong *) option.u_max_value)= ULONG_MAX; - } - SYSVAR_ASSERT(def_val < typelib.count); - SYSVAR_ASSERT(size == sizeof(ulong)); - } - bool check_maximum(THD *thd, set_var *var, - const char *c_val, longlong i_val) - { - if (!max_var_ptr() || - var->save_result.ulonglong_value <= get_max_var()) - return FALSE; - var->save_result.ulonglong_value= get_max_var(); - - return c_val ? throw_bounds_warning(thd, name.str, c_val) : - throw_bounds_warning(thd, name.str, TRUE, - var->value->unsigned_flag, i_val); - } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, ulong)= static_cast(var->save_result.ulonglong_value); - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(ulong)= static_cast(var->save_result.ulonglong_value); - return false; - } - void session_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= global_var(ulong); } - void global_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= option.def_value; } - uchar *valptr(THD *thd, ulong val) - { return (uchar*)typelib.type_names[val]; } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, session_var(thd, ulong)); } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, global_var(ulong)); } - uchar *default_value_ptr(THD *thd) - { return valptr(thd, (ulong)option.def_value); } - - ulong get_max_var() { return *((ulong *) max_var_ptr()); } -}; - -/** - The class for boolean variables - a variant of ENUM variables - with the fixed list of values of { OFF , ON } - - Backing store: my_bool -*/ -class Sys_var_mybool: public Sys_var_typelib -{ -public: - Sys_var_mybool(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - my_bool def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, - SHOW_MY_BOOL, bool_values, def_val, lock, - binlog_status_arg, on_check_func, on_update_func, - substitute) - { - option.var_type|= GET_BOOL; - global_var(my_bool)= def_val; - SYSVAR_ASSERT(def_val < 2); - SYSVAR_ASSERT(getopt.arg_type == OPT_ARG || getopt.id < 0); - SYSVAR_ASSERT(size == sizeof(my_bool)); - } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, my_bool)= var->save_result.ulonglong_value != 0; - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(my_bool)= var->save_result.ulonglong_value != 0; - return false; - } - void session_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); } - void global_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= option.def_value; } - uchar *default_value_ptr(THD *thd) - { - thd->sys_var_tmp.my_bool_value=(my_bool) option.def_value; - return (uchar*) &thd->sys_var_tmp.my_bool_value; - } -}; - -/** - The class for string variables. The string can be in character_set_filesystem - or in character_set_system. The string can be allocated with my_malloc() - or not. The state of the initial value is specified in the constructor, - after that it's managed automatically. The value of NULL is supported. - - Class specific constructor arguments: - enum charset_enum is_os_charset_arg - - Backing store: char* - - @note - This class supports only GLOBAL variables, because THD on destruction - does not destroy individual members of SV, there's no way to free - allocated string variables for every thread. -*/ -class Sys_var_charptr_base: public sys_var -{ -public: - Sys_var_charptr_base(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - enum charset_enum is_os_charset_arg, - const char *def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute) - { - is_os_charset= is_os_charset_arg == IN_FS_CHARSET; - /* - use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated, - otherwise (GET_STR) you'll never know whether to free it or not. - (think of an exit because of an error right after my_getopt) - */ - option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR; - global_var(const char*)= def_val; - } - void cleanup() - { - if (flags & ALLOCATED) - { - my_free(global_var(char*)); - global_var(char *)= NULL; - } - flags&= ~ALLOCATED; - } - static bool do_string_check(THD *thd, set_var *var, CHARSET_INFO *charset) - { - char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), charset); - String str2(buff2, sizeof(buff2), charset), *res; - - if (!(res=var->value->val_str(&str))) - var->save_result.string_value.str= 0; - else - { - uint32 unused; - if (String::needs_conversion(res->length(), res->charset(), - charset, &unused)) - { - uint errors; - str2.copy(res->ptr(), res->length(), res->charset(), charset, - &errors); - res=&str2; - - } - var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); - var->save_result.string_value.length= res->length(); - } - - return false; - } - bool do_check(THD *thd, set_var *var) - { return do_string_check(thd, var, charset(thd)); } - bool session_update(THD *thd, set_var *var)= 0; - char *global_update_prepare(THD *thd, set_var *var) - { - char *new_val, *ptr= var->save_result.string_value.str; - size_t len=var->save_result.string_value.length; - if (ptr) - { - new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME)); - if (!new_val) return 0; - new_val[len]=0; - } - else - new_val= 0; - return new_val; - } - void global_update_finish(char *new_val) - { - if (flags & ALLOCATED) - my_free(global_var(char*)); - flags|= ALLOCATED; - global_var(char*)= new_val; - } - bool global_update(THD *thd, set_var *var) - { - char *new_val= global_update_prepare(thd, var); - global_update_finish(new_val); - return (new_val == 0 && var->save_result.string_value.str != 0); - } - void session_save_default(THD *thd, set_var *var)= 0; - void global_save_default(THD *thd, set_var *var) - { - char *ptr= (char*)(intptr)option.def_value; - var->save_result.string_value.str= ptr; - var->save_result.string_value.length= ptr ? strlen(ptr) : 0; - } -}; - -class Sys_var_charptr: public Sys_var_charptr_base -{ -public: - Sys_var_charptr(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - enum charset_enum is_os_charset_arg, - const char *def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) : - Sys_var_charptr_base(name_arg, comment, flag_args, off, size, getopt, - is_os_charset_arg, def_val, lock, binlog_status_arg, - on_check_func, on_update_func, substitute) - { - SYSVAR_ASSERT(scope() == GLOBAL); - SYSVAR_ASSERT(size == sizeof(char *)); - } - - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - void session_save_default(THD *thd, set_var *var) - { DBUG_ASSERT(FALSE); } -}; - -#ifndef EMBEDDED_LIBRARY -class Sys_var_sesvartrack: public Sys_var_charptr_base -{ -public: - Sys_var_sesvartrack(const char *name_arg, - const char *comment, - CMD_LINE getopt, - enum charset_enum is_os_charset_arg, - const char *def_val, PolyLock *lock) : - Sys_var_charptr_base(name_arg, comment, - SESSION_VAR(session_track_system_variables), - getopt, is_os_charset_arg, def_val, lock, - VARIABLE_NOT_IN_BINLOG, 0, 0, 0) - {} - bool do_check(THD *thd, set_var *var) - { - if (Sys_var_charptr_base::do_check(thd, var) || - sysvartrack_validate_value(thd, var->save_result.string_value.str, - var->save_result.string_value.length)) - return TRUE; - return FALSE; - } - bool global_update(THD *thd, set_var *var) - { - char *new_val= global_update_prepare(thd, var); - if (new_val) - { - if (sysvartrack_reprint_value(thd, new_val, - var->save_result.string_value.length)) - new_val= 0; - } - global_update_finish(new_val); - return (new_val == 0 && var->save_result.string_value.str != 0); - } - bool session_update(THD *thd, set_var *var) - { - return sysvartrack_update(thd, var); - } - void session_save_default(THD *thd, set_var *var) - { - var->save_result.string_value.str= global_var(char*); - var->save_result.string_value.length= - strlen(var->save_result.string_value.str); - /* parse and feel list with default values */ - if (thd) - { - IF_DBUG(bool res=,) - sysvartrack_validate_value(thd, - var->save_result.string_value.str, - var->save_result.string_value.length); - DBUG_ASSERT(res == 0); - } - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(thd != NULL); - size_t len= sysvartrack_value_len(thd); - char *res= (char *)thd->alloc(len + sizeof(char *)); - if (res) - { - char *buf= res + sizeof(char *); - *((char**) res)= buf; - sysvartrack_value_construct(thd, buf, len); - } - return (uchar *)res; - } -}; -#endif //EMBEDDED_LIBRARY - - -class Sys_var_proxy_user: public sys_var -{ -public: - Sys_var_proxy_user(const char *name_arg, - const char *comment, enum charset_enum is_os_charset_arg) - : sys_var(&all_sys_vars, name_arg, comment, - sys_var::READONLY+sys_var::ONLY_SESSION, 0, NO_GETOPT, - NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, NULL) - { - is_os_charset= is_os_charset_arg == IN_FS_CHARSET; - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return false; - } - void session_save_default(THD *thd, set_var *var) - { DBUG_ASSERT(FALSE); } - void global_save_default(THD *thd, set_var *var) - { DBUG_ASSERT(FALSE); } -protected: - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - return thd->security_ctx->proxy_user[0] ? - (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; - } -}; - -class Sys_var_external_user : public Sys_var_proxy_user -{ -public: - Sys_var_external_user(const char *name_arg, const char *comment_arg, - enum charset_enum is_os_charset_arg) - : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg) - {} - -protected: - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - return (uchar*)thd->security_ctx->external_user; - } -}; - -class Master_info; -class Sys_var_rpl_filter: public sys_var -{ -private: - int opt_id; - -public: - Sys_var_rpl_filter(const char *name, int getopt_id, const char *comment) - : sys_var(&all_sys_vars, name, comment, sys_var::GLOBAL, 0, NO_GETOPT, - NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, NULL), opt_id(getopt_id) - { - option.var_type|= GET_STR | GET_ASK_ADDR; - } - - bool do_check(THD *thd, set_var *var) - { - return Sys_var_charptr::do_string_check(thd, var, charset(thd)); - } - void session_save_default(THD *thd, set_var *var) - { DBUG_ASSERT(FALSE); } - - void global_save_default(THD *thd, set_var *var) - { - char *ptr= (char*)(intptr)option.def_value; - var->save_result.string_value.str= ptr; - var->save_result.string_value.length= ptr ? strlen(ptr) : 0; - } - - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - - bool global_update(THD *thd, set_var *var); - -protected: - uchar *global_value_ptr(THD *thd, const LEX_STRING *base); - bool set_filter_value(const char *value, Master_info *mi); -}; - -/** - The class for string variables. Useful for strings that aren't necessarily - \0-terminated. Otherwise the same as Sys_var_charptr. - - Class specific constructor arguments: - enum charset_enum is_os_charset_arg - - Backing store: LEX_STRING - - @note - Behaves exactly as Sys_var_charptr, only the backing store is different. -*/ -class Sys_var_lexstring: public Sys_var_charptr -{ -public: - Sys_var_lexstring(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - enum charset_enum is_os_charset_arg, - const char *def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*), - getopt, is_os_charset_arg, def_val, lock, binlog_status_arg, - on_check_func, on_update_func, substitute) - { - global_var(LEX_STRING).length= strlen(def_val); - SYSVAR_ASSERT(size == sizeof(LEX_STRING)); - *const_cast(&show_val_type)= SHOW_LEX_STRING; - } - bool global_update(THD *thd, set_var *var) - { - if (Sys_var_charptr::global_update(thd, var)) - return true; - global_var(LEX_STRING).length= var->save_result.string_value.length; - return false; - } -}; - - -/* - A LEX_STRING stored only in thd->variables - Only to be used for small buffers -*/ - -class Sys_var_session_lexstring: public sys_var -{ - size_t max_length; -public: - Sys_var_session_lexstring(const char *name_arg, - const char *comment, int flag_args, - ptrdiff_t off, size_t size, CMD_LINE getopt, - enum charset_enum is_os_charset_arg, - const char *def_val, size_t max_length_arg, - on_check_function on_check_func=0, - on_update_function on_update_func=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, (intptr)def_val, - 0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func, - 0),max_length(max_length_arg) - { - option.var_type|= GET_STR; - SYSVAR_ASSERT(scope() == ONLY_SESSION) - *const_cast(&show_val_type)= SHOW_LEX_STRING; - } - bool do_check(THD *thd, set_var *var) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (!(res=var->value->val_str(&str))) - { - var->save_result.string_value.str= 0; /* NULL */ - var->save_result.string_value.length= 0; - } - else - { - if (res->length() > max_length) - { - my_error(ER_WRONG_STRING_LENGTH, MYF(0), - res->ptr(), name.str, (int) max_length); - return true; - } - var->save_result.string_value.str= thd->strmake(res->ptr(), - res->length()); - var->save_result.string_value.length= res->length(); - } - return false; - } - bool session_update(THD *thd, set_var *var) - { - LEX_STRING *tmp= &session_var(thd, LEX_STRING); - tmp->length= var->save_result.string_value.length; - /* Store as \0 terminated string (just to be safe) */ - strmake(tmp->str, var->save_result.string_value.str, tmp->length); - return false; - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return false; - } - void session_save_default(THD *thd, set_var *var) - { - char *ptr= (char*)(intptr)option.def_value; - var->save_result.string_value.str= ptr; - var->save_result.string_value.length= strlen(ptr); - } - void global_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(FALSE); - return NULL; - } -}; - - -#ifndef DBUG_OFF -/** - @@session.debug_dbug and @@global.debug_dbug variables. - - @@dbug variable differs from other variables in one aspect: - if its value is not assigned in the session, it "points" to the global - value, and so when the global value is changed, the change - immediately takes effect in the session. - - This semantics is intentional, to be able to debug one session from - another. -*/ -class Sys_var_dbug: public sys_var -{ -public: - Sys_var_dbug(const char *name_arg, - const char *comment, int flag_args, - CMD_LINE getopt, - const char *def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, - (char*)¤t_dbug_option-(char*)&global_system_variables, getopt.id, - getopt.arg_type, SHOW_CHAR, (intptr)def_val, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute) - { option.var_type|= GET_STR; } - bool do_check(THD *thd, set_var *var) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (!(res=var->value->val_str(&str))) - var->save_result.string_value.str= const_cast(""); - else - var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); - return false; - } - bool session_update(THD *thd, set_var *var) - { - const char *val= var->save_result.string_value.str; - if (!var->value) - DBUG_POP(); - else - DBUG_SET(val); - return false; - } - bool global_update(THD *thd, set_var *var) - { - const char *val= var->save_result.string_value.str; - DBUG_SET_INITIAL(val); - return false; - } - void session_save_default(THD *thd, set_var *var) - { } - void global_save_default(THD *thd, set_var *var) - { - char *ptr= (char*)(intptr)option.def_value; - var->save_result.string_value.str= ptr; - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - char buf[256]; - DBUG_EXPLAIN(buf, sizeof(buf)); - return (uchar*) thd->strdup(buf); - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - char buf[256]; - DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); - return (uchar*) thd->strdup(buf); - } - uchar *default_value_ptr(THD *thd) - { return (uchar*)""; } -}; -#endif - -#define KEYCACHE_VAR(X) GLOBAL_VAR(dflt_key_cache_var.X) -#define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF)) -#define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF)) -typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong); - -/** - The class for keycache_* variables. Supports structured names, - keycache_name.variable_name. - - Class specific constructor arguments: - everything derived from Sys_var_ulonglong - - Backing store: ulonglong - - @note these variables can be only GLOBAL -*/ -class Sys_var_keycache: public Sys_var_ulonglong -{ - keycache_update_function keycache_update; -public: - Sys_var_keycache(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - ulonglong min_val, ulonglong max_val, ulonglong def_val, - uint block_size, PolyLock *lock, - enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func, - keycache_update_function on_update_func, - const char *substitute=0) - : Sys_var_ulonglong(name_arg, comment, flag_args, off, size, - getopt, min_val, max_val, def_val, - block_size, lock, binlog_status_arg, on_check_func, 0, - substitute), - keycache_update(on_update_func) - { - option.var_type|= GET_ASK_ADDR; - option.value= (uchar**)1; // crash me, please - // fix an offset from global_system_variables to be an offset in KEY_CACHE - offset= global_var_ptr() - (uchar*)dflt_key_cache; - SYSVAR_ASSERT(scope() == GLOBAL); - } - bool global_update(THD *thd, set_var *var) - { - ulonglong new_value= var->save_result.ulonglong_value; - LEX_STRING *base_name= &var->base; - KEY_CACHE *key_cache; - - /* If no basename, assume it's for the key cache named 'default' */ - if (!base_name->length) - base_name= &default_key_cache_base; - - key_cache= get_key_cache(base_name); - - if (!key_cache) - { // Key cache didn't exists */ - if (!new_value) // Tried to delete cache - return false; // Ok, nothing to do - if (!(key_cache= create_key_cache(base_name->str, base_name->length))) - return true; - } - - /** - Abort if some other thread is changing the key cache - @todo This should be changed so that we wait until the previous - assignment is done and then do the new assign - */ - if (key_cache->in_init) - return true; - - return keycache_update(thd, key_cache, offset, new_value); - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - KEY_CACHE *key_cache= get_key_cache(base); - if (!key_cache) - key_cache= &zero_key_cache; - return keycache_var_ptr(key_cache, offset); - } -}; - -static bool update_buffer_size(THD *thd, KEY_CACHE *key_cache, - ptrdiff_t offset, ulonglong new_value) -{ - bool error= false; - DBUG_ASSERT(offset == offsetof(KEY_CACHE, param_buff_size)); - - if (new_value == 0) - { - if (key_cache == dflt_key_cache) - { - my_error(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, MYF(0)); - return true; - } - - if (key_cache->key_cache_inited) // If initied - { - /* - Move tables using this key cache to the default key cache - and clear the old key cache. - */ - key_cache->in_init= 1; - mysql_mutex_unlock(&LOCK_global_system_variables); - key_cache->param_buff_size= 0; - ha_resize_key_cache(key_cache); - ha_change_key_cache(key_cache, dflt_key_cache); - /* - We don't delete the key cache as some running threads my still be in - the key cache code with a pointer to the deleted (empty) key cache - */ - mysql_mutex_lock(&LOCK_global_system_variables); - key_cache->in_init= 0; - } - return error; - } - - key_cache->param_buff_size= new_value; - - /* If key cache didn't exist initialize it, else resize it */ - key_cache->in_init= 1; - mysql_mutex_unlock(&LOCK_global_system_variables); - - if (!key_cache->key_cache_inited) - error= ha_init_key_cache(0, key_cache, 0); - else - error= ha_resize_key_cache(key_cache); - - mysql_mutex_lock(&LOCK_global_system_variables); - key_cache->in_init= 0; - - return error; -} - -static bool update_keycache(THD *thd, KEY_CACHE *key_cache, - ptrdiff_t offset, ulonglong new_value, - int (*func)(KEY_CACHE *)) -{ - bool error= false; - DBUG_ASSERT(offset != offsetof(KEY_CACHE, param_buff_size)); - - keycache_var(key_cache, offset)= new_value; - - key_cache->in_init= 1; - mysql_mutex_unlock(&LOCK_global_system_variables); - error= func(key_cache); - mysql_mutex_lock(&LOCK_global_system_variables); - key_cache->in_init= 0; - - return error; -} - -static bool resize_keycache(THD *thd, KEY_CACHE *key_cache, - ptrdiff_t offset, ulonglong new_value) -{ - return update_keycache(thd, key_cache, offset, new_value, - ha_resize_key_cache); -} - -static bool change_keycache_param(THD *thd, KEY_CACHE *key_cache, - ptrdiff_t offset, ulonglong new_value) -{ - return update_keycache(thd, key_cache, offset, new_value, - ha_change_key_cache_param); -} - -static bool repartition_keycache(THD *thd, KEY_CACHE *key_cache, - ptrdiff_t offset, ulonglong new_value) -{ - return update_keycache(thd, key_cache, offset, new_value, - ha_repartition_key_cache); -} - - -/** - The class for floating point variables - - Class specific constructor arguments: min, max - - Backing store: double -*/ -class Sys_var_double: public sys_var -{ -public: - Sys_var_double(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - double min_val, double max_val, double def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_DOUBLE, - (longlong) getopt_double2ulonglong(def_val), - lock, binlog_status_arg, on_check_func, on_update_func, - substitute) - { - option.var_type|= GET_DOUBLE; - option.min_value= (longlong) getopt_double2ulonglong(min_val); - option.max_value= (longlong) getopt_double2ulonglong(max_val); - global_var(double)= (double)option.def_value; - SYSVAR_ASSERT(min_val < max_val); - SYSVAR_ASSERT(min_val <= def_val); - SYSVAR_ASSERT(max_val >= def_val); - SYSVAR_ASSERT(size == sizeof(double)); - } - bool do_check(THD *thd, set_var *var) - { - my_bool fixed; - double v= var->value->val_real(); - var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed); - - return throw_bounds_warning(thd, name.str, fixed, v); - } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, double)= var->save_result.double_value; - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(double)= var->save_result.double_value; - return false; - } - void session_save_default(THD *thd, set_var *var) - { var->save_result.double_value= global_var(double); } - void global_save_default(THD *thd, set_var *var) - { var->save_result.double_value= getopt_ulonglong2double(option.def_value); } -}; - -/** - The class for the @max_user_connections. - It's derived from Sys_var_uint, but non-standard session value - requires a new class. - - Class specific constructor arguments: - everything derived from Sys_var_uint - - Backing store: uint -*/ -class Sys_var_max_user_conn: public Sys_var_int -{ -public: - Sys_var_max_user_conn(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - int min_val, int max_val, int def_val, - uint block_size, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : Sys_var_int(name_arg, comment, SESSION, off, size, getopt, - min_val, max_val, def_val, block_size, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute) - { } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - if (thd->user_connect && thd->user_connect->user_resources.user_conn) - return (uchar*) &(thd->user_connect->user_resources.user_conn); - return global_value_ptr(thd, base); - } -}; - -/** - The class for flagset variables - a variant of SET that allows in-place - editing (turning on/off individual bits). String representations looks like - a "flag=val,flag=val,...". Example: @@optimizer_switch - - Class specific constructor arguments: - char* values[] - 0-terminated list of strings of valid values - - Backing store: ulonglong - - @note - the last value in the values[] array should - *always* be the string "default". -*/ -class Sys_var_flagset: public Sys_var_typelib -{ -public: - Sys_var_flagset(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - const char *values[], ulonglong def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, - SHOW_CHAR, values, def_val, lock, - binlog_status_arg, on_check_func, on_update_func, - substitute) - { - option.var_type|= GET_FLAGSET; - global_var(ulonglong)= def_val; - SYSVAR_ASSERT(typelib.count > 1); - SYSVAR_ASSERT(typelib.count <= 65); - SYSVAR_ASSERT(def_val < my_set_bits(typelib.count)); - SYSVAR_ASSERT(strcmp(values[typelib.count-1], "default") == 0); - SYSVAR_ASSERT(size == sizeof(ulonglong)); - } - bool do_check(THD *thd, set_var *var) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), system_charset_info), *res; - ulonglong default_value, current_value; - if (var->type == OPT_GLOBAL) - { - default_value= option.def_value; - current_value= global_var(ulonglong); - } - else - { - default_value= global_var(ulonglong); - current_value= session_var(thd, ulonglong); - } - - if (var->value->result_type() == STRING_RESULT) - { - if (!(res=var->value->val_str(&str))) - return true; - else - { - char *error; - uint error_len; - - var->save_result.ulonglong_value= - find_set_from_flags(&typelib, - typelib.count, - current_value, - default_value, - res->ptr(), res->length(), - &error, &error_len); - if (error) - { - ErrConvString err(error, error_len, res->charset()); - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); - return true; - } - } - } - else - { - longlong tmp=var->value->val_int(); - if ((tmp < 0 && ! var->value->unsigned_flag) - || (ulonglong)tmp > my_set_bits(typelib.count)) - return true; - else - var->save_result.ulonglong_value= tmp; - } - - return false; - } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, ulonglong)= var->save_result.ulonglong_value; - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(ulonglong)= var->save_result.ulonglong_value; - return false; - } - void session_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= global_var(ulonglong); } - void global_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= option.def_value; } - uchar *valptr(THD *thd, ulonglong val) - { return (uchar*)flagset_to_string(thd, 0, val, typelib.type_names); } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, session_var(thd, ulonglong)); } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, global_var(ulonglong)); } - uchar *default_value_ptr(THD *thd) - { return valptr(thd, option.def_value); } -}; - -/** - The class for SET variables - variables taking zero or more values - from the given list. Example: @@sql_mode - - Class specific constructor arguments: - char* values[] - 0-terminated list of strings of valid values - - Backing store: ulonglong -*/ -class Sys_var_set: public Sys_var_typelib -{ -public: - Sys_var_set(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - const char *values[], ulonglong def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, - SHOW_CHAR, values, def_val, lock, - binlog_status_arg, on_check_func, on_update_func, - substitute) - { - option.var_type|= GET_SET; - option.min_value= 0; - option.max_value= ~0ULL; - global_var(ulonglong)= def_val; - if ((option.u_max_value= (uchar**)max_var_ptr())) - { - *((ulonglong*) option.u_max_value)= ~0ULL; - } - SYSVAR_ASSERT(typelib.count > 0); - SYSVAR_ASSERT(typelib.count <= 64); - SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count)); - SYSVAR_ASSERT(size == sizeof(ulonglong)); - } - bool check_maximum(THD *thd, set_var *var, - const char *c_val, longlong i_val) - { - if (!max_var_ptr() || - (var->save_result.ulonglong_value & ~(get_max_var())) == 0) - return FALSE; - var->save_result.ulonglong_value&= get_max_var(); - - return c_val ? throw_bounds_warning(thd, name.str, c_val) : - throw_bounds_warning(thd, name.str, TRUE, - var->value->unsigned_flag, i_val); - } - bool do_check(THD *thd, set_var *var) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (var->value->result_type() == STRING_RESULT) - { - char *error; - uint error_len; - bool not_used; - - if (!(res=var->value->val_str_ascii(&str))) - return true; - - var->save_result.ulonglong_value= - find_set(&typelib, res->ptr(), res->length(), NULL, - &error, &error_len, ¬_used); - /* - note, we only issue an error if error_len > 0. - That is even while empty (zero-length) values are considered - errors by find_set(), these errors are ignored here - */ - if (error_len) - { - ErrConvString err(error, error_len, res->charset()); - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); - return true; - } - return check_maximum(thd, var, res->ptr(), 0); - } - - longlong tmp=var->value->val_int(); - if ((tmp < 0 && ! var->value->unsigned_flag) - || (ulonglong)tmp > my_set_bits(typelib.count)) - return true; - - var->save_result.ulonglong_value= tmp; - return check_maximum(thd, var, 0, tmp); - } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, ulonglong)= var->save_result.ulonglong_value; - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(ulonglong)= var->save_result.ulonglong_value; - return false; - } - void session_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= global_var(ulonglong); } - void global_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= option.def_value; } - uchar *valptr(THD *thd, ulonglong val) - { return (uchar*)set_to_string(thd, 0, val, typelib.type_names); } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, session_var(thd, ulonglong)); } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, global_var(ulonglong)); } - uchar *default_value_ptr(THD *thd) - { return valptr(thd, option.def_value); } - - ulonglong get_max_var() { return *((ulonglong*) max_var_ptr()); } -}; - -/** - The class for variables which value is a plugin. - Example: @@default_storage_engine - - Class specific constructor arguments: - int plugin_type_arg (for example MYSQL_STORAGE_ENGINE_PLUGIN) - - Backing store: plugin_ref - - @note - these variables don't support command-line equivalents, any such - command-line options should be added manually to my_long_options in mysqld.cc -*/ -class Sys_var_plugin: public sys_var -{ - int plugin_type; -public: - Sys_var_plugin(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - int plugin_type_arg, char **def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, (intptr)def_val, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute), - plugin_type(plugin_type_arg) - { - option.var_type|= GET_STR; - SYSVAR_ASSERT(size == sizeof(plugin_ref)); - SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE - } - bool do_check(THD *thd, set_var *var) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff,sizeof(buff), system_charset_info), *res; - if (!(res=var->value->val_str(&str))) - var->save_result.plugin= NULL; - else - { - const LEX_STRING pname= { const_cast(res->ptr()), res->length() }; - plugin_ref plugin; - - // special code for storage engines (e.g. to handle historical aliases) - if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) - plugin= ha_resolve_by_name(thd, &pname, false); - else - plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); - if (!plugin) - { - // historically different error code - if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) - { - ErrConvString err(res); - my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr()); - } - return true; - } - var->save_result.plugin= plugin; - } - return false; - } - void do_update(plugin_ref *valptr, plugin_ref newval) - { - plugin_ref oldval= *valptr; - if (oldval != newval) - { - *valptr= newval ? my_plugin_lock(NULL, newval) : 0; - plugin_unlock(NULL, oldval); - } - } - bool session_update(THD *thd, set_var *var) - { - do_update((plugin_ref*)session_var_ptr(thd), - var->save_result.plugin); - return false; - } - bool global_update(THD *thd, set_var *var) - { - do_update((plugin_ref*)global_var_ptr(), - var->save_result.plugin); - return false; - } - void session_save_default(THD *thd, set_var *var) - { - plugin_ref plugin= global_var(plugin_ref); - var->save_result.plugin= plugin ? my_plugin_lock(thd, plugin) : 0; - } - plugin_ref get_default(THD *thd) - { - char *default_value= *reinterpret_cast(option.def_value); - if (!default_value) - return 0; - - LEX_STRING pname= { default_value, strlen(pname.str) }; - plugin_ref plugin; - - if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) - plugin= ha_resolve_by_name(thd, &pname, false); - else - plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); - DBUG_ASSERT(plugin); - return my_plugin_lock(thd, plugin); - } - - void global_save_default(THD *thd, set_var *var) - { - var->save_result.plugin= get_default(thd); - } - - uchar *valptr(THD *thd, plugin_ref plugin) - { - return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, - plugin_name(plugin)->length) : 0); - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, session_var(thd, plugin_ref)); } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, global_var(plugin_ref)); } - uchar *default_value_ptr(THD *thd) - { return valptr(thd, get_default(thd)); } -}; - -#if defined(ENABLED_DEBUG_SYNC) - -#include "debug_sync.h" - -/** - The class for @@debug_sync session-only variable -*/ -class Sys_var_debug_sync :public sys_var -{ -public: - Sys_var_debug_sync(const char *name_arg, - const char *comment, int flag_args, - CMD_LINE getopt, - const char *def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, - getopt.arg_type, SHOW_CHAR, (intptr)def_val, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute) - { - SYSVAR_ASSERT(scope() == ONLY_SESSION); - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (!(res=var->value->val_str(&str))) - var->save_result.string_value= empty_lex_str; - else - { - if (!thd->make_lex_string(&var->save_result.string_value, - res->ptr(), res->length())) - return true; - } - return false; - } - bool session_update(THD *thd, set_var *var) - { - return debug_sync_update(thd, var->save_result.string_value.str, - var->save_result.string_value.length); - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - void session_save_default(THD *thd, set_var *var) - { - var->save_result.string_value.str= const_cast(""); - var->save_result.string_value.length= 0; - } - void global_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - return debug_sync_value_ptr(thd); - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(FALSE); - return 0; - } - uchar *default_value_ptr(THD *thd) - { return (uchar*)""; } -}; -#endif /* defined(ENABLED_DEBUG_SYNC) */ - - -/** - The class for bit variables - a variant of boolean that stores the value - in a bit. - - Class specific constructor arguments: - ulonglong bitmask_arg - the mask for the bit to set in the ulonglong - backing store - - Backing store: ulonglong - - @note - This class supports the "reverse" semantics, when the value of the bit - being 0 corresponds to the value of variable being set. To activate it - use REVERSE(bitmask) instead of simply bitmask in the constructor. - - @note - variables of this class cannot be set from the command line as - my_getopt does not support bits. -*/ -class Sys_var_bit: public Sys_var_typelib -{ - ulonglong bitmask; - bool reverse_semantics; - void set(uchar *ptr, ulonglong value) - { - if ((value != 0) ^ reverse_semantics) - (*(ulonglong *)ptr)|= bitmask; - else - (*(ulonglong *)ptr)&= ~bitmask; - } -public: - Sys_var_bit(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, - SHOW_MY_BOOL, bool_values, def_val, lock, - binlog_status_arg, on_check_func, on_update_func, - substitute) - { - option.var_type|= GET_BOOL; - reverse_semantics= my_count_bits(bitmask_arg) > 1; - bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg; - set(global_var_ptr(), def_val); - SYSVAR_ASSERT(def_val < 2); - SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE - SYSVAR_ASSERT(size == sizeof(ulonglong)); - } - bool session_update(THD *thd, set_var *var) - { - set(session_var_ptr(thd), var->save_result.ulonglong_value); - return false; - } - bool global_update(THD *thd, set_var *var) - { - set(global_var_ptr(), var->save_result.ulonglong_value); - return false; - } - void session_save_default(THD *thd, set_var *var) - { - var->save_result.ulonglong_value= - (reverse_semantics == !(global_var(ulonglong) & bitmask)); - } - void global_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= option.def_value; } - - uchar *valptr(THD *thd, ulonglong val) - { - thd->sys_var_tmp.my_bool_value= (reverse_semantics == !(val & bitmask)); - return (uchar*) &thd->sys_var_tmp.my_bool_value; - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, session_var(thd, ulonglong)); } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, global_var(ulonglong)); } - uchar *default_value_ptr(THD *thd) - { - thd->sys_var_tmp.my_bool_value= option.def_value != 0; - return (uchar*) &thd->sys_var_tmp.my_bool_value; - } -}; - -/** - The class for variables that have a special meaning for a session, - such as @@timestamp or @@rnd_seed1, their values typically cannot be read - from SV structure, and a special "read" callback is provided. - - Class specific constructor arguments: - everything derived from Sys_var_ulonglong - session_special_read_function read_func_arg - - Backing store: ulonglong - - @note - These variables are session-only, global or command-line equivalents - are not supported as they're generally meaningless. -*/ -class Sys_var_session_special: public Sys_var_ulonglong -{ - typedef bool (*session_special_update_function)(THD *thd, set_var *var); - typedef ulonglong (*session_special_read_function)(THD *thd); - - session_special_read_function read_func; - session_special_update_function update_func; -public: - Sys_var_session_special(const char *name_arg, - const char *comment, int flag_args, - CMD_LINE getopt, - ulonglong min_val, ulonglong max_val, uint block_size, - PolyLock *lock, enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func, - session_special_update_function update_func_arg, - session_special_read_function read_func_arg, - const char *substitute=0) - : Sys_var_ulonglong(name_arg, comment, flag_args, 0, - sizeof(ulonglong), getopt, min_val, - max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0, - substitute), - read_func(read_func_arg), update_func(update_func_arg) - { - SYSVAR_ASSERT(scope() == ONLY_SESSION); - SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake - } - bool session_update(THD *thd, set_var *var) - { return update_func(thd, var); } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - void session_save_default(THD *thd, set_var *var) - { var->value= 0; } - void global_save_default(THD *thd, set_var *var) - { DBUG_ASSERT(FALSE); } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - thd->sys_var_tmp.ulonglong_value= read_func(thd); - return (uchar*) &thd->sys_var_tmp.ulonglong_value; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(FALSE); - return 0; - } - uchar *default_value_ptr(THD *thd) - { - thd->sys_var_tmp.ulonglong_value= 0; - return (uchar*) &thd->sys_var_tmp.ulonglong_value; - } -}; - - -/* - Dedicated class because of a weird behavior of a default value. - Assigning timestamp to itself - - SET @@timestamp = @@timestamp - - make it non-default and stops the time flow. -*/ -class Sys_var_timestamp: public Sys_var_double -{ -public: - Sys_var_timestamp(const char *name_arg, - const char *comment, int flag_args, - CMD_LINE getopt, - double min_val, double max_val, - PolyLock *lock, enum binlog_status_enum binlog_status_arg) - : Sys_var_double(name_arg, comment, flag_args, 0, - sizeof(double), getopt, min_val, - max_val, 0, lock, binlog_status_arg) - { - SYSVAR_ASSERT(scope() == ONLY_SESSION); - SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake - } - bool session_update(THD *thd, set_var *var) - { - if (var->value) - { - my_hrtime_t hrtime = { hrtime_from_time(var->save_result.double_value) }; - thd->set_time(hrtime); - } - else // SET timestamp=DEFAULT - thd->user_time.val= 0; - return false; - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - bool session_is_default(THD *thd) - { - return thd->user_time.val == 0; - } - void session_save_default(THD *thd, set_var *var) - { var->value= 0; } - void global_save_default(THD *thd, set_var *var) - { DBUG_ASSERT(FALSE); } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - thd->sys_var_tmp.double_value= thd->start_time + - thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR; - return (uchar*) &thd->sys_var_tmp.double_value; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(FALSE); - return 0; - } - uchar *default_value_ptr(THD *thd) - { - thd->sys_var_tmp.double_value= 0; - return (uchar*) &thd->sys_var_tmp.double_value; - } -}; - - -/** - The class for read-only variables that show whether a particular - feature is supported by the server. Example: have_compression - - Backing store: enum SHOW_COMP_OPTION - - @note - These variables are necessarily read-only, only global, and have no - command-line equivalent. -*/ -class Sys_var_have: public sys_var -{ -public: - Sys_var_have(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, 0, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute) - { - SYSVAR_ASSERT(scope() == GLOBAL); - SYSVAR_ASSERT(getopt.id < 0); - SYSVAR_ASSERT(lock == 0); - SYSVAR_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG); - SYSVAR_ASSERT(is_readonly()); - SYSVAR_ASSERT(on_update == 0); - SYSVAR_ASSERT(size == sizeof(enum SHOW_COMP_OPTION)); - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var) { - DBUG_ASSERT(FALSE); - return true; - } - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(FALSE); - return true; - } - void session_save_default(THD *thd, set_var *var) { } - void global_save_default(THD *thd, set_var *var) { } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(FALSE); - return 0; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)]; - } -}; - -/** - Generic class for variables for storing entities that are internally - represented as structures, have names, and possibly can be referred to by - numbers. Examples: character sets, collations, locales, - - Class specific constructor arguments: - ptrdiff_t name_offset - offset of the 'name' field in the structure - - Backing store: void* - - @note - As every such a structure requires special treatment from my_getopt, - these variables don't support command-line equivalents, any such - command-line options should be added manually to my_long_options in mysqld.cc -*/ -class Sys_var_struct: public sys_var -{ - ptrdiff_t name_offset; // offset to the 'name' property in the structure -public: - Sys_var_struct(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - ptrdiff_t name_off, void *def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, (intptr)def_val, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute), - name_offset(name_off) - { - option.var_type|= GET_ENUM; // because we accept INT and STRING here - /* - struct variables are special on the command line - often (e.g. for - charsets) the name cannot be immediately resolved, but only after all - options (in particular, basedir) are parsed. - - thus all struct command-line options should be added manually - to my_long_options in mysqld.cc - */ - SYSVAR_ASSERT(getopt.id < 0); - SYSVAR_ASSERT(size == sizeof(void *)); - } - bool do_check(THD *thd, set_var *var) - { return false; } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, const void*)= var->save_result.ptr; - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(const void*)= var->save_result.ptr; - return false; - } - void session_save_default(THD *thd, set_var *var) - { var->save_result.ptr= global_var(void*); } - void global_save_default(THD *thd, set_var *var) - { - void **default_value= reinterpret_cast(option.def_value); - var->save_result.ptr= *default_value; - } - uchar *valptr(THD *thd, uchar *val) - { return val ? *(uchar**)(val+name_offset) : 0; } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, session_var(thd, uchar*)); } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, global_var(uchar*)); } - uchar *default_value_ptr(THD *thd) - { return valptr(thd, *(uchar**)option.def_value); } -}; - -/** - The class for variables that store time zones - - Backing store: Time_zone* - - @note - Time zones cannot be supported directly by my_getopt, thus - these variables don't support command-line equivalents, any such - command-line options should be added manually to my_long_options in mysqld.cc -*/ -class Sys_var_tz: public sys_var -{ -public: - Sys_var_tz(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - Time_zone **def_val, PolyLock *lock=0, - enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, - on_check_function on_check_func=0, - on_update_function on_update_func=0, - const char *substitute=0) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, (intptr)def_val, - lock, binlog_status_arg, on_check_func, on_update_func, - substitute) - { - SYSVAR_ASSERT(getopt.id < 0); - SYSVAR_ASSERT(size == sizeof(Time_zone *)); - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var) - { - char buff[MAX_TIME_ZONE_NAME_LENGTH]; - String str(buff, sizeof(buff), &my_charset_latin1); - String *res= var->value->val_str(&str); - - if (!res) - return true; - - if (!(var->save_result.time_zone= my_tz_find(thd, res))) - { - ErrConvString err(res); - my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr()); - return true; - } - return false; - } - bool session_update(THD *thd, set_var *var) - { - session_var(thd, Time_zone*)= var->save_result.time_zone; - return false; - } - bool global_update(THD *thd, set_var *var) - { - global_var(Time_zone*)= var->save_result.time_zone; - return false; - } - void session_save_default(THD *thd, set_var *var) - { - var->save_result.time_zone= global_var(Time_zone*); - } - void global_save_default(THD *thd, set_var *var) - { - var->save_result.time_zone= - *(Time_zone**)(intptr)option.def_value; - } - uchar *valptr(THD *thd, Time_zone *val) - { return (uchar *)(val->get_name()->ptr()); } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - /* - This is an ugly fix for replication: we don't replicate properly queries - invoking system variables' values to update tables; but - CONVERT_TZ(,,@@session.time_zone) is so popular that we make it - replicable (i.e. we tell the binlog code to store the session - timezone). If it's the global value which was used we can't replicate - (binlog code stores session value only). - */ - thd->time_zone_used= 1; - return valptr(thd, session_var(thd, Time_zone *)); - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { return valptr(thd, global_var(Time_zone*)); } - uchar *default_value_ptr(THD *thd) - { return valptr(thd, *(Time_zone**)option.def_value); } -}; - -/** - Special implementation for transaction isolation, that - distingushes between - - SET GLOBAL TRANSACTION ISOLATION (stored in global_system_variables) - SET SESSION TRANSACTION ISOLATION (stored in thd->variables) - SET TRANSACTION ISOLATION (stored in thd->tx_isolation) - - where the last statement sets isolation level for the next transaction only -*/ -class Sys_var_tx_isolation: public Sys_var_enum -{ -public: - Sys_var_tx_isolation(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - const char *values[], uint def_val, PolyLock *lock, - enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func) - :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, - values, def_val, lock, binlog_status_arg, on_check_func) - {} - bool session_update(THD *thd, set_var *var) - { - if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var)) - return TRUE; - if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction()) - { -#ifndef EMBEDDED_LIBRARY - Transaction_state_tracker *tst= NULL; - - if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) - tst= (Transaction_state_tracker *) - thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER); -#endif //EMBEDDED_LIBRARY - - thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value; - -#ifndef EMBEDDED_LIBRARY - if (var->type == OPT_DEFAULT) - { - enum enum_tx_isol_level l; - switch (thd->tx_isolation) { - case ISO_READ_UNCOMMITTED: - l= TX_ISOL_UNCOMMITTED; - break; - case ISO_READ_COMMITTED: - l= TX_ISOL_COMMITTED; - break; - case ISO_REPEATABLE_READ: - l= TX_ISOL_REPEATABLE; - break; - case ISO_SERIALIZABLE: - l= TX_ISOL_SERIALIZABLE; - break; - default: - DBUG_ASSERT(0); - return TRUE; - } - if (tst) - tst->set_isol_level(thd, l); - } - else if (tst) - { - tst->set_isol_level(thd, TX_ISOL_INHERIT); - } -#endif //EMBEDDED_LIBRARY - } - return FALSE; - } -}; - - -/** - Class representing the tx_read_only system variable for setting - default transaction access mode. - - Note that there is a special syntax - SET TRANSACTION READ ONLY - (or READ WRITE) that sets the access mode for the next transaction - only. -*/ - -class Sys_var_tx_read_only: public Sys_var_mybool -{ -public: - Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args, - ptrdiff_t off, size_t size, CMD_LINE getopt, - my_bool def_val, PolyLock *lock, - enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func) - :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt, - def_val, lock, binlog_status_arg, on_check_func) - {} - virtual bool session_update(THD *thd, set_var *var); -}; - -/* - Class for replicate_events_marked_for_skip. - We need a custom update function that ensures the slave is stopped when - the update is happening. -*/ -class Sys_var_replicate_events_marked_for_skip: public Sys_var_enum -{ -public: - Sys_var_replicate_events_marked_for_skip(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, - const char *values[], uint def_val, PolyLock *lock= 0, - enum binlog_status_enum binlog_status_arg= VARIABLE_NOT_IN_BINLOG) - :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, - values, def_val, lock, binlog_status_arg) - {} - bool global_update(THD *thd, set_var *var); -}; - -/* - Class for handing multi-source replication variables - Variable values are store in Master_info, but to make it possible to - access variable without locks we also store it thd->variables. - These can be used as GLOBAL or SESSION, but both points to the same - variable. This is to make things compatible with MySQL 5.5 where variables - like sql_slave_skip_counter are GLOBAL. -*/ - -#define MASTER_INFO_VAR(X) my_offsetof(Master_info, X), sizeof(((Master_info *)0x10)->X) -class Sys_var_multi_source_ulonglong; -class Master_info; - -typedef bool (*on_multi_source_update_function)(sys_var *self, THD *thd, - Master_info *mi); -bool update_multi_source_variable(sys_var *self, - THD *thd, enum_var_type type); - - -class Sys_var_multi_source_ulonglong :public Sys_var_ulonglong -{ - ptrdiff_t master_info_offset; - on_multi_source_update_function update_multi_source_variable_func; -public: - Sys_var_multi_source_ulonglong(const char *name_arg, - const char *comment, int flag_args, - ptrdiff_t off, size_t size, - CMD_LINE getopt, - ptrdiff_t master_info_offset_arg, - size_t master_info_arg_size, - ulonglong min_val, ulonglong max_val, - ulonglong def_val, uint block_size, - on_multi_source_update_function on_update_func) - :Sys_var_ulonglong(name_arg, comment, flag_args, off, size, - getopt, min_val, max_val, def_val, block_size, - 0, VARIABLE_NOT_IN_BINLOG, 0, update_multi_source_variable), - master_info_offset(master_info_offset_arg), - update_multi_source_variable_func(on_update_func) - { - SYSVAR_ASSERT(master_info_arg_size == size); - } - bool global_update(THD *thd, set_var *var) - { - return session_update(thd, var); - } - void session_save_default(THD *thd, set_var *var) - { - /* Use value given in variable declaration */ - global_save_default(thd, var); - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - ulonglong *tmp, res; - tmp= (ulonglong*) (((uchar*)&(thd->variables)) + offset); - res= get_master_info_ulonglong_value(thd, master_info_offset); - *tmp= res; - return (uchar*) tmp; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - return session_value_ptr(thd, base); - } - ulonglong get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset); - bool update_variable(THD *thd, Master_info *mi) - { - return update_multi_source_variable_func(this, thd, mi); - } -}; - - -/** - Class for @@global.gtid_current_pos. -*/ -class Sys_var_gtid_current_pos: public sys_var -{ -public: - Sys_var_gtid_current_pos(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, NULL) - { - SYSVAR_ASSERT(getopt.id < 0); - SYSVAR_ASSERT(is_readonly()); - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - void session_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - void global_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(false); - return NULL; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base); -}; - - -/** - Class for @@global.gtid_binlog_pos. -*/ -class Sys_var_gtid_binlog_pos: public sys_var -{ -public: - Sys_var_gtid_binlog_pos(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, NULL) - { - SYSVAR_ASSERT(getopt.id < 0); - SYSVAR_ASSERT(is_readonly()); - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - void session_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - void global_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(false); - return NULL; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base); -}; - - -/** - Class for @@global.gtid_slave_pos. -*/ -class Sys_var_gtid_slave_pos: public sys_var -{ -public: - Sys_var_gtid_slave_pos(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, NULL) - { - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var); - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool global_update(THD *thd, set_var *var); - void session_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - void global_save_default(THD *thd, set_var *var) - { - /* Record the attempt to use default so we can error. */ - var->value= 0; - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(false); - return NULL; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base); - uchar *default_value_ptr(THD *thd) - { return 0; } -}; - - -/** - Class for @@global.gtid_binlog_state. -*/ -class Sys_var_gtid_binlog_state: public sys_var -{ -public: - Sys_var_gtid_binlog_state(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, - getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, NULL) - { - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var); - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool global_update(THD *thd, set_var *var); - void session_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - void global_save_default(THD *thd, set_var *var) - { - /* Record the attempt to use default so we can error. */ - var->value= 0; - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(false); - return NULL; - } - uchar *global_value_ptr(THD *thd, const LEX_STRING *base); - uchar *default_value_ptr(THD *thd) - { return 0; } -}; - - -/** - Class for @@session.last_gtid. -*/ -class Sys_var_last_gtid: public sys_var -{ -public: - Sys_var_last_gtid(const char *name_arg, - const char *comment, int flag_args, CMD_LINE getopt) - : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, - getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, NULL) - { - SYSVAR_ASSERT(getopt.id < 0); - SYSVAR_ASSERT(is_readonly()); - option.var_type|= GET_STR; - } - bool do_check(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool session_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - bool global_update(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - return true; - } - void session_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - void global_save_default(THD *thd, set_var *var) - { - DBUG_ASSERT(false); - } - uchar *session_value_ptr(THD *thd, const LEX_STRING *base); - uchar *global_value_ptr(THD *thd, const LEX_STRING *base) - { - DBUG_ASSERT(false); - return NULL; - } -}; - - -/** - Class for connection_name.slave_parallel_mode. -*/ -class Sys_var_slave_parallel_mode: public Sys_var_enum -{ -public: - Sys_var_slave_parallel_mode(const char *name_arg, - const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, const char *values[], - enum_slave_parallel_mode def_val) - : Sys_var_enum(name_arg, comment, flag_args, off, size, - getopt, values, def_val) - { - option.var_type|= GET_ASK_ADDR; - option.value= (uchar**)1; // crash me, please - SYSVAR_ASSERT(scope() == GLOBAL); - } - bool global_update(THD *thd, set_var *var); - uchar *global_value_ptr(THD *thd, const LEX_STRING *base); -}; diff --git a/sql/sys_vars.inl b/sql/sys_vars.inl new file mode 100644 index 00000000000..3c3cfb8c8a6 --- /dev/null +++ b/sql/sys_vars.inl @@ -0,0 +1,2527 @@ +/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. + Copyright (c) 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + "private" interface to sys_var - server configuration variables. + + This header is included only by the file that contains declarations + of sys_var variables (sys_vars.cc). +*/ + +#include "sys_vars_shared.h" +#include +#include +#include +#include "keycaches.h" +#include "strfunc.h" +#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone +#include "rpl_mi.h" // For Multi-Source Replication +#include "debug_sync.h" + +/* + a set of mostly trivial (as in f(X)=X) defines below to make system variable + declarations more readable +*/ +#define VALID_RANGE(X,Y) X,Y +#define DEFAULT(X) X +#define BLOCK_SIZE(X) X +#define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X) +#define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) +#define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) +#define NO_CMD_LINE CMD_LINE(NO_ARG, sys_var::NO_GETOPT) +#define CMD_LINE_HELP_ONLY CMD_LINE(NO_ARG, sys_var::GETOPT_ONLY_HELP) +/* + the define below means that there's no *second* mutex guard, + LOCK_global_system_variables always guards all system variables +*/ +#define NO_MUTEX_GUARD ((PolyLock*)0) +#define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG +#define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG +#define ON_READ(X) X +#define ON_CHECK(X) X +#define ON_UPDATE(X) X +#define READ_ONLY sys_var::READONLY+ +#define AUTO_SET sys_var::AUTO_SET+ +// this means that Sys_var_charptr initial value was malloc()ed +#define PREALLOCATED sys_var::ALLOCATED+ +#define PARSED_EARLY sys_var::PARSE_EARLY+ +#define NO_SET_STMT sys_var::NO_SET_STATEMENT+ + +/* + Sys_var_bit meaning is reversed, like in + @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS +*/ +#define REVERSE(X) ~(X) +#define DEPRECATED(X) X + +#define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD)) +#define global_var(TYPE) (*(TYPE*)global_var_ptr()) + +#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) +#define GET_HA_ROWS GET_ULL +#else +#define GET_HA_ROWS GET_ULONG +#endif + +/* + special assert for sysvars. Tells the name of the variable, + and fails even in non-debug builds. + + It is supposed to be used *only* in Sys_var* constructors, + and has name_arg hard-coded to prevent incorrect usage. +*/ +#define SYSVAR_ASSERT(X) \ + while(!(X)) \ + { \ + fprintf(stderr, "Sysvar '%s' failed '%s'\n", name_arg, #X); \ + DBUG_ABORT(); \ + exit(255); \ + } + +enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET}; + +static const char *bool_values[3]= {"OFF", "ON", 0}; +TYPELIB bool_typelib={ array_elements(bool_values)-1, "", bool_values, 0 }; + +/** + A small wrapper class to pass getopt arguments as a pair + to the Sys_var_* constructors. It improves type safety and helps + to catch errors in the argument order. +*/ +struct CMD_LINE +{ + int id; + enum get_opt_arg_type arg_type; + CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0) + : id(getopt_id), arg_type(getopt_arg_type) {} +}; + +/** + Sys_var_integer template is used to generate Sys_var_* classes + for variables that represent the value as an integer number. + They are Sys_var_uint, Sys_var_ulong, Sys_var_harows, Sys_var_ulonglong, + Sys_var_int. + + An integer variable has a minimal and maximal values, and a "block_size" + (any valid value of the variable must be divisible by the block_size). + + Class specific constructor arguments: min, max, block_size + Backing store: int, uint, ulong, ha_rows, ulonglong, depending on the class +*/ +template +class Sys_var_integer: public sys_var +{ +public: + Sys_var_integer(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg, + on_check_func, on_update_func, substitute) + { + option.var_type|= ARGT; + option.min_value= min_val; + option.max_value= max_val; + option.block_size= block_size; + if ((option.u_max_value= (uchar**) max_var_ptr())) + { + *((T*) option.u_max_value)= max_val; + } + + global_var(T)= def_val; + SYSVAR_ASSERT(size == sizeof(T)); + SYSVAR_ASSERT(min_val < max_val); + SYSVAR_ASSERT(min_val <= def_val); + SYSVAR_ASSERT(max_val >= def_val); + SYSVAR_ASSERT(block_size > 0); + SYSVAR_ASSERT(def_val % block_size == 0); + } + bool do_check(THD *thd, set_var *var) + { + my_bool fixed= FALSE, unused; + longlong v= var->value->val_int(); + + if ((ARGT == GET_HA_ROWS) || (ARGT == GET_UINT) || + (ARGT == GET_ULONG) || (ARGT == GET_ULL)) + { + ulonglong uv; + + /* + if the value is signed and negative, + and a variable is unsigned, it is set to zero + */ + if ((fixed= (!var->value->unsigned_flag && v < 0))) + uv= 0; + else + uv= v; + + var->save_result.ulonglong_value= + getopt_ull_limit_value(uv, &option, &unused); + + if (max_var_ptr() && (T)var->save_result.ulonglong_value > get_max_var()) + var->save_result.ulonglong_value= get_max_var(); + + fixed= fixed || var->save_result.ulonglong_value != uv; + } + else + { + /* + if the value is unsigned and has the highest bit set + and a variable is signed, it is set to max signed value + */ + if ((fixed= (var->value->unsigned_flag && v < 0))) + v= LONGLONG_MAX; + + var->save_result.longlong_value= + getopt_ll_limit_value(v, &option, &unused); + + if (max_var_ptr() && (T)var->save_result.longlong_value > get_max_var()) + var->save_result.longlong_value= get_max_var(); + + fixed= fixed || var->save_result.longlong_value != v; + } + return throw_bounds_warning(thd, name.str, fixed, + var->value->unsigned_flag, v); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, T)= static_cast(var->save_result.ulonglong_value); + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(T)= static_cast(var->save_result.ulonglong_value); + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + private: + T get_max_var() { return *((T*) max_var_ptr()); } + uchar *default_value_ptr(THD *thd) { return (uchar*) &option.def_value; } +}; + +typedef Sys_var_integer Sys_var_int; +typedef Sys_var_integer Sys_var_uint; +typedef Sys_var_integer Sys_var_ulong; +typedef Sys_var_integer Sys_var_harows; +typedef Sys_var_integer Sys_var_ulonglong; +typedef Sys_var_integer Sys_var_long; + + +template<> uchar *Sys_var_int::default_value_ptr(THD *thd) +{ + thd->sys_var_tmp.int_value= (int)option.def_value; + return (uchar*) &thd->sys_var_tmp.int_value; +} + +template<> uchar *Sys_var_uint::default_value_ptr(THD *thd) +{ + thd->sys_var_tmp.uint_value= (uint)option.def_value; + return (uchar*) &thd->sys_var_tmp.uint_value; +} + +template<> uchar *Sys_var_long::default_value_ptr(THD *thd) +{ + thd->sys_var_tmp.long_value= (long)option.def_value; + return (uchar*) &thd->sys_var_tmp.long_value; +} + +template<> uchar *Sys_var_ulong::default_value_ptr(THD *thd) +{ + thd->sys_var_tmp.ulong_value= (ulong)option.def_value; + return (uchar*) &thd->sys_var_tmp.ulong_value; +} + + +/** + Helper class for variables that take values from a TYPELIB +*/ +class Sys_var_typelib: public sys_var +{ +protected: + TYPELIB typelib; + virtual bool check_maximum(THD *thd, set_var *var, + const char *c_val, longlong i_val) + { return FALSE; } +public: + Sys_var_typelib(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, + CMD_LINE getopt, + SHOW_TYPE show_val_type_arg, const char *values[], + ulonglong def_val, PolyLock *lock, + enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, on_update_function on_update_func, + const char *substitute) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, show_val_type_arg, def_val, lock, + binlog_status_arg, on_check_func, + on_update_func, substitute) + { + for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */; + typelib.name=""; + typelib.type_names= values; + typelib.type_lengths= 0; // only used by Fields_enum and Field_set + option.typelib= &typelib; + } + bool do_check(THD *thd, set_var *var) // works for enums and my_bool + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (var->value->result_type() == STRING_RESULT) + { + if (!(res=var->value->val_str(&str))) + return true; + else + if (!(var->save_result.ulonglong_value= + find_type(&typelib, res->ptr(), res->length(), false))) + return true; + else + var->save_result.ulonglong_value--; + return check_maximum(thd, var, res->ptr(), 0); + } + + longlong tmp=var->value->val_int(); + if (tmp < 0 || tmp >= typelib.count) + return true; + var->save_result.ulonglong_value= tmp; + return check_maximum(thd, var, 0, tmp); + } +}; + +/** + The class for ENUM variables - variables that take one value from a fixed + list of values. + + Class specific constructor arguments: + char* values[] - 0-terminated list of strings of valid values + + Backing store: uint + + @note + Do *not* use "enum FOO" variables as a backing store, there is no + guarantee that sizeof(enum FOO) == sizeof(uint), there is no guarantee + even that sizeof(enum FOO) == sizeof(enum BAR) +*/ +class Sys_var_enum: public Sys_var_typelib +{ +public: + Sys_var_enum(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], uint def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_CHAR, values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + substitute) + { + option.var_type|= GET_ENUM; + option.min_value= 0; + option.max_value= ULONG_MAX; + global_var(ulong)= def_val; + if ((option.u_max_value= (uchar**)max_var_ptr())) + { + *((ulong *) option.u_max_value)= ULONG_MAX; + } + SYSVAR_ASSERT(def_val < typelib.count); + SYSVAR_ASSERT(size == sizeof(ulong)); + } + bool check_maximum(THD *thd, set_var *var, + const char *c_val, longlong i_val) + { + if (!max_var_ptr() || + var->save_result.ulonglong_value <= get_max_var()) + return FALSE; + var->save_result.ulonglong_value= get_max_var(); + + return c_val ? throw_bounds_warning(thd, name.str, c_val) : + throw_bounds_warning(thd, name.str, TRUE, + var->value->unsigned_flag, i_val); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, ulong)= static_cast(var->save_result.ulonglong_value); + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(ulong)= static_cast(var->save_result.ulonglong_value); + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= global_var(ulong); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *valptr(THD *thd, ulong val) + { return (uchar*)typelib.type_names[val]; } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, session_var(thd, ulong)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(ulong)); } + uchar *default_value_ptr(THD *thd) + { return valptr(thd, (ulong)option.def_value); } + + ulong get_max_var() { return *((ulong *) max_var_ptr()); } +}; + +/** + The class for boolean variables - a variant of ENUM variables + with the fixed list of values of { OFF , ON } + + Backing store: my_bool +*/ +class Sys_var_mybool: public Sys_var_typelib +{ +public: + Sys_var_mybool(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + my_bool def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_MY_BOOL, bool_values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + substitute) + { + option.var_type|= GET_BOOL; + global_var(my_bool)= def_val; + SYSVAR_ASSERT(def_val < 2); + SYSVAR_ASSERT(getopt.arg_type == OPT_ARG || getopt.id < 0); + SYSVAR_ASSERT(size == sizeof(my_bool)); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, my_bool)= var->save_result.ulonglong_value != 0; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(my_bool)= var->save_result.ulonglong_value != 0; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *default_value_ptr(THD *thd) + { + thd->sys_var_tmp.my_bool_value=(my_bool) option.def_value; + return (uchar*) &thd->sys_var_tmp.my_bool_value; + } +}; + +/** + The class for string variables. The string can be in character_set_filesystem + or in character_set_system. The string can be allocated with my_malloc() + or not. The state of the initial value is specified in the constructor, + after that it's managed automatically. The value of NULL is supported. + + Class specific constructor arguments: + enum charset_enum is_os_charset_arg + + Backing store: char* + + @note + This class supports only GLOBAL variables, because THD on destruction + does not destroy individual members of SV, there's no way to free + allocated string variables for every thread. +*/ +class Sys_var_charptr_base: public sys_var +{ +public: + Sys_var_charptr_base(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute) + { + is_os_charset= is_os_charset_arg == IN_FS_CHARSET; + /* + use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated, + otherwise (GET_STR) you'll never know whether to free it or not. + (think of an exit because of an error right after my_getopt) + */ + option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR; + global_var(const char*)= def_val; + } + void cleanup() + { + if (flags & ALLOCATED) + { + my_free(global_var(char*)); + global_var(char *)= NULL; + } + flags&= ~ALLOCATED; + } + static bool do_string_check(THD *thd, set_var *var, CHARSET_INFO *charset) + { + char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), charset); + String str2(buff2, sizeof(buff2), charset), *res; + + if (!(res=var->value->val_str(&str))) + var->save_result.string_value.str= 0; + else + { + uint32 unused; + if (String::needs_conversion(res->length(), res->charset(), + charset, &unused)) + { + uint errors; + str2.copy(res->ptr(), res->length(), res->charset(), charset, + &errors); + res=&str2; + + } + var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); + var->save_result.string_value.length= res->length(); + } + + return false; + } + bool do_check(THD *thd, set_var *var) + { return do_string_check(thd, var, charset(thd)); } + bool session_update(THD *thd, set_var *var)= 0; + char *global_update_prepare(THD *thd, set_var *var) + { + char *new_val, *ptr= var->save_result.string_value.str; + size_t len=var->save_result.string_value.length; + if (ptr) + { + new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME)); + if (!new_val) return 0; + new_val[len]=0; + } + else + new_val= 0; + return new_val; + } + void global_update_finish(char *new_val) + { + if (flags & ALLOCATED) + my_free(global_var(char*)); + flags|= ALLOCATED; + global_var(char*)= new_val; + } + bool global_update(THD *thd, set_var *var) + { + char *new_val= global_update_prepare(thd, var); + global_update_finish(new_val); + return (new_val == 0 && var->save_result.string_value.str != 0); + } + void session_save_default(THD *thd, set_var *var)= 0; + void global_save_default(THD *thd, set_var *var) + { + char *ptr= (char*)(intptr)option.def_value; + var->save_result.string_value.str= ptr; + var->save_result.string_value.length= ptr ? strlen(ptr) : 0; + } +}; + +class Sys_var_charptr: public Sys_var_charptr_base +{ +public: + Sys_var_charptr(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) : + Sys_var_charptr_base(name_arg, comment, flag_args, off, size, getopt, + is_os_charset_arg, def_val, lock, binlog_status_arg, + on_check_func, on_update_func, substitute) + { + SYSVAR_ASSERT(scope() == GLOBAL); + SYSVAR_ASSERT(size == sizeof(char *)); + } + + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + void session_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } +}; + +#ifndef EMBEDDED_LIBRARY +class Sys_var_sesvartrack: public Sys_var_charptr_base +{ +public: + Sys_var_sesvartrack(const char *name_arg, + const char *comment, + CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, PolyLock *lock) : + Sys_var_charptr_base(name_arg, comment, + SESSION_VAR(session_track_system_variables), + getopt, is_os_charset_arg, def_val, lock, + VARIABLE_NOT_IN_BINLOG, 0, 0, 0) + {} + bool do_check(THD *thd, set_var *var) + { + if (Sys_var_charptr_base::do_check(thd, var) || + sysvartrack_validate_value(thd, var->save_result.string_value.str, + var->save_result.string_value.length)) + return TRUE; + return FALSE; + } + bool global_update(THD *thd, set_var *var) + { + char *new_val= global_update_prepare(thd, var); + if (new_val) + { + if (sysvartrack_reprint_value(thd, new_val, + var->save_result.string_value.length)) + new_val= 0; + } + global_update_finish(new_val); + return (new_val == 0 && var->save_result.string_value.str != 0); + } + bool session_update(THD *thd, set_var *var) + { + return sysvartrack_update(thd, var); + } + void session_save_default(THD *thd, set_var *var) + { + var->save_result.string_value.str= global_var(char*); + var->save_result.string_value.length= + strlen(var->save_result.string_value.str); + /* parse and feel list with default values */ + if (thd) + { + IF_DBUG(bool res=,) + sysvartrack_validate_value(thd, + var->save_result.string_value.str, + var->save_result.string_value.length); + DBUG_ASSERT(res == 0); + } + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(thd != NULL); + size_t len= sysvartrack_value_len(thd); + char *res= (char *)thd->alloc(len + sizeof(char *)); + if (res) + { + char *buf= res + sizeof(char *); + *((char**) res)= buf; + sysvartrack_value_construct(thd, buf, len); + } + return (uchar *)res; + } +}; +#endif //EMBEDDED_LIBRARY + + +class Sys_var_proxy_user: public sys_var +{ +public: + Sys_var_proxy_user(const char *name_arg, + const char *comment, enum charset_enum is_os_charset_arg) + : sys_var(&all_sys_vars, name_arg, comment, + sys_var::READONLY+sys_var::ONLY_SESSION, 0, NO_GETOPT, + NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + is_os_charset= is_os_charset_arg == IN_FS_CHARSET; + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return false; + } + void session_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + void global_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } +protected: + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + return thd->security_ctx->proxy_user[0] ? + (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; + } +}; + +class Sys_var_external_user : public Sys_var_proxy_user +{ +public: + Sys_var_external_user(const char *name_arg, const char *comment_arg, + enum charset_enum is_os_charset_arg) + : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg) + {} + +protected: + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + return (uchar*)thd->security_ctx->external_user; + } +}; + +class Master_info; +class Sys_var_rpl_filter: public sys_var +{ +private: + int opt_id; + +public: + Sys_var_rpl_filter(const char *name, int getopt_id, const char *comment) + : sys_var(&all_sys_vars, name, comment, sys_var::GLOBAL, 0, NO_GETOPT, + NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL), opt_id(getopt_id) + { + option.var_type|= GET_STR | GET_ASK_ADDR; + } + + bool do_check(THD *thd, set_var *var) + { + return Sys_var_charptr::do_string_check(thd, var, charset(thd)); + } + void session_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + + void global_save_default(THD *thd, set_var *var) + { + char *ptr= (char*)(intptr)option.def_value; + var->save_result.string_value.str= ptr; + var->save_result.string_value.length= ptr ? strlen(ptr) : 0; + } + + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + + bool global_update(THD *thd, set_var *var); + +protected: + uchar *global_value_ptr(THD *thd, const LEX_STRING *base); + bool set_filter_value(const char *value, Master_info *mi); +}; + +/** + The class for string variables. Useful for strings that aren't necessarily + \0-terminated. Otherwise the same as Sys_var_charptr. + + Class specific constructor arguments: + enum charset_enum is_os_charset_arg + + Backing store: LEX_STRING + + @note + Behaves exactly as Sys_var_charptr, only the backing store is different. +*/ +class Sys_var_lexstring: public Sys_var_charptr +{ +public: + Sys_var_lexstring(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*), + getopt, is_os_charset_arg, def_val, lock, binlog_status_arg, + on_check_func, on_update_func, substitute) + { + global_var(LEX_STRING).length= strlen(def_val); + SYSVAR_ASSERT(size == sizeof(LEX_STRING)); + *const_cast(&show_val_type)= SHOW_LEX_STRING; + } + bool global_update(THD *thd, set_var *var) + { + if (Sys_var_charptr::global_update(thd, var)) + return true; + global_var(LEX_STRING).length= var->save_result.string_value.length; + return false; + } +}; + + +/* + A LEX_STRING stored only in thd->variables + Only to be used for small buffers +*/ + +class Sys_var_session_lexstring: public sys_var +{ + size_t max_length; +public: + Sys_var_session_lexstring(const char *name_arg, + const char *comment, int flag_args, + ptrdiff_t off, size_t size, CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, size_t max_length_arg, + on_check_function on_check_func=0, + on_update_function on_update_func=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + 0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func, + 0),max_length(max_length_arg) + { + option.var_type|= GET_STR; + SYSVAR_ASSERT(scope() == ONLY_SESSION) + *const_cast(&show_val_type)= SHOW_LEX_STRING; + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (!(res=var->value->val_str(&str))) + { + var->save_result.string_value.str= 0; /* NULL */ + var->save_result.string_value.length= 0; + } + else + { + if (res->length() > max_length) + { + my_error(ER_WRONG_STRING_LENGTH, MYF(0), + res->ptr(), name.str, (int) max_length); + return true; + } + var->save_result.string_value.str= thd->strmake(res->ptr(), + res->length()); + var->save_result.string_value.length= res->length(); + } + return false; + } + bool session_update(THD *thd, set_var *var) + { + LEX_STRING *tmp= &session_var(thd, LEX_STRING); + tmp->length= var->save_result.string_value.length; + /* Store as \0 terminated string (just to be safe) */ + strmake(tmp->str, var->save_result.string_value.str, tmp->length); + return false; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return false; + } + void session_save_default(THD *thd, set_var *var) + { + char *ptr= (char*)(intptr)option.def_value; + var->save_result.string_value.str= ptr; + var->save_result.string_value.length= strlen(ptr); + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return NULL; + } +}; + + +#ifndef DBUG_OFF +/** + @@session.debug_dbug and @@global.debug_dbug variables. + + @@dbug variable differs from other variables in one aspect: + if its value is not assigned in the session, it "points" to the global + value, and so when the global value is changed, the change + immediately takes effect in the session. + + This semantics is intentional, to be able to debug one session from + another. +*/ +class Sys_var_dbug: public sys_var +{ +public: + Sys_var_dbug(const char *name_arg, + const char *comment, int flag_args, + CMD_LINE getopt, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, + (char*)¤t_dbug_option-(char*)&global_system_variables, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute) + { option.var_type|= GET_STR; } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (!(res=var->value->val_str(&str))) + var->save_result.string_value.str= const_cast(""); + else + var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); + return false; + } + bool session_update(THD *thd, set_var *var) + { + const char *val= var->save_result.string_value.str; + if (!var->value) + DBUG_POP(); + else + DBUG_SET(val); + return false; + } + bool global_update(THD *thd, set_var *var) + { + const char *val= var->save_result.string_value.str; + DBUG_SET_INITIAL(val); + return false; + } + void session_save_default(THD *thd, set_var *var) + { } + void global_save_default(THD *thd, set_var *var) + { + char *ptr= (char*)(intptr)option.def_value; + var->save_result.string_value.str= ptr; + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + char buf[256]; + DBUG_EXPLAIN(buf, sizeof(buf)); + return (uchar*) thd->strdup(buf); + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + char buf[256]; + DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); + return (uchar*) thd->strdup(buf); + } + uchar *default_value_ptr(THD *thd) + { return (uchar*)""; } +}; +#endif + +#define KEYCACHE_VAR(X) GLOBAL_VAR(dflt_key_cache_var.X) +#define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF)) +#define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF)) +typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong); + +/** + The class for keycache_* variables. Supports structured names, + keycache_name.variable_name. + + Class specific constructor arguments: + everything derived from Sys_var_ulonglong + + Backing store: ulonglong + + @note these variables can be only GLOBAL +*/ +class Sys_var_keycache: public Sys_var_ulonglong +{ + keycache_update_function keycache_update; +public: + Sys_var_keycache(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + ulonglong min_val, ulonglong max_val, ulonglong def_val, + uint block_size, PolyLock *lock, + enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, + keycache_update_function on_update_func, + const char *substitute=0) + : Sys_var_ulonglong(name_arg, comment, flag_args, off, size, + getopt, min_val, max_val, def_val, + block_size, lock, binlog_status_arg, on_check_func, 0, + substitute), + keycache_update(on_update_func) + { + option.var_type|= GET_ASK_ADDR; + option.value= (uchar**)1; // crash me, please + // fix an offset from global_system_variables to be an offset in KEY_CACHE + offset= global_var_ptr() - (uchar*)dflt_key_cache; + SYSVAR_ASSERT(scope() == GLOBAL); + } + bool global_update(THD *thd, set_var *var) + { + ulonglong new_value= var->save_result.ulonglong_value; + LEX_STRING *base_name= &var->base; + KEY_CACHE *key_cache; + + /* If no basename, assume it's for the key cache named 'default' */ + if (!base_name->length) + base_name= &default_key_cache_base; + + key_cache= get_key_cache(base_name); + + if (!key_cache) + { // Key cache didn't exists */ + if (!new_value) // Tried to delete cache + return false; // Ok, nothing to do + if (!(key_cache= create_key_cache(base_name->str, base_name->length))) + return true; + } + + /** + Abort if some other thread is changing the key cache + @todo This should be changed so that we wait until the previous + assignment is done and then do the new assign + */ + if (key_cache->in_init) + return true; + + return keycache_update(thd, key_cache, offset, new_value); + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + KEY_CACHE *key_cache= get_key_cache(base); + if (!key_cache) + key_cache= &zero_key_cache; + return keycache_var_ptr(key_cache, offset); + } +}; + +static bool update_buffer_size(THD *thd, KEY_CACHE *key_cache, + ptrdiff_t offset, ulonglong new_value) +{ + bool error= false; + DBUG_ASSERT(offset == offsetof(KEY_CACHE, param_buff_size)); + + if (new_value == 0) + { + if (key_cache == dflt_key_cache) + { + my_error(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, MYF(0)); + return true; + } + + if (key_cache->key_cache_inited) // If initied + { + /* + Move tables using this key cache to the default key cache + and clear the old key cache. + */ + key_cache->in_init= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + key_cache->param_buff_size= 0; + ha_resize_key_cache(key_cache); + ha_change_key_cache(key_cache, dflt_key_cache); + /* + We don't delete the key cache as some running threads my still be in + the key cache code with a pointer to the deleted (empty) key cache + */ + mysql_mutex_lock(&LOCK_global_system_variables); + key_cache->in_init= 0; + } + return error; + } + + key_cache->param_buff_size= new_value; + + /* If key cache didn't exist initialize it, else resize it */ + key_cache->in_init= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + + if (!key_cache->key_cache_inited) + error= ha_init_key_cache(0, key_cache, 0); + else + error= ha_resize_key_cache(key_cache); + + mysql_mutex_lock(&LOCK_global_system_variables); + key_cache->in_init= 0; + + return error; +} + +static bool update_keycache(THD *thd, KEY_CACHE *key_cache, + ptrdiff_t offset, ulonglong new_value, + int (*func)(KEY_CACHE *)) +{ + bool error= false; + DBUG_ASSERT(offset != offsetof(KEY_CACHE, param_buff_size)); + + keycache_var(key_cache, offset)= new_value; + + key_cache->in_init= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + error= func(key_cache); + mysql_mutex_lock(&LOCK_global_system_variables); + key_cache->in_init= 0; + + return error; +} + +static bool resize_keycache(THD *thd, KEY_CACHE *key_cache, + ptrdiff_t offset, ulonglong new_value) +{ + return update_keycache(thd, key_cache, offset, new_value, + ha_resize_key_cache); +} + +static bool change_keycache_param(THD *thd, KEY_CACHE *key_cache, + ptrdiff_t offset, ulonglong new_value) +{ + return update_keycache(thd, key_cache, offset, new_value, + ha_change_key_cache_param); +} + +static bool repartition_keycache(THD *thd, KEY_CACHE *key_cache, + ptrdiff_t offset, ulonglong new_value) +{ + return update_keycache(thd, key_cache, offset, new_value, + ha_repartition_key_cache); +} + + +/** + The class for floating point variables + + Class specific constructor arguments: min, max + + Backing store: double +*/ +class Sys_var_double: public sys_var +{ +public: + Sys_var_double(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + double min_val, double max_val, double def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_DOUBLE, + (longlong) getopt_double2ulonglong(def_val), + lock, binlog_status_arg, on_check_func, on_update_func, + substitute) + { + option.var_type|= GET_DOUBLE; + option.min_value= (longlong) getopt_double2ulonglong(min_val); + option.max_value= (longlong) getopt_double2ulonglong(max_val); + global_var(double)= (double)option.def_value; + SYSVAR_ASSERT(min_val < max_val); + SYSVAR_ASSERT(min_val <= def_val); + SYSVAR_ASSERT(max_val >= def_val); + SYSVAR_ASSERT(size == sizeof(double)); + } + bool do_check(THD *thd, set_var *var) + { + my_bool fixed; + double v= var->value->val_real(); + var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed); + + return throw_bounds_warning(thd, name.str, fixed, v); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, double)= var->save_result.double_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(double)= var->save_result.double_value; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.double_value= global_var(double); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.double_value= getopt_ulonglong2double(option.def_value); } +}; + +/** + The class for the @max_user_connections. + It's derived from Sys_var_uint, but non-standard session value + requires a new class. + + Class specific constructor arguments: + everything derived from Sys_var_uint + + Backing store: uint +*/ +class Sys_var_max_user_conn: public Sys_var_int +{ +public: + Sys_var_max_user_conn(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + int min_val, int max_val, int def_val, + uint block_size, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : Sys_var_int(name_arg, comment, SESSION, off, size, getopt, + min_val, max_val, def_val, block_size, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute) + { } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + if (thd->user_connect && thd->user_connect->user_resources.user_conn) + return (uchar*) &(thd->user_connect->user_resources.user_conn); + return global_value_ptr(thd, base); + } +}; + +/** + The class for flagset variables - a variant of SET that allows in-place + editing (turning on/off individual bits). String representations looks like + a "flag=val,flag=val,...". Example: @@optimizer_switch + + Class specific constructor arguments: + char* values[] - 0-terminated list of strings of valid values + + Backing store: ulonglong + + @note + the last value in the values[] array should + *always* be the string "default". +*/ +class Sys_var_flagset: public Sys_var_typelib +{ +public: + Sys_var_flagset(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], ulonglong def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_CHAR, values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + substitute) + { + option.var_type|= GET_FLAGSET; + global_var(ulonglong)= def_val; + SYSVAR_ASSERT(typelib.count > 1); + SYSVAR_ASSERT(typelib.count <= 65); + SYSVAR_ASSERT(def_val < my_set_bits(typelib.count)); + SYSVAR_ASSERT(strcmp(values[typelib.count-1], "default") == 0); + SYSVAR_ASSERT(size == sizeof(ulonglong)); + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + ulonglong default_value, current_value; + if (var->type == OPT_GLOBAL) + { + default_value= option.def_value; + current_value= global_var(ulonglong); + } + else + { + default_value= global_var(ulonglong); + current_value= session_var(thd, ulonglong); + } + + if (var->value->result_type() == STRING_RESULT) + { + if (!(res=var->value->val_str(&str))) + return true; + else + { + char *error; + uint error_len; + + var->save_result.ulonglong_value= + find_set_from_flags(&typelib, + typelib.count, + current_value, + default_value, + res->ptr(), res->length(), + &error, &error_len); + if (error) + { + ErrConvString err(error, error_len, res->charset()); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); + return true; + } + } + } + else + { + longlong tmp=var->value->val_int(); + if ((tmp < 0 && ! var->value->unsigned_flag) + || (ulonglong)tmp > my_set_bits(typelib.count)) + return true; + else + var->save_result.ulonglong_value= tmp; + } + + return false; + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, ulonglong)= var->save_result.ulonglong_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(ulonglong)= var->save_result.ulonglong_value; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= global_var(ulonglong); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *valptr(THD *thd, ulonglong val) + { return (uchar*)flagset_to_string(thd, 0, val, typelib.type_names); } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, session_var(thd, ulonglong)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(ulonglong)); } + uchar *default_value_ptr(THD *thd) + { return valptr(thd, option.def_value); } +}; + +/** + The class for SET variables - variables taking zero or more values + from the given list. Example: @@sql_mode + + Class specific constructor arguments: + char* values[] - 0-terminated list of strings of valid values + + Backing store: ulonglong +*/ +class Sys_var_set: public Sys_var_typelib +{ +public: + Sys_var_set(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], ulonglong def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_CHAR, values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + substitute) + { + option.var_type|= GET_SET; + option.min_value= 0; + option.max_value= ~0ULL; + global_var(ulonglong)= def_val; + if ((option.u_max_value= (uchar**)max_var_ptr())) + { + *((ulonglong*) option.u_max_value)= ~0ULL; + } + SYSVAR_ASSERT(typelib.count > 0); + SYSVAR_ASSERT(typelib.count <= 64); + SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count)); + SYSVAR_ASSERT(size == sizeof(ulonglong)); + } + bool check_maximum(THD *thd, set_var *var, + const char *c_val, longlong i_val) + { + if (!max_var_ptr() || + (var->save_result.ulonglong_value & ~(get_max_var())) == 0) + return FALSE; + var->save_result.ulonglong_value&= get_max_var(); + + return c_val ? throw_bounds_warning(thd, name.str, c_val) : + throw_bounds_warning(thd, name.str, TRUE, + var->value->unsigned_flag, i_val); + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (var->value->result_type() == STRING_RESULT) + { + char *error; + uint error_len; + bool not_used; + + if (!(res=var->value->val_str_ascii(&str))) + return true; + + var->save_result.ulonglong_value= + find_set(&typelib, res->ptr(), res->length(), NULL, + &error, &error_len, ¬_used); + /* + note, we only issue an error if error_len > 0. + That is even while empty (zero-length) values are considered + errors by find_set(), these errors are ignored here + */ + if (error_len) + { + ErrConvString err(error, error_len, res->charset()); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); + return true; + } + return check_maximum(thd, var, res->ptr(), 0); + } + + longlong tmp=var->value->val_int(); + if ((tmp < 0 && ! var->value->unsigned_flag) + || (ulonglong)tmp > my_set_bits(typelib.count)) + return true; + + var->save_result.ulonglong_value= tmp; + return check_maximum(thd, var, 0, tmp); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, ulonglong)= var->save_result.ulonglong_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(ulonglong)= var->save_result.ulonglong_value; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= global_var(ulonglong); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *valptr(THD *thd, ulonglong val) + { return (uchar*)set_to_string(thd, 0, val, typelib.type_names); } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, session_var(thd, ulonglong)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(ulonglong)); } + uchar *default_value_ptr(THD *thd) + { return valptr(thd, option.def_value); } + + ulonglong get_max_var() { return *((ulonglong*) max_var_ptr()); } +}; + +/** + The class for variables which value is a plugin. + Example: @@default_storage_engine + + Class specific constructor arguments: + int plugin_type_arg (for example MYSQL_STORAGE_ENGINE_PLUGIN) + + Backing store: plugin_ref + + @note + these variables don't support command-line equivalents, any such + command-line options should be added manually to my_long_options in mysqld.cc +*/ +class Sys_var_plugin: public sys_var +{ + int plugin_type; +public: + Sys_var_plugin(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + int plugin_type_arg, char **def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute), + plugin_type(plugin_type_arg) + { + option.var_type|= GET_STR; + SYSVAR_ASSERT(size == sizeof(plugin_ref)); + SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff,sizeof(buff), system_charset_info), *res; + if (!(res=var->value->val_str(&str))) + var->save_result.plugin= NULL; + else + { + const LEX_STRING pname= { const_cast(res->ptr()), res->length() }; + plugin_ref plugin; + + // special code for storage engines (e.g. to handle historical aliases) + if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) + plugin= ha_resolve_by_name(thd, &pname, false); + else + plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); + if (!plugin) + { + // historically different error code + if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) + { + ErrConvString err(res); + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr()); + } + return true; + } + var->save_result.plugin= plugin; + } + return false; + } + void do_update(plugin_ref *valptr, plugin_ref newval) + { + plugin_ref oldval= *valptr; + if (oldval != newval) + { + *valptr= newval ? my_plugin_lock(NULL, newval) : 0; + plugin_unlock(NULL, oldval); + } + } + bool session_update(THD *thd, set_var *var) + { + do_update((plugin_ref*)session_var_ptr(thd), + var->save_result.plugin); + return false; + } + bool global_update(THD *thd, set_var *var) + { + do_update((plugin_ref*)global_var_ptr(), + var->save_result.plugin); + return false; + } + void session_save_default(THD *thd, set_var *var) + { + plugin_ref plugin= global_var(plugin_ref); + var->save_result.plugin= plugin ? my_plugin_lock(thd, plugin) : 0; + } + plugin_ref get_default(THD *thd) + { + char *default_value= *reinterpret_cast(option.def_value); + if (!default_value) + return 0; + + LEX_STRING pname= { default_value, strlen(pname.str) }; + plugin_ref plugin; + + if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) + plugin= ha_resolve_by_name(thd, &pname, false); + else + plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); + DBUG_ASSERT(plugin); + return my_plugin_lock(thd, plugin); + } + + void global_save_default(THD *thd, set_var *var) + { + var->save_result.plugin= get_default(thd); + } + + uchar *valptr(THD *thd, plugin_ref plugin) + { + return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, + plugin_name(plugin)->length) : 0); + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, session_var(thd, plugin_ref)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(plugin_ref)); } + uchar *default_value_ptr(THD *thd) + { return valptr(thd, get_default(thd)); } +}; + +#if defined(ENABLED_DEBUG_SYNC) + +#include "debug_sync.h" + +/** + The class for @@debug_sync session-only variable +*/ +class Sys_var_debug_sync :public sys_var +{ +public: + Sys_var_debug_sync(const char *name_arg, + const char *comment, int flag_args, + CMD_LINE getopt, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute) + { + SYSVAR_ASSERT(scope() == ONLY_SESSION); + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (!(res=var->value->val_str(&str))) + var->save_result.string_value= empty_lex_str; + else + { + if (!thd->make_lex_string(&var->save_result.string_value, + res->ptr(), res->length())) + return true; + } + return false; + } + bool session_update(THD *thd, set_var *var) + { + return debug_sync_update(thd, var->save_result.string_value.str, + var->save_result.string_value.length); + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + void session_save_default(THD *thd, set_var *var) + { + var->save_result.string_value.str= const_cast(""); + var->save_result.string_value.length= 0; + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + return debug_sync_value_ptr(thd); + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return 0; + } + uchar *default_value_ptr(THD *thd) + { return (uchar*)""; } +}; +#endif /* defined(ENABLED_DEBUG_SYNC) */ + + +/** + The class for bit variables - a variant of boolean that stores the value + in a bit. + + Class specific constructor arguments: + ulonglong bitmask_arg - the mask for the bit to set in the ulonglong + backing store + + Backing store: ulonglong + + @note + This class supports the "reverse" semantics, when the value of the bit + being 0 corresponds to the value of variable being set. To activate it + use REVERSE(bitmask) instead of simply bitmask in the constructor. + + @note + variables of this class cannot be set from the command line as + my_getopt does not support bits. +*/ +class Sys_var_bit: public Sys_var_typelib +{ + ulonglong bitmask; + bool reverse_semantics; + void set(uchar *ptr, ulonglong value) + { + if ((value != 0) ^ reverse_semantics) + (*(ulonglong *)ptr)|= bitmask; + else + (*(ulonglong *)ptr)&= ~bitmask; + } +public: + Sys_var_bit(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_MY_BOOL, bool_values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + substitute) + { + option.var_type|= GET_BOOL; + reverse_semantics= my_count_bits(bitmask_arg) > 1; + bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg; + set(global_var_ptr(), def_val); + SYSVAR_ASSERT(def_val < 2); + SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE + SYSVAR_ASSERT(size == sizeof(ulonglong)); + } + bool session_update(THD *thd, set_var *var) + { + set(session_var_ptr(thd), var->save_result.ulonglong_value); + return false; + } + bool global_update(THD *thd, set_var *var) + { + set(global_var_ptr(), var->save_result.ulonglong_value); + return false; + } + void session_save_default(THD *thd, set_var *var) + { + var->save_result.ulonglong_value= + (reverse_semantics == !(global_var(ulonglong) & bitmask)); + } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + + uchar *valptr(THD *thd, ulonglong val) + { + thd->sys_var_tmp.my_bool_value= (reverse_semantics == !(val & bitmask)); + return (uchar*) &thd->sys_var_tmp.my_bool_value; + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, session_var(thd, ulonglong)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(ulonglong)); } + uchar *default_value_ptr(THD *thd) + { + thd->sys_var_tmp.my_bool_value= option.def_value != 0; + return (uchar*) &thd->sys_var_tmp.my_bool_value; + } +}; + +/** + The class for variables that have a special meaning for a session, + such as @@timestamp or @@rnd_seed1, their values typically cannot be read + from SV structure, and a special "read" callback is provided. + + Class specific constructor arguments: + everything derived from Sys_var_ulonglong + session_special_read_function read_func_arg + + Backing store: ulonglong + + @note + These variables are session-only, global or command-line equivalents + are not supported as they're generally meaningless. +*/ +class Sys_var_session_special: public Sys_var_ulonglong +{ + typedef bool (*session_special_update_function)(THD *thd, set_var *var); + typedef ulonglong (*session_special_read_function)(THD *thd); + + session_special_read_function read_func; + session_special_update_function update_func; +public: + Sys_var_session_special(const char *name_arg, + const char *comment, int flag_args, + CMD_LINE getopt, + ulonglong min_val, ulonglong max_val, uint block_size, + PolyLock *lock, enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, + session_special_update_function update_func_arg, + session_special_read_function read_func_arg, + const char *substitute=0) + : Sys_var_ulonglong(name_arg, comment, flag_args, 0, + sizeof(ulonglong), getopt, min_val, + max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0, + substitute), + read_func(read_func_arg), update_func(update_func_arg) + { + SYSVAR_ASSERT(scope() == ONLY_SESSION); + SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake + } + bool session_update(THD *thd, set_var *var) + { return update_func(thd, var); } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + void session_save_default(THD *thd, set_var *var) + { var->value= 0; } + void global_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + thd->sys_var_tmp.ulonglong_value= read_func(thd); + return (uchar*) &thd->sys_var_tmp.ulonglong_value; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return 0; + } + uchar *default_value_ptr(THD *thd) + { + thd->sys_var_tmp.ulonglong_value= 0; + return (uchar*) &thd->sys_var_tmp.ulonglong_value; + } +}; + + +/* + Dedicated class because of a weird behavior of a default value. + Assigning timestamp to itself + + SET @@timestamp = @@timestamp + + make it non-default and stops the time flow. +*/ +class Sys_var_timestamp: public Sys_var_double +{ +public: + Sys_var_timestamp(const char *name_arg, + const char *comment, int flag_args, + CMD_LINE getopt, + double min_val, double max_val, + PolyLock *lock, enum binlog_status_enum binlog_status_arg) + : Sys_var_double(name_arg, comment, flag_args, 0, + sizeof(double), getopt, min_val, + max_val, 0, lock, binlog_status_arg) + { + SYSVAR_ASSERT(scope() == ONLY_SESSION); + SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake + } + bool session_update(THD *thd, set_var *var) + { + if (var->value) + { + my_hrtime_t hrtime = { hrtime_from_time(var->save_result.double_value) }; + thd->set_time(hrtime); + } + else // SET timestamp=DEFAULT + thd->user_time.val= 0; + return false; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + bool session_is_default(THD *thd) + { + return thd->user_time.val == 0; + } + void session_save_default(THD *thd, set_var *var) + { var->value= 0; } + void global_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + thd->sys_var_tmp.double_value= thd->start_time + + thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR; + return (uchar*) &thd->sys_var_tmp.double_value; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return 0; + } + uchar *default_value_ptr(THD *thd) + { + thd->sys_var_tmp.double_value= 0; + return (uchar*) &thd->sys_var_tmp.double_value; + } +}; + + +/** + The class for read-only variables that show whether a particular + feature is supported by the server. Example: have_compression + + Backing store: enum SHOW_COMP_OPTION + + @note + These variables are necessarily read-only, only global, and have no + command-line equivalent. +*/ +class Sys_var_have: public sys_var +{ +public: + Sys_var_have(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute) + { + SYSVAR_ASSERT(scope() == GLOBAL); + SYSVAR_ASSERT(getopt.id < 0); + SYSVAR_ASSERT(lock == 0); + SYSVAR_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG); + SYSVAR_ASSERT(is_readonly()); + SYSVAR_ASSERT(on_update == 0); + SYSVAR_ASSERT(size == sizeof(enum SHOW_COMP_OPTION)); + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var) { + DBUG_ASSERT(FALSE); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + void session_save_default(THD *thd, set_var *var) { } + void global_save_default(THD *thd, set_var *var) { } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return 0; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)]; + } +}; + +/** + Generic class for variables for storing entities that are internally + represented as structures, have names, and possibly can be referred to by + numbers. Examples: character sets, collations, locales, + + Class specific constructor arguments: + ptrdiff_t name_offset - offset of the 'name' field in the structure + + Backing store: void* + + @note + As every such a structure requires special treatment from my_getopt, + these variables don't support command-line equivalents, any such + command-line options should be added manually to my_long_options in mysqld.cc +*/ +class Sys_var_struct: public sys_var +{ + ptrdiff_t name_offset; // offset to the 'name' property in the structure +public: + Sys_var_struct(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + ptrdiff_t name_off, void *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute), + name_offset(name_off) + { + option.var_type|= GET_ENUM; // because we accept INT and STRING here + /* + struct variables are special on the command line - often (e.g. for + charsets) the name cannot be immediately resolved, but only after all + options (in particular, basedir) are parsed. + + thus all struct command-line options should be added manually + to my_long_options in mysqld.cc + */ + SYSVAR_ASSERT(getopt.id < 0); + SYSVAR_ASSERT(size == sizeof(void *)); + } + bool do_check(THD *thd, set_var *var) + { return false; } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, const void*)= var->save_result.ptr; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(const void*)= var->save_result.ptr; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ptr= global_var(void*); } + void global_save_default(THD *thd, set_var *var) + { + void **default_value= reinterpret_cast(option.def_value); + var->save_result.ptr= *default_value; + } + uchar *valptr(THD *thd, uchar *val) + { return val ? *(uchar**)(val+name_offset) : 0; } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, session_var(thd, uchar*)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(uchar*)); } + uchar *default_value_ptr(THD *thd) + { return valptr(thd, *(uchar**)option.def_value); } +}; + +/** + The class for variables that store time zones + + Backing store: Time_zone* + + @note + Time zones cannot be supported directly by my_getopt, thus + these variables don't support command-line equivalents, any such + command-line options should be added manually to my_long_options in mysqld.cc +*/ +class Sys_var_tz: public sys_var +{ +public: + Sys_var_tz(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + Time_zone **def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + const char *substitute=0) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + substitute) + { + SYSVAR_ASSERT(getopt.id < 0); + SYSVAR_ASSERT(size == sizeof(Time_zone *)); + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + char buff[MAX_TIME_ZONE_NAME_LENGTH]; + String str(buff, sizeof(buff), &my_charset_latin1); + String *res= var->value->val_str(&str); + + if (!res) + return true; + + if (!(var->save_result.time_zone= my_tz_find(thd, res))) + { + ErrConvString err(res); + my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr()); + return true; + } + return false; + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, Time_zone*)= var->save_result.time_zone; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(Time_zone*)= var->save_result.time_zone; + return false; + } + void session_save_default(THD *thd, set_var *var) + { + var->save_result.time_zone= global_var(Time_zone*); + } + void global_save_default(THD *thd, set_var *var) + { + var->save_result.time_zone= + *(Time_zone**)(intptr)option.def_value; + } + uchar *valptr(THD *thd, Time_zone *val) + { return (uchar *)(val->get_name()->ptr()); } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + /* + This is an ugly fix for replication: we don't replicate properly queries + invoking system variables' values to update tables; but + CONVERT_TZ(,,@@session.time_zone) is so popular that we make it + replicable (i.e. we tell the binlog code to store the session + timezone). If it's the global value which was used we can't replicate + (binlog code stores session value only). + */ + thd->time_zone_used= 1; + return valptr(thd, session_var(thd, Time_zone *)); + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(Time_zone*)); } + uchar *default_value_ptr(THD *thd) + { return valptr(thd, *(Time_zone**)option.def_value); } +}; + +/** + Special implementation for transaction isolation, that + distingushes between + + SET GLOBAL TRANSACTION ISOLATION (stored in global_system_variables) + SET SESSION TRANSACTION ISOLATION (stored in thd->variables) + SET TRANSACTION ISOLATION (stored in thd->tx_isolation) + + where the last statement sets isolation level for the next transaction only +*/ +class Sys_var_tx_isolation: public Sys_var_enum +{ +public: + Sys_var_tx_isolation(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], uint def_val, PolyLock *lock, + enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func) + :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, + values, def_val, lock, binlog_status_arg, on_check_func) + {} + bool session_update(THD *thd, set_var *var) + { + if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var)) + return TRUE; + if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction()) + { +#ifndef EMBEDDED_LIBRARY + Transaction_state_tracker *tst= NULL; + + if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) + tst= (Transaction_state_tracker *) + thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER); +#endif //EMBEDDED_LIBRARY + + thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value; + +#ifndef EMBEDDED_LIBRARY + if (var->type == OPT_DEFAULT) + { + enum enum_tx_isol_level l; + switch (thd->tx_isolation) { + case ISO_READ_UNCOMMITTED: + l= TX_ISOL_UNCOMMITTED; + break; + case ISO_READ_COMMITTED: + l= TX_ISOL_COMMITTED; + break; + case ISO_REPEATABLE_READ: + l= TX_ISOL_REPEATABLE; + break; + case ISO_SERIALIZABLE: + l= TX_ISOL_SERIALIZABLE; + break; + default: + DBUG_ASSERT(0); + return TRUE; + } + if (tst) + tst->set_isol_level(thd, l); + } + else if (tst) + { + tst->set_isol_level(thd, TX_ISOL_INHERIT); + } +#endif //EMBEDDED_LIBRARY + } + return FALSE; + } +}; + + +/** + Class representing the tx_read_only system variable for setting + default transaction access mode. + + Note that there is a special syntax - SET TRANSACTION READ ONLY + (or READ WRITE) that sets the access mode for the next transaction + only. +*/ + +class Sys_var_tx_read_only: public Sys_var_mybool +{ +public: + Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args, + ptrdiff_t off, size_t size, CMD_LINE getopt, + my_bool def_val, PolyLock *lock, + enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func) + :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt, + def_val, lock, binlog_status_arg, on_check_func) + {} + virtual bool session_update(THD *thd, set_var *var); +}; + +/* + Class for replicate_events_marked_for_skip. + We need a custom update function that ensures the slave is stopped when + the update is happening. +*/ +class Sys_var_replicate_events_marked_for_skip: public Sys_var_enum +{ +public: + Sys_var_replicate_events_marked_for_skip(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], uint def_val, PolyLock *lock= 0, + enum binlog_status_enum binlog_status_arg= VARIABLE_NOT_IN_BINLOG) + :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, + values, def_val, lock, binlog_status_arg) + {} + bool global_update(THD *thd, set_var *var); +}; + +/* + Class for handing multi-source replication variables + Variable values are store in Master_info, but to make it possible to + access variable without locks we also store it thd->variables. + These can be used as GLOBAL or SESSION, but both points to the same + variable. This is to make things compatible with MySQL 5.5 where variables + like sql_slave_skip_counter are GLOBAL. +*/ + +#define MASTER_INFO_VAR(X) my_offsetof(Master_info, X), sizeof(((Master_info *)0x10)->X) +class Sys_var_multi_source_ulonglong; +class Master_info; + +typedef bool (*on_multi_source_update_function)(sys_var *self, THD *thd, + Master_info *mi); +bool update_multi_source_variable(sys_var *self, + THD *thd, enum_var_type type); + + +class Sys_var_multi_source_ulonglong :public Sys_var_ulonglong +{ + ptrdiff_t master_info_offset; + on_multi_source_update_function update_multi_source_variable_func; +public: + Sys_var_multi_source_ulonglong(const char *name_arg, + const char *comment, int flag_args, + ptrdiff_t off, size_t size, + CMD_LINE getopt, + ptrdiff_t master_info_offset_arg, + size_t master_info_arg_size, + ulonglong min_val, ulonglong max_val, + ulonglong def_val, uint block_size, + on_multi_source_update_function on_update_func) + :Sys_var_ulonglong(name_arg, comment, flag_args, off, size, + getopt, min_val, max_val, def_val, block_size, + 0, VARIABLE_NOT_IN_BINLOG, 0, update_multi_source_variable), + master_info_offset(master_info_offset_arg), + update_multi_source_variable_func(on_update_func) + { + SYSVAR_ASSERT(master_info_arg_size == size); + } + bool global_update(THD *thd, set_var *var) + { + return session_update(thd, var); + } + void session_save_default(THD *thd, set_var *var) + { + /* Use value given in variable declaration */ + global_save_default(thd, var); + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + ulonglong *tmp, res; + tmp= (ulonglong*) (((uchar*)&(thd->variables)) + offset); + res= get_master_info_ulonglong_value(thd, master_info_offset); + *tmp= res; + return (uchar*) tmp; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + return session_value_ptr(thd, base); + } + ulonglong get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset); + bool update_variable(THD *thd, Master_info *mi) + { + return update_multi_source_variable_func(this, thd, mi); + } +}; + + +/** + Class for @@global.gtid_current_pos. +*/ +class Sys_var_gtid_current_pos: public sys_var +{ +public: + Sys_var_gtid_current_pos(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + SYSVAR_ASSERT(getopt.id < 0); + SYSVAR_ASSERT(is_readonly()); + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + void session_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(false); + return NULL; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base); +}; + + +/** + Class for @@global.gtid_binlog_pos. +*/ +class Sys_var_gtid_binlog_pos: public sys_var +{ +public: + Sys_var_gtid_binlog_pos(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + SYSVAR_ASSERT(getopt.id < 0); + SYSVAR_ASSERT(is_readonly()); + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + void session_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(false); + return NULL; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base); +}; + + +/** + Class for @@global.gtid_slave_pos. +*/ +class Sys_var_gtid_slave_pos: public sys_var +{ +public: + Sys_var_gtid_slave_pos(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var); + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool global_update(THD *thd, set_var *var); + void session_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + void global_save_default(THD *thd, set_var *var) + { + /* Record the attempt to use default so we can error. */ + var->value= 0; + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(false); + return NULL; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base); + uchar *default_value_ptr(THD *thd) + { return 0; } +}; + + +/** + Class for @@global.gtid_binlog_state. +*/ +class Sys_var_gtid_binlog_state: public sys_var +{ +public: + Sys_var_gtid_binlog_state(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var); + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool global_update(THD *thd, set_var *var); + void session_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + void global_save_default(THD *thd, set_var *var) + { + /* Record the attempt to use default so we can error. */ + var->value= 0; + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(false); + return NULL; + } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base); + uchar *default_value_ptr(THD *thd) + { return 0; } +}; + + +/** + Class for @@session.last_gtid. +*/ +class Sys_var_last_gtid: public sys_var +{ +public: + Sys_var_last_gtid(const char *name_arg, + const char *comment, int flag_args, CMD_LINE getopt) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + SYSVAR_ASSERT(getopt.id < 0); + SYSVAR_ASSERT(is_readonly()); + option.var_type|= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + void session_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base); + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { + DBUG_ASSERT(false); + return NULL; + } +}; + + +/** + Class for connection_name.slave_parallel_mode. +*/ +class Sys_var_slave_parallel_mode: public Sys_var_enum +{ +public: + Sys_var_slave_parallel_mode(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, const char *values[], + enum_slave_parallel_mode def_val) + : Sys_var_enum(name_arg, comment, flag_args, off, size, + getopt, values, def_val) + { + option.var_type|= GET_ASK_ADDR; + option.value= (uchar**)1; // crash me, please + SYSVAR_ASSERT(scope() == GLOBAL); + } + bool global_update(THD *thd, set_var *var); + uchar *global_value_ptr(THD *thd, const LEX_STRING *base); +}; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 4c47c01bf63..505539f0217 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -38,7 +38,7 @@ Created 11/5/1995 Heikki Tuuri #include #ifdef UNIV_NONINL -#include "buf0buf.ic" +#include "buf0buf.inl" #endif #ifndef UNIV_INNOCHECKSUM diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index f9c7bcd75c4..37ab561c1ba 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -31,7 +31,7 @@ Full Text Search interface #include "fts0fts.h" #include "fts0priv.h" #include "fts0types.h" -#include "fts0types.ic" +#include "fts0types.inl" #include "fts0vlc.h" #include "fts0plugin.h" #include "dict0priv.h" diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 04f2cd0f160..26c035a1a8c 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -768,7 +768,7 @@ btr_lift_page_up( #define BTR_N_LEAF_PAGES 1 #define BTR_TOTAL_SIZE 2 -#include "btr0btr.ic" +#include "btr0btr.inl" /**************************************************************** Global variable controlling if scrubbing should be performed */ diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic deleted file mode 100644 index 878e414a039..00000000000 --- a/storage/innobase/include/btr0btr.ic +++ /dev/null @@ -1,274 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 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/btr0btr.ic -The B-tree - -Created 6/2/1994 Heikki Tuuri -*******************************************************/ - -#include "mach0data.h" -#include "mtr0mtr.h" -#include "mtr0log.h" -#include "page0zip.h" - -#define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level - (not really a hard limit). - Used in debug assertions - in btr_page_set_level and - btr_page_get_level_low */ - -/** Gets a buffer page and declares its latching order level. -@param[in] page_id page id -@param[in] mode latch mode -@param[in] file file name -@param[in] line line where called -@param[in] index index tree, may be NULL if it is not an insert buffer -tree -@param[in,out] mtr mini-transaction -@return block */ -UNIV_INLINE -buf_block_t* -btr_block_get_func( - const page_id_t page_id, - const page_size_t& page_size, - ulint mode, - const char* file, - unsigned line, - dict_index_t* index, - mtr_t* mtr) -{ - buf_block_t* block; - dberr_t err=DB_SUCCESS; - - block = buf_page_get_gen( - page_id, page_size, mode, NULL, BUF_GET, file, line, mtr, &err); - - if (err == DB_DECRYPTION_FAILED) { - if (index && index->table) { - index->table->file_unreadable = true; - } - } - - if (block) { - if (mode != RW_NO_LATCH) { - - buf_block_dbg_add_level( - block, index != NULL && dict_index_is_ibuf(index) - ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE); - } - } - - return(block); -} - -/**************************************************************//** -Sets the index id field of a page. */ -UNIV_INLINE -void -btr_page_set_index_id( -/*==================*/ - page_t* page, /*!< in: page to be created */ - page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed - part will be updated, or NULL */ - index_id_t id, /*!< in: index id */ - mtr_t* mtr) /*!< in: mtr */ -{ - if (page_zip) { - mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id); - page_zip_write_header(page_zip, - page + (PAGE_HEADER + PAGE_INDEX_ID), - 8, mtr); - } else { - mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr); - } -} - -/**************************************************************//** -Gets the index id field of a page. -@return index id */ -UNIV_INLINE -index_id_t -btr_page_get_index_id( -/*==================*/ - const page_t* page) /*!< in: index page */ -{ - return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)); -} - -/********************************************************//** -Gets the node level field in an index page. -@return level, leaf level == 0 */ -UNIV_INLINE -ulint -btr_page_get_level_low( -/*===================*/ - const page_t* page) /*!< in: index page */ -{ - ulint level; - - ut_ad(page); - - level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL); - - ut_ad(level <= BTR_MAX_NODE_LEVEL); - - return(level); -} - -/********************************************************//** -Sets the node level field in an index page. */ -UNIV_INLINE -void -btr_page_set_level( -/*===============*/ - page_t* page, /*!< in: index page */ - page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed - part will be updated, or NULL */ - ulint level, /*!< in: level, leaf level == 0 */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - ut_ad(page != NULL); - ut_ad(mtr != NULL); - ut_ad(level <= BTR_MAX_NODE_LEVEL); - - if (page_zip) { - mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level); - page_zip_write_header(page_zip, - page + (PAGE_HEADER + PAGE_LEVEL), - 2, mtr); - } else { - mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level, - MLOG_2BYTES, mtr); - } -} - -/********************************************************//** -Sets the next index page field. */ -UNIV_INLINE -void -btr_page_set_next( -/*==============*/ - page_t* page, /*!< in: index page */ - page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed - part will be updated, or NULL */ - ulint next, /*!< in: next page number */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - ut_ad(page != NULL); - ut_ad(mtr != NULL); - - if (page_zip) { - mach_write_to_4(page + FIL_PAGE_NEXT, next); - page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr); - } else { - mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr); - } -} - -/********************************************************//** -Sets the previous index page field. */ -UNIV_INLINE -void -btr_page_set_prev( -/*==============*/ - page_t* page, /*!< in: index page */ - page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed - part will be updated, or NULL */ - ulint prev, /*!< in: previous page number */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - ut_ad(page != NULL); - ut_ad(mtr != NULL); - - if (page_zip) { - mach_write_to_4(page + FIL_PAGE_PREV, prev); - page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr); - } else { - mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr); - } -} - -/**************************************************************//** -Gets the child node file address in a node pointer. -NOTE: the offsets array must contain all offsets for the record since -we read the last field according to offsets and assume that it contains -the child page number. In other words offsets must have been retrieved -with rec_get_offsets(n_fields=ULINT_UNDEFINED). -@return child node address */ -UNIV_INLINE -ulint -btr_node_ptr_get_child_page_no( -/*===========================*/ - const rec_t* rec, /*!< in: node pointer record */ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - const byte* field; - ulint len; - ulint page_no; - - ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); - - /* The child address is in the last field */ - field = rec_get_nth_field(rec, offsets, - rec_offs_n_fields(offsets) - 1, &len); - - ut_ad(len == 4); - - page_no = mach_read_from_4(field); - ut_ad(page_no > 1); - - return(page_no); -} - -/**************************************************************//** -Releases the latches on a leaf page and bufferunfixes it. */ -UNIV_INLINE -void -btr_leaf_page_release( -/*==================*/ - buf_block_t* block, /*!< in: buffer block */ - ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or - BTR_MODIFY_LEAF */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(latch_mode == BTR_SEARCH_LEAF - || latch_mode == BTR_MODIFY_LEAF - || latch_mode == BTR_NO_LATCHES); - - ut_ad(!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY)); - - ulint mode; - switch (latch_mode) { - case BTR_SEARCH_LEAF: - mode = MTR_MEMO_PAGE_S_FIX; - break; - case BTR_MODIFY_LEAF: - mode = MTR_MEMO_PAGE_X_FIX; - break; - case BTR_NO_LATCHES: - mode = MTR_MEMO_BUF_FIX; - break; - default: - ut_a(0); - } - - mtr->memo_release(block, mode); -} diff --git a/storage/innobase/include/btr0btr.inl b/storage/innobase/include/btr0btr.inl new file mode 100644 index 00000000000..878e414a039 --- /dev/null +++ b/storage/innobase/include/btr0btr.inl @@ -0,0 +1,274 @@ +/***************************************************************************** + +Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 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/btr0btr.ic +The B-tree + +Created 6/2/1994 Heikki Tuuri +*******************************************************/ + +#include "mach0data.h" +#include "mtr0mtr.h" +#include "mtr0log.h" +#include "page0zip.h" + +#define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level + (not really a hard limit). + Used in debug assertions + in btr_page_set_level and + btr_page_get_level_low */ + +/** Gets a buffer page and declares its latching order level. +@param[in] page_id page id +@param[in] mode latch mode +@param[in] file file name +@param[in] line line where called +@param[in] index index tree, may be NULL if it is not an insert buffer +tree +@param[in,out] mtr mini-transaction +@return block */ +UNIV_INLINE +buf_block_t* +btr_block_get_func( + const page_id_t page_id, + const page_size_t& page_size, + ulint mode, + const char* file, + unsigned line, + dict_index_t* index, + mtr_t* mtr) +{ + buf_block_t* block; + dberr_t err=DB_SUCCESS; + + block = buf_page_get_gen( + page_id, page_size, mode, NULL, BUF_GET, file, line, mtr, &err); + + if (err == DB_DECRYPTION_FAILED) { + if (index && index->table) { + index->table->file_unreadable = true; + } + } + + if (block) { + if (mode != RW_NO_LATCH) { + + buf_block_dbg_add_level( + block, index != NULL && dict_index_is_ibuf(index) + ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE); + } + } + + return(block); +} + +/**************************************************************//** +Sets the index id field of a page. */ +UNIV_INLINE +void +btr_page_set_index_id( +/*==================*/ + page_t* page, /*!< in: page to be created */ + page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed + part will be updated, or NULL */ + index_id_t id, /*!< in: index id */ + mtr_t* mtr) /*!< in: mtr */ +{ + if (page_zip) { + mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id); + page_zip_write_header(page_zip, + page + (PAGE_HEADER + PAGE_INDEX_ID), + 8, mtr); + } else { + mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr); + } +} + +/**************************************************************//** +Gets the index id field of a page. +@return index id */ +UNIV_INLINE +index_id_t +btr_page_get_index_id( +/*==================*/ + const page_t* page) /*!< in: index page */ +{ + return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)); +} + +/********************************************************//** +Gets the node level field in an index page. +@return level, leaf level == 0 */ +UNIV_INLINE +ulint +btr_page_get_level_low( +/*===================*/ + const page_t* page) /*!< in: index page */ +{ + ulint level; + + ut_ad(page); + + level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL); + + ut_ad(level <= BTR_MAX_NODE_LEVEL); + + return(level); +} + +/********************************************************//** +Sets the node level field in an index page. */ +UNIV_INLINE +void +btr_page_set_level( +/*===============*/ + page_t* page, /*!< in: index page */ + page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed + part will be updated, or NULL */ + ulint level, /*!< in: level, leaf level == 0 */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + ut_ad(page != NULL); + ut_ad(mtr != NULL); + ut_ad(level <= BTR_MAX_NODE_LEVEL); + + if (page_zip) { + mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level); + page_zip_write_header(page_zip, + page + (PAGE_HEADER + PAGE_LEVEL), + 2, mtr); + } else { + mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level, + MLOG_2BYTES, mtr); + } +} + +/********************************************************//** +Sets the next index page field. */ +UNIV_INLINE +void +btr_page_set_next( +/*==============*/ + page_t* page, /*!< in: index page */ + page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed + part will be updated, or NULL */ + ulint next, /*!< in: next page number */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + ut_ad(page != NULL); + ut_ad(mtr != NULL); + + if (page_zip) { + mach_write_to_4(page + FIL_PAGE_NEXT, next); + page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr); + } else { + mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr); + } +} + +/********************************************************//** +Sets the previous index page field. */ +UNIV_INLINE +void +btr_page_set_prev( +/*==============*/ + page_t* page, /*!< in: index page */ + page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed + part will be updated, or NULL */ + ulint prev, /*!< in: previous page number */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + ut_ad(page != NULL); + ut_ad(mtr != NULL); + + if (page_zip) { + mach_write_to_4(page + FIL_PAGE_PREV, prev); + page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr); + } else { + mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr); + } +} + +/**************************************************************//** +Gets the child node file address in a node pointer. +NOTE: the offsets array must contain all offsets for the record since +we read the last field according to offsets and assume that it contains +the child page number. In other words offsets must have been retrieved +with rec_get_offsets(n_fields=ULINT_UNDEFINED). +@return child node address */ +UNIV_INLINE +ulint +btr_node_ptr_get_child_page_no( +/*===========================*/ + const rec_t* rec, /*!< in: node pointer record */ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + const byte* field; + ulint len; + ulint page_no; + + ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); + + /* The child address is in the last field */ + field = rec_get_nth_field(rec, offsets, + rec_offs_n_fields(offsets) - 1, &len); + + ut_ad(len == 4); + + page_no = mach_read_from_4(field); + ut_ad(page_no > 1); + + return(page_no); +} + +/**************************************************************//** +Releases the latches on a leaf page and bufferunfixes it. */ +UNIV_INLINE +void +btr_leaf_page_release( +/*==================*/ + buf_block_t* block, /*!< in: buffer block */ + ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or + BTR_MODIFY_LEAF */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(latch_mode == BTR_SEARCH_LEAF + || latch_mode == BTR_MODIFY_LEAF + || latch_mode == BTR_NO_LATCHES); + + ut_ad(!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY)); + + ulint mode; + switch (latch_mode) { + case BTR_SEARCH_LEAF: + mode = MTR_MEMO_PAGE_S_FIX; + break; + case BTR_MODIFY_LEAF: + mode = MTR_MEMO_PAGE_X_FIX; + break; + case BTR_NO_LATCHES: + mode = MTR_MEMO_BUF_FIX; + break; + default: + ut_a(0); + } + + mtr->memo_release(block, mode); +} diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 2f49ac6d12f..26cdbdedb2c 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -1034,6 +1034,6 @@ extern ulint btr_cur_n_sea_old; extern uint btr_cur_limit_optimistic_insert_debug; #endif /* UNIV_DEBUG */ -#include "btr0cur.ic" +#include "btr0cur.inl" #endif diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic deleted file mode 100644 index 7cf6c5982fa..00000000000 --- a/storage/innobase/include/btr0cur.ic +++ /dev/null @@ -1,230 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 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/btr0cur.ic -The index tree cursor - -Created 10/16/1994 Heikki Tuuri -*******************************************************/ - -#include "btr0btr.h" - -#ifdef UNIV_DEBUG -# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\ -if (btr_cur_limit_optimistic_insert_debug > 1\ - && (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\ - CODE;\ -} -#else -# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE) -#endif /* UNIV_DEBUG */ - -#ifdef UNIV_DEBUG -/*********************************************************//** -Returns the page cursor component of a tree cursor. -@return pointer to page cursor component */ -UNIV_INLINE -page_cur_t* -btr_cur_get_page_cur( -/*=================*/ - const btr_cur_t* cursor) /*!< in: tree cursor */ -{ - return(&((btr_cur_t*) cursor)->page_cur); -} - -/*********************************************************//** -Returns the buffer block on which the tree cursor is positioned. -@return pointer to buffer block */ -UNIV_INLINE -buf_block_t* -btr_cur_get_block( -/*==============*/ - const btr_cur_t* cursor) /*!< in: tree cursor */ -{ - return(page_cur_get_block(btr_cur_get_page_cur(cursor))); -} - -/*********************************************************//** -Returns the record pointer of a tree cursor. -@return pointer to record */ -UNIV_INLINE -rec_t* -btr_cur_get_rec( -/*============*/ - const btr_cur_t* cursor) /*!< in: tree cursor */ -{ - return(page_cur_get_rec(btr_cur_get_page_cur(cursor))); -} -#endif /* UNIV_DEBUG */ - -/*********************************************************//** -Returns the compressed page on which the tree cursor is positioned. -@return pointer to compressed page, or NULL if the page is not compressed */ -UNIV_INLINE -page_zip_des_t* -btr_cur_get_page_zip( -/*=================*/ - btr_cur_t* cursor) /*!< in: tree cursor */ -{ - return(buf_block_get_page_zip(btr_cur_get_block(cursor))); -} - -/*********************************************************//** -Returns the page of a tree cursor. -@return pointer to page */ -UNIV_INLINE -page_t* -btr_cur_get_page( -/*=============*/ - btr_cur_t* cursor) /*!< in: tree cursor */ -{ - return(page_align(page_cur_get_rec(&(cursor->page_cur)))); -} - -/*********************************************************//** -Positions a tree cursor at a given record. */ -UNIV_INLINE -void -btr_cur_position( -/*=============*/ - dict_index_t* index, /*!< in: index */ - rec_t* rec, /*!< in: record in tree */ - buf_block_t* block, /*!< in: buffer block of rec */ - btr_cur_t* cursor) /*!< out: cursor */ -{ - ut_ad(page_align(rec) == block->frame); - - page_cur_position(rec, block, btr_cur_get_page_cur(cursor)); - - cursor->index = index; -} - -/*********************************************************************//** -Checks if compressing an index page where a btr cursor is placed makes -sense. -@return TRUE if compression is recommended */ -UNIV_INLINE -ibool -btr_cur_compress_recommendation( -/*============================*/ - btr_cur_t* cursor, /*!< in: btr cursor */ - mtr_t* mtr) /*!< in: mtr */ -{ - const page_t* page; - - ut_ad(mtr_is_block_fix( - mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX, cursor->index->table)); - - page = btr_cur_get_page(cursor); - - LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2U, - return(FALSE)); - - if (page_get_data_size(page) - < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index) - || !page_has_siblings(page)) { - - /* The page fillfactor has dropped below a predefined - minimum value OR the level in the B-tree contains just - one page: we recommend compression if this is not the - root page. */ - - return(dict_index_get_page(cursor->index) - != page_get_page_no(page)); - } - - return(FALSE); -} - -/*********************************************************************//** -Checks if the record on which the cursor is placed can be deleted without -making tree compression necessary (or, recommended). -@return TRUE if can be deleted without recommended compression */ -UNIV_INLINE -ibool -btr_cur_can_delete_without_compress( -/*================================*/ - btr_cur_t* cursor, /*!< in: btr cursor */ - ulint rec_size,/*!< in: rec_get_size(btr_cur_get_rec(cursor))*/ - mtr_t* mtr) /*!< in: mtr */ -{ - page_t* page; - - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX)); - - page = btr_cur_get_page(cursor); - - if (page_get_data_size(page) - rec_size - < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index) - || !page_has_siblings(page) || page_get_n_recs(page) < 2) { - - /* The page fillfactor will drop below a predefined - minimum value, OR the level in the B-tree contains just - one page, OR the page will become empty: we recommend - compression if this is not the root page. */ - - return(dict_index_get_page(cursor->index) - == page_get_page_no(page)); - } - - return(TRUE); -} - -/*******************************************************************//** -Determine if an operation on off-page columns is an update. -@return TRUE if op != BTR_STORE_INSERT */ -UNIV_INLINE -ibool -btr_blob_op_is_update( -/*==================*/ - enum blob_op op) /*!< in: operation */ -{ - switch (op) { - case BTR_STORE_INSERT: - case BTR_STORE_INSERT_BULK: - return(FALSE); - case BTR_STORE_INSERT_UPDATE: - case BTR_STORE_UPDATE: - return(TRUE); - } - - ut_ad(0); - return(FALSE); -} - -/******************************************************//** -The following function is used to set the deleted bit of a record. */ -UNIV_INLINE -void -btr_rec_set_deleted_flag( -/*=====================*/ - rec_t* rec, /*!< in/out: physical record */ - page_zip_des_t* page_zip,/*!< in/out: compressed page (or NULL) */ - ulint flag) /*!< in: nonzero if delete marked */ -{ - if (page_rec_is_comp(rec)) { - rec_set_deleted_flag_new(rec, page_zip, flag); - } else { - ut_ad(!page_zip); - rec_set_deleted_flag_old(rec, flag); - } -} diff --git a/storage/innobase/include/btr0cur.inl b/storage/innobase/include/btr0cur.inl new file mode 100644 index 00000000000..7cf6c5982fa --- /dev/null +++ b/storage/innobase/include/btr0cur.inl @@ -0,0 +1,230 @@ +/***************************************************************************** + +Copyright (c) 1994, 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/btr0cur.ic +The index tree cursor + +Created 10/16/1994 Heikki Tuuri +*******************************************************/ + +#include "btr0btr.h" + +#ifdef UNIV_DEBUG +# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\ +if (btr_cur_limit_optimistic_insert_debug > 1\ + && (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\ + CODE;\ +} +#else +# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE) +#endif /* UNIV_DEBUG */ + +#ifdef UNIV_DEBUG +/*********************************************************//** +Returns the page cursor component of a tree cursor. +@return pointer to page cursor component */ +UNIV_INLINE +page_cur_t* +btr_cur_get_page_cur( +/*=================*/ + const btr_cur_t* cursor) /*!< in: tree cursor */ +{ + return(&((btr_cur_t*) cursor)->page_cur); +} + +/*********************************************************//** +Returns the buffer block on which the tree cursor is positioned. +@return pointer to buffer block */ +UNIV_INLINE +buf_block_t* +btr_cur_get_block( +/*==============*/ + const btr_cur_t* cursor) /*!< in: tree cursor */ +{ + return(page_cur_get_block(btr_cur_get_page_cur(cursor))); +} + +/*********************************************************//** +Returns the record pointer of a tree cursor. +@return pointer to record */ +UNIV_INLINE +rec_t* +btr_cur_get_rec( +/*============*/ + const btr_cur_t* cursor) /*!< in: tree cursor */ +{ + return(page_cur_get_rec(btr_cur_get_page_cur(cursor))); +} +#endif /* UNIV_DEBUG */ + +/*********************************************************//** +Returns the compressed page on which the tree cursor is positioned. +@return pointer to compressed page, or NULL if the page is not compressed */ +UNIV_INLINE +page_zip_des_t* +btr_cur_get_page_zip( +/*=================*/ + btr_cur_t* cursor) /*!< in: tree cursor */ +{ + return(buf_block_get_page_zip(btr_cur_get_block(cursor))); +} + +/*********************************************************//** +Returns the page of a tree cursor. +@return pointer to page */ +UNIV_INLINE +page_t* +btr_cur_get_page( +/*=============*/ + btr_cur_t* cursor) /*!< in: tree cursor */ +{ + return(page_align(page_cur_get_rec(&(cursor->page_cur)))); +} + +/*********************************************************//** +Positions a tree cursor at a given record. */ +UNIV_INLINE +void +btr_cur_position( +/*=============*/ + dict_index_t* index, /*!< in: index */ + rec_t* rec, /*!< in: record in tree */ + buf_block_t* block, /*!< in: buffer block of rec */ + btr_cur_t* cursor) /*!< out: cursor */ +{ + ut_ad(page_align(rec) == block->frame); + + page_cur_position(rec, block, btr_cur_get_page_cur(cursor)); + + cursor->index = index; +} + +/*********************************************************************//** +Checks if compressing an index page where a btr cursor is placed makes +sense. +@return TRUE if compression is recommended */ +UNIV_INLINE +ibool +btr_cur_compress_recommendation( +/*============================*/ + btr_cur_t* cursor, /*!< in: btr cursor */ + mtr_t* mtr) /*!< in: mtr */ +{ + const page_t* page; + + ut_ad(mtr_is_block_fix( + mtr, btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX, cursor->index->table)); + + page = btr_cur_get_page(cursor); + + LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2U, + return(FALSE)); + + if (page_get_data_size(page) + < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index) + || !page_has_siblings(page)) { + + /* The page fillfactor has dropped below a predefined + minimum value OR the level in the B-tree contains just + one page: we recommend compression if this is not the + root page. */ + + return(dict_index_get_page(cursor->index) + != page_get_page_no(page)); + } + + return(FALSE); +} + +/*********************************************************************//** +Checks if the record on which the cursor is placed can be deleted without +making tree compression necessary (or, recommended). +@return TRUE if can be deleted without recommended compression */ +UNIV_INLINE +ibool +btr_cur_can_delete_without_compress( +/*================================*/ + btr_cur_t* cursor, /*!< in: btr cursor */ + ulint rec_size,/*!< in: rec_get_size(btr_cur_get_rec(cursor))*/ + mtr_t* mtr) /*!< in: mtr */ +{ + page_t* page; + + ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX)); + + page = btr_cur_get_page(cursor); + + if (page_get_data_size(page) - rec_size + < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index) + || !page_has_siblings(page) || page_get_n_recs(page) < 2) { + + /* The page fillfactor will drop below a predefined + minimum value, OR the level in the B-tree contains just + one page, OR the page will become empty: we recommend + compression if this is not the root page. */ + + return(dict_index_get_page(cursor->index) + == page_get_page_no(page)); + } + + return(TRUE); +} + +/*******************************************************************//** +Determine if an operation on off-page columns is an update. +@return TRUE if op != BTR_STORE_INSERT */ +UNIV_INLINE +ibool +btr_blob_op_is_update( +/*==================*/ + enum blob_op op) /*!< in: operation */ +{ + switch (op) { + case BTR_STORE_INSERT: + case BTR_STORE_INSERT_BULK: + return(FALSE); + case BTR_STORE_INSERT_UPDATE: + case BTR_STORE_UPDATE: + return(TRUE); + } + + ut_ad(0); + return(FALSE); +} + +/******************************************************//** +The following function is used to set the deleted bit of a record. */ +UNIV_INLINE +void +btr_rec_set_deleted_flag( +/*=====================*/ + rec_t* rec, /*!< in/out: physical record */ + page_zip_des_t* page_zip,/*!< in/out: compressed page (or NULL) */ + ulint flag) /*!< in: nonzero if delete marked */ +{ + if (page_rec_is_comp(rec)) { + rec_set_deleted_flag_new(rec, page_zip, flag); + } else { + ut_ad(!page_zip); + rec_set_deleted_flag_old(rec, flag); + } +} diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index 9e3b4fc20a6..b4527f72ea0 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -550,6 +550,6 @@ struct btr_pcur_t{ dict_index_t* index() const { return(btr_cur.index); } }; -#include "btr0pcur.ic" +#include "btr0pcur.inl" #endif diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic deleted file mode 100644 index 6bc5b356dab..00000000000 --- a/storage/innobase/include/btr0pcur.ic +++ /dev/null @@ -1,657 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 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 -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/btr0pcur.ic -The index tree persistent cursor - -Created 2/23/1996 Heikki Tuuri -*******************************************************/ - - -/*********************************************************//** -Gets the rel_pos field for a cursor whose position has been stored. -@return BTR_PCUR_ON, ... */ -UNIV_INLINE -ulint -btr_pcur_get_rel_pos( -/*=================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_ad(cursor); - ut_ad(cursor->old_rec); - ut_ad(cursor->old_stored); - ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED - || cursor->pos_state == BTR_PCUR_IS_POSITIONED); - - return(cursor->rel_pos); -} - -#ifdef UNIV_DEBUG -/*********************************************************//** -Returns the btr cursor component of a persistent cursor. -@return pointer to btr cursor component */ -UNIV_INLINE -btr_cur_t* -btr_pcur_get_btr_cur( -/*=================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - const btr_cur_t* btr_cur = &cursor->btr_cur; - return((btr_cur_t*) btr_cur); -} - -/*********************************************************//** -Returns the page cursor component of a persistent cursor. -@return pointer to page cursor component */ -UNIV_INLINE -page_cur_t* -btr_pcur_get_page_cur( -/*==================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor))); -} - -/*********************************************************//** -Returns the page of a persistent cursor. -@return pointer to the page */ -UNIV_INLINE -page_t* -btr_pcur_get_page( -/*==============*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - - return(btr_cur_get_page(btr_pcur_get_btr_cur(cursor))); -} - -/*********************************************************//** -Returns the buffer block of a persistent cursor. -@return pointer to the block */ -UNIV_INLINE -buf_block_t* -btr_pcur_get_block( -/*===============*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - - return(btr_cur_get_block(btr_pcur_get_btr_cur(cursor))); -} - -/*********************************************************//** -Returns the record of a persistent cursor. -@return pointer to the record */ -UNIV_INLINE -rec_t* -btr_pcur_get_rec( -/*=============*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor))); -} -#endif /* UNIV_DEBUG */ - -/**************************************************************//** -Gets the up_match value for a pcur after a search. -@return number of matched fields at the cursor or to the right if -search mode was PAGE_CUR_GE, otherwise undefined */ -UNIV_INLINE -ulint -btr_pcur_get_up_match( -/*==================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - const btr_cur_t* btr_cursor; - - ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED) - || (cursor->pos_state == BTR_PCUR_IS_POSITIONED)); - - btr_cursor = btr_pcur_get_btr_cur(cursor); - - ut_ad(btr_cursor->up_match != ULINT_UNDEFINED); - - return(btr_cursor->up_match); -} - -/**************************************************************//** -Gets the low_match value for a pcur after a search. -@return number of matched fields at the cursor or to the right if -search mode was PAGE_CUR_LE, otherwise undefined */ -UNIV_INLINE -ulint -btr_pcur_get_low_match( -/*===================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - const btr_cur_t* btr_cursor; - - ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED) - || (cursor->pos_state == BTR_PCUR_IS_POSITIONED)); - - btr_cursor = btr_pcur_get_btr_cur(cursor); - ut_ad(btr_cursor->low_match != ULINT_UNDEFINED); - - return(btr_cursor->low_match); -} - -/*********************************************************//** -Checks if the persistent cursor is after the last user record on -a page. */ -UNIV_INLINE -ibool -btr_pcur_is_after_last_on_page( -/*===========================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor))); -} - -/*********************************************************//** -Checks if the persistent cursor is before the first user record on -a page. */ -UNIV_INLINE -ibool -btr_pcur_is_before_first_on_page( -/*=============================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor))); -} - -/*********************************************************//** -Checks if the persistent cursor is on a user record. */ -UNIV_INLINE -ibool -btr_pcur_is_on_user_rec( -/*====================*/ - const btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - if (btr_pcur_is_before_first_on_page(cursor) - || btr_pcur_is_after_last_on_page(cursor)) { - - return(FALSE); - } - - return(TRUE); -} - -/*********************************************************//** -Checks if the persistent cursor is before the first user record in -the index tree. */ -UNIV_INLINE -ibool -btr_pcur_is_before_first_in_tree( -/*=============================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - return !page_has_prev(btr_pcur_get_page(cursor)) - && page_cur_is_before_first(btr_pcur_get_page_cur(cursor)); -} - -/*********************************************************//** -Checks if the persistent cursor is after the last user record in -the index tree. */ -UNIV_INLINE -ibool -btr_pcur_is_after_last_in_tree( -/*===========================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - return !page_has_next(btr_pcur_get_page(cursor)) - && page_cur_is_after_last(btr_pcur_get_page_cur(cursor)); -} - -/*********************************************************//** -Moves the persistent cursor to the next record on the same page. */ -UNIV_INLINE -void -btr_pcur_move_to_next_on_page( -/*==========================*/ - btr_pcur_t* cursor) /*!< in/out: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); - - cursor->old_stored = false; -} - -/*********************************************************//** -Moves the persistent cursor to the previous record on the same page. */ -UNIV_INLINE -void -btr_pcur_move_to_prev_on_page( -/*==========================*/ - btr_pcur_t* cursor) /*!< in/out: persistent cursor */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); - - cursor->old_stored = false; -} - -/*********************************************************//** -Moves the persistent cursor to the next user record in the tree. If no user -records are left, the cursor ends up 'after last in tree'. -@return TRUE if the cursor moved forward, ending on a user record */ -UNIV_INLINE -ibool -btr_pcur_move_to_next_user_rec( -/*===========================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the - function may release the page latch */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - cursor->old_stored = false; -loop: - if (btr_pcur_is_after_last_on_page(cursor)) { - - if (btr_pcur_is_after_last_in_tree(cursor, mtr)) { - - return(FALSE); - } - - btr_pcur_move_to_next_page(cursor, mtr); - } else { - btr_pcur_move_to_next_on_page(cursor); - } - - if (btr_pcur_is_on_user_rec(cursor)) { - - return(TRUE); - } - - goto loop; -} - -/*********************************************************//** -Moves the persistent cursor to the next record in the tree. If no records are -left, the cursor stays 'after last in tree'. -@return TRUE if the cursor was not after last in tree */ -UNIV_INLINE -ibool -btr_pcur_move_to_next( -/*==================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the - function may release the page latch */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - cursor->old_stored = false; - - if (btr_pcur_is_after_last_on_page(cursor)) { - - if (btr_pcur_is_after_last_in_tree(cursor, mtr)) { - - return(FALSE); - } - - btr_pcur_move_to_next_page(cursor, mtr); - - return(TRUE); - } - - btr_pcur_move_to_next_on_page(cursor); - - return(TRUE); -} - -/**************************************************************//** -Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES, -that is, the cursor becomes detached. -Function btr_pcur_store_position should be used before calling this, -if restoration of cursor is wanted later. */ -UNIV_INLINE -void -btr_pcur_commit_specify_mtr( -/*========================*/ - btr_pcur_t* pcur, /*!< in: persistent cursor */ - mtr_t* mtr) /*!< in: mtr to commit */ -{ - ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED); - - pcur->latch_mode = BTR_NO_LATCHES; - - mtr_commit(mtr); - - pcur->pos_state = BTR_PCUR_WAS_POSITIONED; -} - -/** Commits the mtr and sets the clustered index pcur and secondary index -pcur latch mode to BTR_NO_LATCHES, that is, the cursor becomes detached. -Function btr_pcur_store_position should be used for both cursor before -calling this, if restoration of cursor is wanted later. -@param[in] pcur persistent cursor -@param[in] sec_pcur secondary index persistent cursor -@param[in] mtr mtr to commit */ -UNIV_INLINE -void -btr_pcurs_commit_specify_mtr( - btr_pcur_t* pcur, - btr_pcur_t* sec_pcur, - mtr_t* mtr) -{ - ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(sec_pcur->pos_state == BTR_PCUR_IS_POSITIONED); - - pcur->latch_mode = BTR_NO_LATCHES; - sec_pcur->latch_mode = BTR_NO_LATCHES; - - mtr_commit(mtr); - - pcur->pos_state = BTR_PCUR_WAS_POSITIONED; - sec_pcur->pos_state = BTR_PCUR_WAS_POSITIONED; -} - -/**************************************************************//** -Sets the old_rec_buf field to NULL. */ -UNIV_INLINE -void -btr_pcur_init( -/*==========*/ - btr_pcur_t* pcur) /*!< in: persistent cursor */ -{ - pcur->old_stored = false; - pcur->old_rec_buf = NULL; - pcur->old_rec = NULL; - - pcur->btr_cur.rtr_info = NULL; -} - -/** Free old_rec_buf. -@param[in] pcur Persistent cursor holding old_rec to be freed. */ -UNIV_INLINE -void -btr_pcur_free( - btr_pcur_t* pcur) -{ - ut_free(pcur->old_rec_buf); -} - -/**************************************************************//** -Initializes and opens a persistent cursor to an index tree. It should be -closed with btr_pcur_close. */ -UNIV_INLINE -dberr_t -btr_pcur_open_low( -/*==============*/ - dict_index_t* index, /*!< in: index */ - ulint level, /*!< in: level in the btree */ - const dtuple_t* tuple, /*!< in: tuple on which search done */ - page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; - NOTE that if the search is made using a unique - prefix of a record, mode should be - PAGE_CUR_LE, not PAGE_CUR_GE, as the latter - may end up on the previous page from the - record! */ - ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ - btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ - const char* file, /*!< in: file name */ - unsigned line, /*!< in: line where called */ - ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written - (0 if none) */ - mtr_t* mtr) /*!< in: mtr */ -{ - btr_cur_t* btr_cursor; - dberr_t err = DB_SUCCESS; - - /* Initialize the cursor */ - - btr_pcur_init(cursor); - - cursor->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); - cursor->search_mode = mode; - - /* Search with the tree cursor */ - - btr_cursor = btr_pcur_get_btr_cur(cursor); - - ut_ad(!dict_index_is_spatial(index)); - - err = btr_cur_search_to_nth_level( - index, level, tuple, mode, latch_mode, - btr_cursor, 0, file, line, mtr, autoinc); - - if (UNIV_UNLIKELY(err != DB_SUCCESS)) { - ib::warn() << " Error code: " << err - << " btr_pcur_open_low " - << " level: " << level - << " called from file: " - << file << " line: " << line - << " table: " << index->table->name - << " index: " << index->name; - } - - cursor->pos_state = BTR_PCUR_IS_POSITIONED; - - cursor->trx_if_known = NULL; - - return(err); -} - -/**************************************************************//** -Opens an persistent cursor to an index tree without initializing the -cursor. */ -UNIV_INLINE -dberr_t -btr_pcur_open_with_no_init_func( -/*============================*/ - dict_index_t* index, /*!< in: index */ - const dtuple_t* tuple, /*!< in: tuple on which search done */ - page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; - NOTE that if the search is made using a unique - prefix of a record, mode should be - PAGE_CUR_LE, not PAGE_CUR_GE, as the latter - may end up on the previous page of the - record! */ - ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...; - NOTE that if has_search_latch != 0 then - we maybe do not acquire a latch on the cursor - page, but assume that the caller uses his - btr search latch to protect the record! */ - btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ -#ifdef BTR_CUR_HASH_ADAPT - ulint has_search_latch, - /*!< in: latch mode the caller - currently has on search system: - RW_S_LATCH, or 0 */ -#endif /* BTR_CUR_HASH_ADAPT */ - const char* file, /*!< in: file name */ - unsigned line, /*!< in: line where called */ - mtr_t* mtr) /*!< in: mtr */ -{ - btr_cur_t* btr_cursor; - dberr_t err = DB_SUCCESS; - - cursor->latch_mode = BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode); - cursor->search_mode = mode; - - /* Search with the tree cursor */ - - btr_cursor = btr_pcur_get_btr_cur(cursor); - - err = btr_cur_search_to_nth_level( - index, 0, tuple, mode, latch_mode, btr_cursor, - has_search_latch, file, line, mtr, 0); - - cursor->pos_state = BTR_PCUR_IS_POSITIONED; - - cursor->old_stored = false; - - cursor->trx_if_known = NULL; - return err; -} - -/*****************************************************************//** -Opens a persistent cursor at either end of an index. */ -UNIV_INLINE -dberr_t -btr_pcur_open_at_index_side( -/*========================*/ - bool from_left, /*!< in: true if open to the low end, - false if to the high end */ - dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: latch mode */ - btr_pcur_t* pcur, /*!< in/out: cursor */ - bool init_pcur, /*!< in: whether to initialize pcur */ - ulint level, /*!< in: level to search for - (0=leaf) */ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - dberr_t err = DB_SUCCESS; - - pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); - - pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L; - - if (init_pcur) { - btr_pcur_init(pcur); - } - - err = btr_cur_open_at_index_side( - from_left, index, latch_mode, - btr_pcur_get_btr_cur(pcur), level, mtr); - pcur->pos_state = BTR_PCUR_IS_POSITIONED; - - pcur->old_stored = false; - - pcur->trx_if_known = NULL; - - return (err); -} - -/**********************************************************************//** -Positions a cursor at a randomly chosen position within a B-tree. -@return true if the index is available and we have put the cursor, false -if the index is unavailable */ -UNIV_INLINE -bool -btr_pcur_open_at_rnd_pos_func( -/*==========================*/ - dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ - btr_pcur_t* cursor, /*!< in/out: B-tree pcur */ - const char* file, /*!< in: file name */ - unsigned line, /*!< in: line where called */ - mtr_t* mtr) /*!< in: mtr */ -{ - /* Initialize the cursor */ - - cursor->latch_mode = latch_mode; - cursor->search_mode = PAGE_CUR_G; - - btr_pcur_init(cursor); - - bool available; - - available = btr_cur_open_at_rnd_pos_func(index, latch_mode, - btr_pcur_get_btr_cur(cursor), - file, line, mtr); - cursor->pos_state = BTR_PCUR_IS_POSITIONED; - cursor->old_stored = false; - - cursor->trx_if_known = NULL; - - return(available); -} - -/**************************************************************//** -Frees the possible memory heap of a persistent cursor and sets the latch -mode of the persistent cursor to BTR_NO_LATCHES. -WARNING: this function does not release the latch on the page where the -cursor is currently positioned. The latch is acquired by the -"move to next/previous" family of functions. Since recursive shared locks -are not allowed, you must take care (if using the cursor in S-mode) to -manually release the latch by either calling -btr_leaf_page_release(btr_pcur_get_block(&pcur), pcur.latch_mode, mtr) -or by committing the mini-transaction right after btr_pcur_close(). -A subsequent attempt to crawl the same page in the same mtr would cause -an assertion failure. */ -UNIV_INLINE -void -btr_pcur_close( -/*===========*/ - btr_pcur_t* cursor) /*!< in: persistent cursor */ -{ - ut_free(cursor->old_rec_buf); - - if (cursor->btr_cur.rtr_info) { - rtr_clean_rtr_info(cursor->btr_cur.rtr_info, true); - cursor->btr_cur.rtr_info = NULL; - } - - cursor->old_rec = NULL; - cursor->old_rec_buf = NULL; - cursor->btr_cur.page_cur.rec = NULL; - cursor->btr_cur.page_cur.block = NULL; - - cursor->old_rec = NULL; - cursor->old_stored = false; - - cursor->latch_mode = BTR_NO_LATCHES; - cursor->pos_state = BTR_PCUR_NOT_POSITIONED; - - cursor->trx_if_known = NULL; -} - -/*********************************************************//** -Moves the persistent cursor to the infimum record on the same page. */ -UNIV_INLINE -void -btr_pcur_move_before_first_on_page( -/*===============================*/ - btr_pcur_t* cursor) /*!< in/out: persistent cursor */ -{ - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - page_cur_set_before_first(btr_pcur_get_block(cursor), - btr_pcur_get_page_cur(cursor)); - - cursor->old_stored = false; -} diff --git a/storage/innobase/include/btr0pcur.inl b/storage/innobase/include/btr0pcur.inl new file mode 100644 index 00000000000..6bc5b356dab --- /dev/null +++ b/storage/innobase/include/btr0pcur.inl @@ -0,0 +1,657 @@ +/***************************************************************************** + +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 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 +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/btr0pcur.ic +The index tree persistent cursor + +Created 2/23/1996 Heikki Tuuri +*******************************************************/ + + +/*********************************************************//** +Gets the rel_pos field for a cursor whose position has been stored. +@return BTR_PCUR_ON, ... */ +UNIV_INLINE +ulint +btr_pcur_get_rel_pos( +/*=================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_ad(cursor); + ut_ad(cursor->old_rec); + ut_ad(cursor->old_stored); + ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED + || cursor->pos_state == BTR_PCUR_IS_POSITIONED); + + return(cursor->rel_pos); +} + +#ifdef UNIV_DEBUG +/*********************************************************//** +Returns the btr cursor component of a persistent cursor. +@return pointer to btr cursor component */ +UNIV_INLINE +btr_cur_t* +btr_pcur_get_btr_cur( +/*=================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + const btr_cur_t* btr_cur = &cursor->btr_cur; + return((btr_cur_t*) btr_cur); +} + +/*********************************************************//** +Returns the page cursor component of a persistent cursor. +@return pointer to page cursor component */ +UNIV_INLINE +page_cur_t* +btr_pcur_get_page_cur( +/*==================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor))); +} + +/*********************************************************//** +Returns the page of a persistent cursor. +@return pointer to the page */ +UNIV_INLINE +page_t* +btr_pcur_get_page( +/*==============*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + + return(btr_cur_get_page(btr_pcur_get_btr_cur(cursor))); +} + +/*********************************************************//** +Returns the buffer block of a persistent cursor. +@return pointer to the block */ +UNIV_INLINE +buf_block_t* +btr_pcur_get_block( +/*===============*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + + return(btr_cur_get_block(btr_pcur_get_btr_cur(cursor))); +} + +/*********************************************************//** +Returns the record of a persistent cursor. +@return pointer to the record */ +UNIV_INLINE +rec_t* +btr_pcur_get_rec( +/*=============*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor))); +} +#endif /* UNIV_DEBUG */ + +/**************************************************************//** +Gets the up_match value for a pcur after a search. +@return number of matched fields at the cursor or to the right if +search mode was PAGE_CUR_GE, otherwise undefined */ +UNIV_INLINE +ulint +btr_pcur_get_up_match( +/*==================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + const btr_cur_t* btr_cursor; + + ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED) + || (cursor->pos_state == BTR_PCUR_IS_POSITIONED)); + + btr_cursor = btr_pcur_get_btr_cur(cursor); + + ut_ad(btr_cursor->up_match != ULINT_UNDEFINED); + + return(btr_cursor->up_match); +} + +/**************************************************************//** +Gets the low_match value for a pcur after a search. +@return number of matched fields at the cursor or to the right if +search mode was PAGE_CUR_LE, otherwise undefined */ +UNIV_INLINE +ulint +btr_pcur_get_low_match( +/*===================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + const btr_cur_t* btr_cursor; + + ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED) + || (cursor->pos_state == BTR_PCUR_IS_POSITIONED)); + + btr_cursor = btr_pcur_get_btr_cur(cursor); + ut_ad(btr_cursor->low_match != ULINT_UNDEFINED); + + return(btr_cursor->low_match); +} + +/*********************************************************//** +Checks if the persistent cursor is after the last user record on +a page. */ +UNIV_INLINE +ibool +btr_pcur_is_after_last_on_page( +/*===========================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor))); +} + +/*********************************************************//** +Checks if the persistent cursor is before the first user record on +a page. */ +UNIV_INLINE +ibool +btr_pcur_is_before_first_on_page( +/*=============================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor))); +} + +/*********************************************************//** +Checks if the persistent cursor is on a user record. */ +UNIV_INLINE +ibool +btr_pcur_is_on_user_rec( +/*====================*/ + const btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + if (btr_pcur_is_before_first_on_page(cursor) + || btr_pcur_is_after_last_on_page(cursor)) { + + return(FALSE); + } + + return(TRUE); +} + +/*********************************************************//** +Checks if the persistent cursor is before the first user record in +the index tree. */ +UNIV_INLINE +ibool +btr_pcur_is_before_first_in_tree( +/*=============================*/ + btr_pcur_t* cursor, /*!< in: persistent cursor */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + return !page_has_prev(btr_pcur_get_page(cursor)) + && page_cur_is_before_first(btr_pcur_get_page_cur(cursor)); +} + +/*********************************************************//** +Checks if the persistent cursor is after the last user record in +the index tree. */ +UNIV_INLINE +ibool +btr_pcur_is_after_last_in_tree( +/*===========================*/ + btr_pcur_t* cursor, /*!< in: persistent cursor */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + return !page_has_next(btr_pcur_get_page(cursor)) + && page_cur_is_after_last(btr_pcur_get_page_cur(cursor)); +} + +/*********************************************************//** +Moves the persistent cursor to the next record on the same page. */ +UNIV_INLINE +void +btr_pcur_move_to_next_on_page( +/*==========================*/ + btr_pcur_t* cursor) /*!< in/out: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); + + cursor->old_stored = false; +} + +/*********************************************************//** +Moves the persistent cursor to the previous record on the same page. */ +UNIV_INLINE +void +btr_pcur_move_to_prev_on_page( +/*==========================*/ + btr_pcur_t* cursor) /*!< in/out: persistent cursor */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); + + cursor->old_stored = false; +} + +/*********************************************************//** +Moves the persistent cursor to the next user record in the tree. If no user +records are left, the cursor ends up 'after last in tree'. +@return TRUE if the cursor moved forward, ending on a user record */ +UNIV_INLINE +ibool +btr_pcur_move_to_next_user_rec( +/*===========================*/ + btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the + function may release the page latch */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + cursor->old_stored = false; +loop: + if (btr_pcur_is_after_last_on_page(cursor)) { + + if (btr_pcur_is_after_last_in_tree(cursor, mtr)) { + + return(FALSE); + } + + btr_pcur_move_to_next_page(cursor, mtr); + } else { + btr_pcur_move_to_next_on_page(cursor); + } + + if (btr_pcur_is_on_user_rec(cursor)) { + + return(TRUE); + } + + goto loop; +} + +/*********************************************************//** +Moves the persistent cursor to the next record in the tree. If no records are +left, the cursor stays 'after last in tree'. +@return TRUE if the cursor was not after last in tree */ +UNIV_INLINE +ibool +btr_pcur_move_to_next( +/*==================*/ + btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the + function may release the page latch */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + cursor->old_stored = false; + + if (btr_pcur_is_after_last_on_page(cursor)) { + + if (btr_pcur_is_after_last_in_tree(cursor, mtr)) { + + return(FALSE); + } + + btr_pcur_move_to_next_page(cursor, mtr); + + return(TRUE); + } + + btr_pcur_move_to_next_on_page(cursor); + + return(TRUE); +} + +/**************************************************************//** +Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES, +that is, the cursor becomes detached. +Function btr_pcur_store_position should be used before calling this, +if restoration of cursor is wanted later. */ +UNIV_INLINE +void +btr_pcur_commit_specify_mtr( +/*========================*/ + btr_pcur_t* pcur, /*!< in: persistent cursor */ + mtr_t* mtr) /*!< in: mtr to commit */ +{ + ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED); + + pcur->latch_mode = BTR_NO_LATCHES; + + mtr_commit(mtr); + + pcur->pos_state = BTR_PCUR_WAS_POSITIONED; +} + +/** Commits the mtr and sets the clustered index pcur and secondary index +pcur latch mode to BTR_NO_LATCHES, that is, the cursor becomes detached. +Function btr_pcur_store_position should be used for both cursor before +calling this, if restoration of cursor is wanted later. +@param[in] pcur persistent cursor +@param[in] sec_pcur secondary index persistent cursor +@param[in] mtr mtr to commit */ +UNIV_INLINE +void +btr_pcurs_commit_specify_mtr( + btr_pcur_t* pcur, + btr_pcur_t* sec_pcur, + mtr_t* mtr) +{ + ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(sec_pcur->pos_state == BTR_PCUR_IS_POSITIONED); + + pcur->latch_mode = BTR_NO_LATCHES; + sec_pcur->latch_mode = BTR_NO_LATCHES; + + mtr_commit(mtr); + + pcur->pos_state = BTR_PCUR_WAS_POSITIONED; + sec_pcur->pos_state = BTR_PCUR_WAS_POSITIONED; +} + +/**************************************************************//** +Sets the old_rec_buf field to NULL. */ +UNIV_INLINE +void +btr_pcur_init( +/*==========*/ + btr_pcur_t* pcur) /*!< in: persistent cursor */ +{ + pcur->old_stored = false; + pcur->old_rec_buf = NULL; + pcur->old_rec = NULL; + + pcur->btr_cur.rtr_info = NULL; +} + +/** Free old_rec_buf. +@param[in] pcur Persistent cursor holding old_rec to be freed. */ +UNIV_INLINE +void +btr_pcur_free( + btr_pcur_t* pcur) +{ + ut_free(pcur->old_rec_buf); +} + +/**************************************************************//** +Initializes and opens a persistent cursor to an index tree. It should be +closed with btr_pcur_close. */ +UNIV_INLINE +dberr_t +btr_pcur_open_low( +/*==============*/ + dict_index_t* index, /*!< in: index */ + ulint level, /*!< in: level in the btree */ + const dtuple_t* tuple, /*!< in: tuple on which search done */ + page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; + NOTE that if the search is made using a unique + prefix of a record, mode should be + PAGE_CUR_LE, not PAGE_CUR_GE, as the latter + may end up on the previous page from the + record! */ + ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ + btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ + const char* file, /*!< in: file name */ + unsigned line, /*!< in: line where called */ + ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written + (0 if none) */ + mtr_t* mtr) /*!< in: mtr */ +{ + btr_cur_t* btr_cursor; + dberr_t err = DB_SUCCESS; + + /* Initialize the cursor */ + + btr_pcur_init(cursor); + + cursor->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); + cursor->search_mode = mode; + + /* Search with the tree cursor */ + + btr_cursor = btr_pcur_get_btr_cur(cursor); + + ut_ad(!dict_index_is_spatial(index)); + + err = btr_cur_search_to_nth_level( + index, level, tuple, mode, latch_mode, + btr_cursor, 0, file, line, mtr, autoinc); + + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + ib::warn() << " Error code: " << err + << " btr_pcur_open_low " + << " level: " << level + << " called from file: " + << file << " line: " << line + << " table: " << index->table->name + << " index: " << index->name; + } + + cursor->pos_state = BTR_PCUR_IS_POSITIONED; + + cursor->trx_if_known = NULL; + + return(err); +} + +/**************************************************************//** +Opens an persistent cursor to an index tree without initializing the +cursor. */ +UNIV_INLINE +dberr_t +btr_pcur_open_with_no_init_func( +/*============================*/ + dict_index_t* index, /*!< in: index */ + const dtuple_t* tuple, /*!< in: tuple on which search done */ + page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; + NOTE that if the search is made using a unique + prefix of a record, mode should be + PAGE_CUR_LE, not PAGE_CUR_GE, as the latter + may end up on the previous page of the + record! */ + ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...; + NOTE that if has_search_latch != 0 then + we maybe do not acquire a latch on the cursor + page, but assume that the caller uses his + btr search latch to protect the record! */ + btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ +#ifdef BTR_CUR_HASH_ADAPT + ulint has_search_latch, + /*!< in: latch mode the caller + currently has on search system: + RW_S_LATCH, or 0 */ +#endif /* BTR_CUR_HASH_ADAPT */ + const char* file, /*!< in: file name */ + unsigned line, /*!< in: line where called */ + mtr_t* mtr) /*!< in: mtr */ +{ + btr_cur_t* btr_cursor; + dberr_t err = DB_SUCCESS; + + cursor->latch_mode = BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode); + cursor->search_mode = mode; + + /* Search with the tree cursor */ + + btr_cursor = btr_pcur_get_btr_cur(cursor); + + err = btr_cur_search_to_nth_level( + index, 0, tuple, mode, latch_mode, btr_cursor, + has_search_latch, file, line, mtr, 0); + + cursor->pos_state = BTR_PCUR_IS_POSITIONED; + + cursor->old_stored = false; + + cursor->trx_if_known = NULL; + return err; +} + +/*****************************************************************//** +Opens a persistent cursor at either end of an index. */ +UNIV_INLINE +dberr_t +btr_pcur_open_at_index_side( +/*========================*/ + bool from_left, /*!< in: true if open to the low end, + false if to the high end */ + dict_index_t* index, /*!< in: index */ + ulint latch_mode, /*!< in: latch mode */ + btr_pcur_t* pcur, /*!< in/out: cursor */ + bool init_pcur, /*!< in: whether to initialize pcur */ + ulint level, /*!< in: level to search for + (0=leaf) */ + mtr_t* mtr) /*!< in/out: mini-transaction */ +{ + dberr_t err = DB_SUCCESS; + + pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); + + pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L; + + if (init_pcur) { + btr_pcur_init(pcur); + } + + err = btr_cur_open_at_index_side( + from_left, index, latch_mode, + btr_pcur_get_btr_cur(pcur), level, mtr); + pcur->pos_state = BTR_PCUR_IS_POSITIONED; + + pcur->old_stored = false; + + pcur->trx_if_known = NULL; + + return (err); +} + +/**********************************************************************//** +Positions a cursor at a randomly chosen position within a B-tree. +@return true if the index is available and we have put the cursor, false +if the index is unavailable */ +UNIV_INLINE +bool +btr_pcur_open_at_rnd_pos_func( +/*==========================*/ + dict_index_t* index, /*!< in: index */ + ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ + btr_pcur_t* cursor, /*!< in/out: B-tree pcur */ + const char* file, /*!< in: file name */ + unsigned line, /*!< in: line where called */ + mtr_t* mtr) /*!< in: mtr */ +{ + /* Initialize the cursor */ + + cursor->latch_mode = latch_mode; + cursor->search_mode = PAGE_CUR_G; + + btr_pcur_init(cursor); + + bool available; + + available = btr_cur_open_at_rnd_pos_func(index, latch_mode, + btr_pcur_get_btr_cur(cursor), + file, line, mtr); + cursor->pos_state = BTR_PCUR_IS_POSITIONED; + cursor->old_stored = false; + + cursor->trx_if_known = NULL; + + return(available); +} + +/**************************************************************//** +Frees the possible memory heap of a persistent cursor and sets the latch +mode of the persistent cursor to BTR_NO_LATCHES. +WARNING: this function does not release the latch on the page where the +cursor is currently positioned. The latch is acquired by the +"move to next/previous" family of functions. Since recursive shared locks +are not allowed, you must take care (if using the cursor in S-mode) to +manually release the latch by either calling +btr_leaf_page_release(btr_pcur_get_block(&pcur), pcur.latch_mode, mtr) +or by committing the mini-transaction right after btr_pcur_close(). +A subsequent attempt to crawl the same page in the same mtr would cause +an assertion failure. */ +UNIV_INLINE +void +btr_pcur_close( +/*===========*/ + btr_pcur_t* cursor) /*!< in: persistent cursor */ +{ + ut_free(cursor->old_rec_buf); + + if (cursor->btr_cur.rtr_info) { + rtr_clean_rtr_info(cursor->btr_cur.rtr_info, true); + cursor->btr_cur.rtr_info = NULL; + } + + cursor->old_rec = NULL; + cursor->old_rec_buf = NULL; + cursor->btr_cur.page_cur.rec = NULL; + cursor->btr_cur.page_cur.block = NULL; + + cursor->old_rec = NULL; + cursor->old_stored = false; + + cursor->latch_mode = BTR_NO_LATCHES; + cursor->pos_state = BTR_PCUR_NOT_POSITIONED; + + cursor->trx_if_known = NULL; +} + +/*********************************************************//** +Moves the persistent cursor to the infimum record on the same page. */ +UNIV_INLINE +void +btr_pcur_move_before_first_on_page( +/*===============================*/ + btr_pcur_t* cursor) /*!< in/out: persistent cursor */ +{ + ut_ad(cursor->latch_mode != BTR_NO_LATCHES); + + page_cur_set_before_first(btr_pcur_get_block(cursor), + btr_pcur_get_page_cur(cursor)); + + cursor->old_stored = false; +} diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index a9781c65491..421796cd084 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -332,6 +332,6 @@ again set this much timeout. This is to reduce contention. */ #define BTR_SEA_TIMEOUT 10000 #endif /* BTR_CUR_HASH_ADAPT */ -#include "btr0sea.ic" +#include "btr0sea.inl" #endif diff --git a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic deleted file mode 100644 index 90877d23192..00000000000 --- a/storage/innobase/include/btr0sea.ic +++ /dev/null @@ -1,195 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 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 -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/btr0sea.ic -The index tree adaptive search - -Created 2/17/1996 Heikki Tuuri -*************************************************************************/ - -#include "dict0mem.h" -#include "btr0cur.h" -#include "buf0buf.h" - -/** Create and initialize search info. -@param[in,out] heap heap where created -@return own: search info struct */ -UNIV_INLINE -btr_search_t* -btr_search_info_create(mem_heap_t* heap) -{ - btr_search_t* info = static_cast( - mem_heap_zalloc(heap, sizeof(btr_search_t))); - ut_d(info->magic_n = BTR_SEARCH_MAGIC_N); -#ifdef BTR_CUR_HASH_ADAPT - info->n_fields = 1; - info->left_side = TRUE; -#endif /* BTR_CUR_HASH_ADAPT */ - return(info); -} - -#ifdef BTR_CUR_HASH_ADAPT -/*********************************************************************//** -Updates the search info. */ -void -btr_search_info_update_slow( -/*========================*/ - btr_search_t* info, /*!< in/out: search info */ - btr_cur_t* cursor);/*!< in: cursor which was just positioned */ - -/*********************************************************************//** -Updates the search info. */ -UNIV_INLINE -void -btr_search_info_update( -/*===================*/ - dict_index_t* index, /*!< in: index of the cursor */ - btr_cur_t* cursor) /*!< in: cursor which was just positioned */ -{ - ut_ad(!rw_lock_own_flagged(btr_get_search_latch(index), - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - - if (dict_index_is_spatial(index) || !btr_search_enabled) { - return; - } - - btr_search_t* info; - info = btr_search_get_info(index); - - info->hash_analysis++; - - if (info->hash_analysis < BTR_SEARCH_HASH_ANALYSIS) { - - /* Do nothing */ - - return; - - } - - ut_ad(cursor->flag != BTR_CUR_HASH); - - btr_search_info_update_slow(info, cursor); -} - -/** Lock all search latches in exclusive mode. */ -UNIV_INLINE -void -btr_search_x_lock_all() -{ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_x_lock(btr_search_latches[i]); - } -} - -/** Unlock all search latches from exclusive mode. */ -UNIV_INLINE -void -btr_search_x_unlock_all() -{ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_x_unlock(btr_search_latches[i]); - } -} - -/** Lock all search latches in shared mode. */ -UNIV_INLINE -void -btr_search_s_lock_all() -{ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_s_lock(btr_search_latches[i]); - } -} - -/** Unlock all search latches from shared mode. */ -UNIV_INLINE -void -btr_search_s_unlock_all() -{ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_s_unlock(btr_search_latches[i]); - } -} - -#ifdef UNIV_DEBUG -/** Check if thread owns all the search latches. -@param[in] mode lock mode check -@retval true if owns all of them -@retval false if does not own some of them */ -UNIV_INLINE -bool -btr_search_own_all(ulint mode) -{ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (!rw_lock_own(btr_search_latches[i], mode)) { - return(false); - } - } - return(true); -} - -/** Check if thread owns any of the search latches. -@param[in] mode lock mode check -@retval true if owns any of them -@retval false if owns no search latch */ -UNIV_INLINE -bool -btr_search_own_any(ulint mode) -{ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (rw_lock_own(btr_search_latches[i], mode)) { - return(true); - } - } - return(false); -} -#endif /* UNIV_DEBUG */ - -/** Get the adaptive hash search index latch for a b-tree. -@param[in] index b-tree index -@return latch */ -UNIV_INLINE -rw_lock_t* -btr_get_search_latch(const dict_index_t* index) -{ - ut_ad(index != NULL); - - ulint ifold = ut_fold_ulint_pair(static_cast(index->id), - static_cast(index->space)); - - return(btr_search_latches[ifold % btr_ahi_parts]); -} - -/** Get the hash-table based on index attributes. -A table is selected from an array of tables using pair of index-id, space-id. -@param[in] index index handler -@return hash table */ -UNIV_INLINE -hash_table_t* -btr_get_search_table(const dict_index_t* index) -{ - ut_ad(index != NULL); - - ulint ifold = ut_fold_ulint_pair(static_cast(index->id), - static_cast(index->space)); - - return(btr_search_sys->hash_tables[ifold % btr_ahi_parts]); -} -#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/btr0sea.inl b/storage/innobase/include/btr0sea.inl new file mode 100644 index 00000000000..90877d23192 --- /dev/null +++ b/storage/innobase/include/btr0sea.inl @@ -0,0 +1,195 @@ +/***************************************************************************** + +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 +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/btr0sea.ic +The index tree adaptive search + +Created 2/17/1996 Heikki Tuuri +*************************************************************************/ + +#include "dict0mem.h" +#include "btr0cur.h" +#include "buf0buf.h" + +/** Create and initialize search info. +@param[in,out] heap heap where created +@return own: search info struct */ +UNIV_INLINE +btr_search_t* +btr_search_info_create(mem_heap_t* heap) +{ + btr_search_t* info = static_cast( + mem_heap_zalloc(heap, sizeof(btr_search_t))); + ut_d(info->magic_n = BTR_SEARCH_MAGIC_N); +#ifdef BTR_CUR_HASH_ADAPT + info->n_fields = 1; + info->left_side = TRUE; +#endif /* BTR_CUR_HASH_ADAPT */ + return(info); +} + +#ifdef BTR_CUR_HASH_ADAPT +/*********************************************************************//** +Updates the search info. */ +void +btr_search_info_update_slow( +/*========================*/ + btr_search_t* info, /*!< in/out: search info */ + btr_cur_t* cursor);/*!< in: cursor which was just positioned */ + +/*********************************************************************//** +Updates the search info. */ +UNIV_INLINE +void +btr_search_info_update( +/*===================*/ + dict_index_t* index, /*!< in: index of the cursor */ + btr_cur_t* cursor) /*!< in: cursor which was just positioned */ +{ + ut_ad(!rw_lock_own_flagged(btr_get_search_latch(index), + RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); + + if (dict_index_is_spatial(index) || !btr_search_enabled) { + return; + } + + btr_search_t* info; + info = btr_search_get_info(index); + + info->hash_analysis++; + + if (info->hash_analysis < BTR_SEARCH_HASH_ANALYSIS) { + + /* Do nothing */ + + return; + + } + + ut_ad(cursor->flag != BTR_CUR_HASH); + + btr_search_info_update_slow(info, cursor); +} + +/** Lock all search latches in exclusive mode. */ +UNIV_INLINE +void +btr_search_x_lock_all() +{ + for (ulint i = 0; i < btr_ahi_parts; ++i) { + rw_lock_x_lock(btr_search_latches[i]); + } +} + +/** Unlock all search latches from exclusive mode. */ +UNIV_INLINE +void +btr_search_x_unlock_all() +{ + for (ulint i = 0; i < btr_ahi_parts; ++i) { + rw_lock_x_unlock(btr_search_latches[i]); + } +} + +/** Lock all search latches in shared mode. */ +UNIV_INLINE +void +btr_search_s_lock_all() +{ + for (ulint i = 0; i < btr_ahi_parts; ++i) { + rw_lock_s_lock(btr_search_latches[i]); + } +} + +/** Unlock all search latches from shared mode. */ +UNIV_INLINE +void +btr_search_s_unlock_all() +{ + for (ulint i = 0; i < btr_ahi_parts; ++i) { + rw_lock_s_unlock(btr_search_latches[i]); + } +} + +#ifdef UNIV_DEBUG +/** Check if thread owns all the search latches. +@param[in] mode lock mode check +@retval true if owns all of them +@retval false if does not own some of them */ +UNIV_INLINE +bool +btr_search_own_all(ulint mode) +{ + for (ulint i = 0; i < btr_ahi_parts; ++i) { + if (!rw_lock_own(btr_search_latches[i], mode)) { + return(false); + } + } + return(true); +} + +/** Check if thread owns any of the search latches. +@param[in] mode lock mode check +@retval true if owns any of them +@retval false if owns no search latch */ +UNIV_INLINE +bool +btr_search_own_any(ulint mode) +{ + for (ulint i = 0; i < btr_ahi_parts; ++i) { + if (rw_lock_own(btr_search_latches[i], mode)) { + return(true); + } + } + return(false); +} +#endif /* UNIV_DEBUG */ + +/** Get the adaptive hash search index latch for a b-tree. +@param[in] index b-tree index +@return latch */ +UNIV_INLINE +rw_lock_t* +btr_get_search_latch(const dict_index_t* index) +{ + ut_ad(index != NULL); + + ulint ifold = ut_fold_ulint_pair(static_cast(index->id), + static_cast(index->space)); + + return(btr_search_latches[ifold % btr_ahi_parts]); +} + +/** Get the hash-table based on index attributes. +A table is selected from an array of tables using pair of index-id, space-id. +@param[in] index index handler +@return hash table */ +UNIV_INLINE +hash_table_t* +btr_get_search_table(const dict_index_t* index) +{ + ut_ad(index != NULL); + + ulint ifold = ut_fold_ulint_pair(static_cast(index->id), + static_cast(index->space)); + + return(btr_search_sys->hash_tables[ifold % btr_ahi_parts]); +} +#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/buf0buddy.h b/storage/innobase/include/buf0buddy.h index 1697c8649c0..906e5437f42 100644 --- a/storage/innobase/include/buf0buddy.h +++ b/storage/innobase/include/buf0buddy.h @@ -87,6 +87,6 @@ void buf_buddy_condense_free( buf_pool_t* buf_pool); -#include "buf0buddy.ic" +#include "buf0buddy.inl" #endif /* buf0buddy_h */ diff --git a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf0buddy.ic deleted file mode 100644 index 4afa795e762..00000000000 --- a/storage/innobase/include/buf0buddy.ic +++ /dev/null @@ -1,139 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2006, 2016, 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/buf0buddy.ic -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" - -/**********************************************************************//** -Allocate a block. The thread calling this function must hold -buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex. -The buf_pool_mutex may be released and reacquired. -@return allocated block, never NULL */ -void* -buf_buddy_alloc_low( -/*================*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ - ulint i, /*!< in: index of buf_pool->zip_free[], - or BUF_BUDDY_SIZES */ - ibool* lru) /*!< in: pointer to a variable that - will be assigned TRUE if storage was - allocated from the LRU list and - buf_pool->mutex was temporarily - released */ - MY_ATTRIBUTE((malloc, nonnull)); - -/**********************************************************************//** -Deallocate a block. */ -void -buf_buddy_free_low( -/*===============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - void* buf, /*!< in: block to be freed, must not be - pointed to by the buffer pool */ - ulint i) /*!< in: index of buf_pool->zip_free[], - or BUF_BUDDY_SIZES */ - MY_ATTRIBUTE((nonnull)); - -/**********************************************************************//** -Get the index of buf_pool->zip_free[] for a given block size. -@return index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ -UNIV_INLINE -ulint -buf_buddy_get_slot( -/*===============*/ - ulint size) /*!< in: block size */ -{ - ulint i; - ulint s; - - ut_ad(size >= UNIV_ZIP_SIZE_MIN); - - for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) { - } - - ut_ad(i <= BUF_BUDDY_SIZES); - return(i); -} - -/**********************************************************************//** -Allocate a block. The thread calling this function must hold -buf_pool->mutex and must not hold buf_pool->zip_mutex or any -block->mutex. The buf_pool->mutex may be released and reacquired. -This function should only be used for allocating compressed page frames. -@return allocated block, never NULL */ -UNIV_INLINE -byte* -buf_buddy_alloc( -/*============*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool in which - the page resides */ - ulint size, /*!< in: compressed page size - (between UNIV_ZIP_SIZE_MIN and - UNIV_PAGE_SIZE) */ - ibool* lru) /*!< in: pointer to a variable - that will be assigned TRUE if - storage was allocated from the - LRU list and buf_pool->mutex was - temporarily released */ -{ - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(ut_is_2pow(size)); - ut_ad(size >= UNIV_ZIP_SIZE_MIN); - ut_ad(size <= UNIV_PAGE_SIZE); - - return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), - lru)); -} - -/**********************************************************************//** -Deallocate a block. */ -UNIV_INLINE -void -buf_buddy_free( -/*===========*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool in which - the block resides */ - void* buf, /*!< in: block to be freed, must not - be pointed to by the buffer pool */ - ulint size) /*!< in: block size, - up to UNIV_PAGE_SIZE */ -{ - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(ut_is_2pow(size)); - ut_ad(size >= UNIV_ZIP_SIZE_MIN); - ut_ad(size <= UNIV_PAGE_SIZE); - - 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/buf0buddy.inl b/storage/innobase/include/buf0buddy.inl new file mode 100644 index 00000000000..4afa795e762 --- /dev/null +++ b/storage/innobase/include/buf0buddy.inl @@ -0,0 +1,139 @@ +/***************************************************************************** + +Copyright (c) 2006, 2016, 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/buf0buddy.ic +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" + +/**********************************************************************//** +Allocate a block. The thread calling this function must hold +buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex. +The buf_pool_mutex may be released and reacquired. +@return allocated block, never NULL */ +void* +buf_buddy_alloc_low( +/*================*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + ulint i, /*!< in: index of buf_pool->zip_free[], + or BUF_BUDDY_SIZES */ + ibool* lru) /*!< in: pointer to a variable that + will be assigned TRUE if storage was + allocated from the LRU list and + buf_pool->mutex was temporarily + released */ + MY_ATTRIBUTE((malloc, nonnull)); + +/**********************************************************************//** +Deallocate a block. */ +void +buf_buddy_free_low( +/*===============*/ + buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + void* buf, /*!< in: block to be freed, must not be + pointed to by the buffer pool */ + ulint i) /*!< in: index of buf_pool->zip_free[], + or BUF_BUDDY_SIZES */ + MY_ATTRIBUTE((nonnull)); + +/**********************************************************************//** +Get the index of buf_pool->zip_free[] for a given block size. +@return index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ +UNIV_INLINE +ulint +buf_buddy_get_slot( +/*===============*/ + ulint size) /*!< in: block size */ +{ + ulint i; + ulint s; + + ut_ad(size >= UNIV_ZIP_SIZE_MIN); + + for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) { + } + + ut_ad(i <= BUF_BUDDY_SIZES); + return(i); +} + +/**********************************************************************//** +Allocate a block. The thread calling this function must hold +buf_pool->mutex and must not hold buf_pool->zip_mutex or any +block->mutex. The buf_pool->mutex may be released and reacquired. +This function should only be used for allocating compressed page frames. +@return allocated block, never NULL */ +UNIV_INLINE +byte* +buf_buddy_alloc( +/*============*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool in which + the page resides */ + ulint size, /*!< in: compressed page size + (between UNIV_ZIP_SIZE_MIN and + UNIV_PAGE_SIZE) */ + ibool* lru) /*!< in: pointer to a variable + that will be assigned TRUE if + storage was allocated from the + LRU list and buf_pool->mutex was + temporarily released */ +{ + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(ut_is_2pow(size)); + ut_ad(size >= UNIV_ZIP_SIZE_MIN); + ut_ad(size <= UNIV_PAGE_SIZE); + + return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), + lru)); +} + +/**********************************************************************//** +Deallocate a block. */ +UNIV_INLINE +void +buf_buddy_free( +/*===========*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool in which + the block resides */ + void* buf, /*!< in: block to be freed, must not + be pointed to by the buffer pool */ + ulint size) /*!< in: block size, + up to UNIV_PAGE_SIZE */ +{ + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(ut_is_2pow(size)); + ut_ad(size >= UNIV_ZIP_SIZE_MIN); + ut_ad(size <= UNIV_PAGE_SIZE); + + 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 468e6be4def..20281040862 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -2408,7 +2408,7 @@ struct CheckUnzipLRUAndLRUList { }; #endif /* UNIV_DEBUG || defined UNIV_BUF_DEBUG */ -#include "buf0buf.ic" +#include "buf0buf.inl" #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic deleted file mode 100644 index 49b741ab5c8..00000000000 --- a/storage/innobase/include/buf0buf.ic +++ /dev/null @@ -1,1478 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. -Copyright (c) 2014, 2019, MariaDB Corporation. - -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - -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/buf0buf.ic -The database buffer buf_pool - -Created 11/5/1995 Heikki Tuuri -*******************************************************/ - -#include "mtr0mtr.h" -#include "buf0flu.h" -#include "buf0lru.h" -#include "buf0rea.h" -#include "fsp0types.h" - -/** A chunk of buffers. The buffer pool is allocated in chunks. */ -struct buf_chunk_t{ - ulint size; /*!< size of frames[] and blocks[] */ - unsigned char* mem; /*!< pointer to the memory area which - was allocated for the frames */ - ut_new_pfx_t mem_pfx; /*!< Auxiliary structure, describing - "mem". It is filled by the allocator's - alloc method and later passed to the - deallocate method. */ - buf_block_t* blocks; /*!< array of buffer control blocks */ - - /** Get the size of 'mem' in bytes. */ - size_t mem_size() const { - return(mem_pfx.m_size); - } -}; - -bool buf_pool_t::is_block_field(const void *ptr) const -{ - const buf_chunk_t* chunk= chunks; - const buf_chunk_t *const echunk= chunk + ut_min(n_chunks, - n_chunks_new); - /* TODO: protect chunks with a mutex (the older pointer will - currently remain during resize()) */ - while (chunk < echunk) - { - if (ptr >= reinterpret_cast(chunk->blocks) && - ptr < reinterpret_cast( - chunk->blocks + chunk->size)) - return true; - chunk++; - } - - return false; -} - -/*********************************************************************//** -Gets the current size of buffer buf_pool in bytes. -@return size in bytes */ -UNIV_INLINE -ulint -buf_pool_get_curr_size(void) -/*========================*/ -{ - return(srv_buf_pool_curr_size); -} - -/********************************************************************//** -Calculates the index of a buffer pool to the buf_pool[] array. -@return the position of the buffer pool in buf_pool[] */ -UNIV_INLINE -unsigned -buf_pool_index( -/*===========*/ - const buf_pool_t* buf_pool) /*!< in: buffer pool */ -{ - unsigned i = unsigned(buf_pool - buf_pool_ptr); - ut_ad(i < MAX_BUFFER_POOLS); - ut_ad(i < srv_buf_pool_instances); - return(i); -} - -/******************************************************************//** -Returns the buffer pool instance given a page instance -@return buf_pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_bpage( -/*================*/ - const buf_page_t* bpage) /*!< in: buffer pool page */ -{ - ut_ad(bpage->buf_pool_index < srv_buf_pool_instances); - return(&buf_pool_ptr[bpage->buf_pool_index]); -} - -/******************************************************************//** -Returns the buffer pool instance given a block instance -@return buf_pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_block( -/*================*/ - const buf_block_t* block) /*!< in: block */ -{ - return(buf_pool_from_bpage(&block->page)); -} - -/*********************************************************************//** -Gets the current size of buffer buf_pool in pages. -@return size in pages*/ -UNIV_INLINE -ulint -buf_pool_get_n_pages(void) -/*======================*/ -{ - if (!buf_pool_ptr) - return buf_pool_get_curr_size() >> srv_page_size_shift; - - ulint chunk_size= 0; - for (uint i= 0; i < srv_buf_pool_instances; i++) - { - buf_pool_t* buf_pool = buf_pool_from_array(i); - for (uint j= 0; j < buf_pool->n_chunks; j++) - chunk_size+= buf_pool->chunks[j].size; - } - return chunk_size; -} - -/********************************************************************//** -Reads the freed_page_clock of a buffer block. -@return freed_page_clock */ -UNIV_INLINE -unsigned -buf_page_get_freed_page_clock( -/*==========================*/ - const buf_page_t* bpage) /*!< in: block */ -{ - /* This is sometimes read without holding buf_pool->mutex. */ - return(bpage->freed_page_clock); -} - -/********************************************************************//** -Reads the freed_page_clock of a buffer block. -@return freed_page_clock */ -UNIV_INLINE -unsigned -buf_block_get_freed_page_clock( -/*===========================*/ - const buf_block_t* block) /*!< in: block */ -{ - return(buf_page_get_freed_page_clock(&block->page)); -} - -/********************************************************************//** -Tells if a block is still close enough to the MRU end of the LRU list -meaning that it is not in danger of getting evicted and also implying -that it has been accessed recently. -Note that this is for heuristics only and does not reserve buffer pool -mutex. -@return TRUE if block is close to MRU end of LRU */ -UNIV_INLINE -ibool -buf_page_peek_if_young( -/*===================*/ - const buf_page_t* bpage) /*!< in: block */ -{ - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - /* FIXME: bpage->freed_page_clock is 31 bits */ - return((buf_pool->freed_page_clock & ((1UL << 31) - 1)) - < (bpage->freed_page_clock - + (buf_pool->curr_size - * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio) - / (BUF_LRU_OLD_RATIO_DIV * 4)))); -} - -/********************************************************************//** -Recommends a move of a block to the start of the LRU list if there is danger -of dropping from the buffer pool. NOTE: does not reserve the buffer pool -mutex. -@return TRUE if should be made younger */ -UNIV_INLINE -ibool -buf_page_peek_if_too_old( -/*=====================*/ - const buf_page_t* bpage) /*!< in: block to make younger */ -{ - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - if (buf_pool->freed_page_clock == 0) { - /* If eviction has not started yet, do not update the - statistics or move blocks in the LRU list. This is - either the warm-up phase or an in-memory workload. */ - return(FALSE); - } else if (buf_LRU_old_threshold_ms && bpage->old) { - unsigned access_time = buf_page_is_accessed(bpage); - - /* It is possible that the below comparison returns an - unexpected result. 2^32 milliseconds pass in about 50 days, - so if the difference between ut_time_ms() and access_time - is e.g. 50 days + 15 ms, then the below will behave as if - it is 15 ms. This is known and fixing it would require to - increase buf_page_t::access_time from 32 to 64 bits. */ - if (access_time > 0 - && ((ib_uint32_t) (ut_time_ms() - access_time)) - >= buf_LRU_old_threshold_ms) { - return(TRUE); - } - - buf_pool->stat.n_pages_not_made_young++; - return(FALSE); - } else { - return(!buf_page_peek_if_young(bpage)); - } -} - -/*********************************************************************//** -Gets the state of a block. -@return state */ -UNIV_INLINE -enum buf_page_state -buf_page_get_state( -/*===============*/ - const buf_page_t* bpage) /*!< in: pointer to the control block */ -{ - enum buf_page_state state = bpage->state; - -#ifdef UNIV_DEBUG - switch (state) { - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_FILE_PAGE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - break; - default: - ut_error; - } -#endif /* UNIV_DEBUG */ - - return(state); -} -/*********************************************************************//** -Gets the state of a block. -@return state */ -UNIV_INLINE -enum buf_page_state -buf_block_get_state( -/*================*/ - const buf_block_t* block) /*!< in: pointer to the control block */ -{ - return(buf_page_get_state(&block->page)); -} - -/*********************************************************************//** -Gets the state name for state of a block -@return name or "CORRUPTED" */ -UNIV_INLINE -const char* -buf_get_state_name( -/*===============*/ - const buf_block_t* block) /*!< in: pointer to the control - block */ -{ - enum buf_page_state state = buf_page_get_state(&block->page); - - switch (state) { - case BUF_BLOCK_POOL_WATCH: - return (const char *) "BUF_BLOCK_POOL_WATCH"; - case BUF_BLOCK_ZIP_PAGE: - return (const char *) "BUF_BLOCK_ZIP_PAGE"; - case BUF_BLOCK_ZIP_DIRTY: - return (const char *) "BUF_BLOCK_ZIP_DIRTY"; - case BUF_BLOCK_NOT_USED: - return (const char *) "BUF_BLOCK_NOT_USED"; - case BUF_BLOCK_READY_FOR_USE: - return (const char *) "BUF_BLOCK_NOT_USED"; - case BUF_BLOCK_FILE_PAGE: - return (const char *) "BUF_BLOCK_FILE_PAGE"; - case BUF_BLOCK_MEMORY: - return (const char *) "BUF_BLOCK_MEMORY"; - case BUF_BLOCK_REMOVE_HASH: - return (const char *) "BUF_BLOCK_REMOVE_HASH"; - default: - return (const char *) "CORRUPTED"; - } -} - -/*********************************************************************//** -Sets the state of a block. */ -UNIV_INLINE -void -buf_page_set_state( -/*===============*/ - buf_page_t* bpage, /*!< in/out: pointer to control block */ - enum buf_page_state state) /*!< in: state */ -{ -#ifdef UNIV_DEBUG - enum buf_page_state old_state = buf_page_get_state(bpage); - - switch (old_state) { - case BUF_BLOCK_POOL_WATCH: - ut_error; - break; - case BUF_BLOCK_ZIP_PAGE: - ut_a(state == BUF_BLOCK_ZIP_DIRTY); - break; - case BUF_BLOCK_ZIP_DIRTY: - ut_a(state == BUF_BLOCK_ZIP_PAGE); - break; - case BUF_BLOCK_NOT_USED: - ut_a(state == BUF_BLOCK_READY_FOR_USE); - break; - case BUF_BLOCK_READY_FOR_USE: - ut_a(state == BUF_BLOCK_MEMORY - || state == BUF_BLOCK_FILE_PAGE - || state == BUF_BLOCK_NOT_USED); - break; - case BUF_BLOCK_MEMORY: - ut_a(state == BUF_BLOCK_NOT_USED); - break; - case BUF_BLOCK_FILE_PAGE: - if (!(state == BUF_BLOCK_NOT_USED - || state == BUF_BLOCK_REMOVE_HASH - || state == BUF_BLOCK_FILE_PAGE)) { - const char *old_state_name = buf_get_state_name((buf_block_t*)bpage); - bpage->state = state; - - fprintf(stderr, - "InnoDB: Error: block old state %d (%s) " - " new state %d (%s) not correct\n", - old_state, - old_state_name, - state, - buf_get_state_name((buf_block_t*)bpage)); - ut_a(state == BUF_BLOCK_NOT_USED - || state == BUF_BLOCK_REMOVE_HASH - || state == BUF_BLOCK_FILE_PAGE); - } - - break; - case BUF_BLOCK_REMOVE_HASH: - ut_a(state == BUF_BLOCK_MEMORY); - break; - } -#endif /* UNIV_DEBUG */ - bpage->state = state; -} - -/*********************************************************************//** -Sets the state of a block. */ -UNIV_INLINE -void -buf_block_set_state( -/*================*/ - buf_block_t* block, /*!< in/out: pointer to control block */ - enum buf_page_state state) /*!< in: state */ -{ - buf_page_set_state(&block->page, state); -} - -/*********************************************************************//** -Determines if a block is mapped to a tablespace. -@return TRUE if mapped */ -UNIV_INLINE -ibool -buf_page_in_file( -/*=============*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ -{ - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: - ut_error; - break; - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - case BUF_BLOCK_FILE_PAGE: - return(TRUE); - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - break; - } - - return(FALSE); -} - -/*********************************************************************//** -Determines if a block should be on unzip_LRU list. -@return TRUE if block belongs to unzip_LRU */ -UNIV_INLINE -ibool -buf_page_belongs_to_unzip_LRU( -/*==========================*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ -{ - ut_ad(buf_page_in_file(bpage)); - - return(bpage->zip.data - && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); -} - -/*********************************************************************//** -Gets the mutex of a block. -@return pointer to mutex protecting bpage */ -UNIV_INLINE -BPageMutex* -buf_page_get_mutex( -/*===============*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ -{ - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: - ut_error; - return(NULL); - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - return(&buf_pool->zip_mutex); - default: - return(&((buf_block_t*) bpage)->mutex); - } -} - -/*********************************************************************//** -Get the flush type of a page. -@return flush type */ -UNIV_INLINE -buf_flush_t -buf_page_get_flush_type( -/*====================*/ - const buf_page_t* bpage) /*!< in: buffer page */ -{ - buf_flush_t flush_type = (buf_flush_t) bpage->flush_type; - -#ifdef UNIV_DEBUG - switch (flush_type) { - case BUF_FLUSH_LRU: - case BUF_FLUSH_LIST: - case BUF_FLUSH_SINGLE_PAGE: - return(flush_type); - case BUF_FLUSH_N_TYPES: - ut_error; - } - ut_error; -#endif /* UNIV_DEBUG */ - return(flush_type); -} -/*********************************************************************//** -Set the flush type of a page. */ -UNIV_INLINE -void -buf_page_set_flush_type( -/*====================*/ - buf_page_t* bpage, /*!< in: buffer page */ - buf_flush_t flush_type) /*!< in: flush type */ -{ - bpage->flush_type = flush_type; - ut_ad(buf_page_get_flush_type(bpage) == flush_type); -} - -/** Map a block to a file page. -@param[in,out] block pointer to control block -@param[in] page_id page id */ -UNIV_INLINE -void -buf_block_set_file_page( - buf_block_t* block, - const page_id_t page_id) -{ - buf_block_set_state(block, BUF_BLOCK_FILE_PAGE); - block->page.id = page_id; -} - -/*********************************************************************//** -Gets the io_fix state of a block. -@return io_fix state */ -UNIV_INLINE -enum buf_io_fix -buf_page_get_io_fix( -/*================*/ - const buf_page_t* bpage) /*!< in: pointer to the control block */ -{ - ut_ad(bpage != NULL); - - enum buf_io_fix io_fix = bpage->io_fix; - -#ifdef UNIV_DEBUG - switch (io_fix) { - case BUF_IO_NONE: - case BUF_IO_READ: - case BUF_IO_WRITE: - case BUF_IO_PIN: - return(io_fix); - } - ut_error; -#endif /* UNIV_DEBUG */ - return(io_fix); -} - -/*********************************************************************//** -Gets the io_fix state of a block. -@return io_fix state */ -UNIV_INLINE -enum buf_io_fix -buf_block_get_io_fix( -/*=================*/ - const buf_block_t* block) /*!< in: pointer to the control block */ -{ - return(buf_page_get_io_fix(&block->page)); -} - -/*********************************************************************//** -Sets the io_fix state of a block. */ -UNIV_INLINE -void -buf_page_set_io_fix( -/*================*/ - buf_page_t* bpage, /*!< in/out: control block */ - enum buf_io_fix io_fix) /*!< in: io_fix state */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - - bpage->io_fix = io_fix; - ut_ad(buf_page_get_io_fix(bpage) == io_fix); -} - -/*********************************************************************//** -Sets the io_fix state of a block. */ -UNIV_INLINE -void -buf_block_set_io_fix( -/*=================*/ - buf_block_t* block, /*!< in/out: control block */ - enum buf_io_fix io_fix) /*!< in: io_fix state */ -{ - buf_page_set_io_fix(&block->page, io_fix); -} - -/*********************************************************************//** -Makes a block sticky. A sticky block implies that even after we release -the buf_pool->mutex and the block->mutex: -* it cannot be removed from the flush_list -* the block descriptor cannot be relocated -* it cannot be removed from the LRU list -Note that: -* the block can still change its position in the LRU list -* the next and previous pointers can change. */ -UNIV_INLINE -void -buf_page_set_sticky( -/*================*/ - buf_page_t* bpage) /*!< in/out: control block */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE); - - bpage->io_fix = BUF_IO_PIN; -} - -/*********************************************************************//** -Removes stickiness of a block. */ -UNIV_INLINE -void -buf_page_unset_sticky( -/*==================*/ - buf_page_t* bpage) /*!< in/out: control block */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN); - - bpage->io_fix = BUF_IO_NONE; -} - -/********************************************************************//** -Determine if a buffer block can be relocated in memory. The block -can be dirty, but it must not be I/O-fixed or bufferfixed. */ -UNIV_INLINE -ibool -buf_page_can_relocate( -/*==================*/ - const buf_page_t* bpage) /*!< control block being relocated */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(buf_page_in_file(bpage)); - ut_ad(bpage->in_LRU_list); - - return(buf_page_get_io_fix(bpage) == BUF_IO_NONE - && bpage->buf_fix_count == 0); -} - -/*********************************************************************//** -Determine if a block has been flagged old. -@return TRUE if old */ -UNIV_INLINE -ibool -buf_page_is_old( -/*============*/ - const buf_page_t* bpage) /*!< in: control block */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ - ut_ad(buf_page_in_file(bpage)); - - return(bpage->old); -} - -/*********************************************************************//** -Flag a block old. */ -UNIV_INLINE -void -buf_page_set_old( -/*=============*/ - buf_page_t* bpage, /*!< in/out: control block */ - bool old) /*!< in: old */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); -#endif /* UNIV_DEBUG */ - ut_a(buf_page_in_file(bpage)); - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(bpage->in_LRU_list); - -#ifdef UNIV_LRU_DEBUG - ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL)); - /* If a block is flagged "old", the LRU_old list must exist. */ - ut_a(!old || buf_pool->LRU_old); - - if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) { - const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); - const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage); - if (prev->old == next->old) { - ut_a(prev->old == old); - } else { - ut_a(!prev->old); - ut_a(buf_pool->LRU_old == (old ? bpage : next)); - } - } -#endif /* UNIV_LRU_DEBUG */ - - bpage->old = old; -} - -/*********************************************************************//** -Determine the time of first access of a block in the buffer pool. -@return ut_time_ms() at the time of first access, 0 if not accessed */ -UNIV_INLINE -unsigned -buf_page_is_accessed( -/*=================*/ - const buf_page_t* bpage) /*!< in: control block */ -{ - ut_ad(buf_page_in_file(bpage)); - - return(bpage->access_time); -} - -/*********************************************************************//** -Flag a block accessed. */ -UNIV_INLINE -void -buf_page_set_accessed( -/*==================*/ - buf_page_t* bpage) /*!< in/out: control block */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(!buf_pool_mutex_own(buf_pool)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); -#endif /* UNIV_DEBUG */ - - ut_a(buf_page_in_file(bpage)); - - if (bpage->access_time == 0) { - /* Make this the time of the first access. */ - bpage->access_time = static_cast(ut_time_ms()); - } -} - -/*********************************************************************//** -Gets the buf_block_t handle of a buffered file block if an uncompressed -page frame exists, or NULL. -@return control block, or NULL */ -UNIV_INLINE -buf_block_t* -buf_page_get_block( -/*===============*/ - buf_page_t* bpage) /*!< in: control block, or NULL */ -{ - if (bpage != NULL) { - ut_ad(buf_page_in_file(bpage)); - - if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { - return((buf_block_t*) bpage); - } - } - - return(NULL); -} - -#ifdef UNIV_DEBUG -/*********************************************************************//** -Gets a pointer to the memory frame of a block. -@return pointer to the frame */ -UNIV_INLINE -buf_frame_t* -buf_block_get_frame( -/*================*/ - const buf_block_t* block) /*!< in: pointer to the control block */ -{ - if (!block) { - return NULL; - } - - switch (buf_block_get_state(block)) { - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - case BUF_BLOCK_NOT_USED: - ut_error; - break; - case BUF_BLOCK_FILE_PAGE: - ut_a(block->page.buf_fix_count > 0); - /* fall through */ - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - goto ok; - } - ut_error; -ok: - return((buf_frame_t*) block->frame); -} -#endif /* UNIV_DEBUG */ - -/*********************************************************************** -FIXME_FTS Gets the frame the pointer is pointing to. */ -UNIV_INLINE -buf_frame_t* -buf_frame_align( -/*============*/ - /* out: pointer to frame */ - byte* ptr) /* in: pointer to a frame */ -{ - buf_frame_t* frame; - - ut_ad(ptr); - - frame = (buf_frame_t*) ut_align_down(ptr, UNIV_PAGE_SIZE); - - return(frame); -} - -/**********************************************************************//** -Gets the space id, page offset, and byte offset within page of a -pointer pointing to a buffer frame containing a file page. */ -UNIV_INLINE -void -buf_ptr_get_fsp_addr( -/*=================*/ - const void* ptr, /*!< in: pointer to a buffer frame */ - ulint* space, /*!< out: space id */ - fil_addr_t* addr) /*!< out: page offset and byte offset */ -{ - const page_t* page = (const page_t*) ut_align_down(ptr, - UNIV_PAGE_SIZE); - - *space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET); - addr->boffset = ut_align_offset(ptr, UNIV_PAGE_SIZE); -} - -/**********************************************************************//** -Gets the hash value of the page the pointer is pointing to. This can be used -in searches in the lock hash table. -@return lock hash value */ -UNIV_INLINE -unsigned -buf_block_get_lock_hash_val( -/*========================*/ - const buf_block_t* block) /*!< in: block */ -{ - ut_ad(block); - ut_ad(buf_page_in_file(&block->page)); - ut_ad(rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_X) - || rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_S)); - - return(block->lock_hash_val); -} - -/********************************************************************//** -Allocates a buf_page_t descriptor. This function must succeed. In case -of failure we assert in this function. -@return: the allocated descriptor. */ -UNIV_INLINE -buf_page_t* -buf_page_alloc_descriptor(void) -/*===========================*/ -{ - buf_page_t* bpage; - - bpage = (buf_page_t*) ut_zalloc_nokey(sizeof *bpage); - ut_ad(bpage); - MEM_UNDEFINED(bpage, sizeof *bpage); - - return(bpage); -} - -/********************************************************************//** -Free a buf_page_t descriptor. */ -UNIV_INLINE -void -buf_page_free_descriptor( -/*=====================*/ - buf_page_t* bpage) /*!< in: bpage descriptor to free. */ -{ - ut_free(bpage); -} - -/********************************************************************//** -Frees a buffer block which does not contain a file page. */ -UNIV_INLINE -void -buf_block_free( -/*===========*/ - buf_block_t* block) /*!< in, own: block to be freed */ -{ - buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); - - buf_pool_mutex_enter(buf_pool); - - buf_page_mutex_enter(block); - - ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE); - - buf_LRU_block_free_non_file_page(block); - - buf_page_mutex_exit(block); - - buf_pool_mutex_exit(buf_pool); -} - -/*********************************************************************//** -Copies contents of a buffer frame to a given buffer. -@return buf */ -UNIV_INLINE -byte* -buf_frame_copy( -/*===========*/ - byte* buf, /*!< in: buffer to copy to */ - const buf_frame_t* frame) /*!< in: buffer frame */ -{ - ut_ad(buf && frame); - - ut_memcpy(buf, frame, UNIV_PAGE_SIZE); - - return(buf); -} - -/********************************************************************//** -Gets the youngest modification log sequence number for a frame. -Returns zero if not file page or no modification occurred yet. -@return newest modification to page */ -UNIV_INLINE -lsn_t -buf_page_get_newest_modification( -/*=============================*/ - const buf_page_t* bpage) /*!< in: block containing the - page frame */ -{ - lsn_t lsn; - BPageMutex* block_mutex = buf_page_get_mutex(bpage); - - mutex_enter(block_mutex); - - if (buf_page_in_file(bpage)) { - lsn = bpage->newest_modification; - } else { - lsn = 0; - } - - mutex_exit(block_mutex); - - return(lsn); -} - -/********************************************************************//** -Increments the modify clock of a frame by 1. The caller must (1) own the -buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock -on the block. */ -UNIV_INLINE -void -buf_block_modify_clock_inc( -/*=======================*/ - buf_block_t* block) /*!< in: block */ -{ -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); - - /* No latch is acquired for the shared temporary tablespace. */ - if (!fsp_is_system_temporary(block->page.id.space())) { - ut_ad((buf_pool_mutex_own(buf_pool) - && (block->page.buf_fix_count == 0)) - || rw_lock_own_flagged(&block->lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); - } -#endif /* UNIV_DEBUG */ - assert_block_ahi_valid(block); - - block->modify_clock++; -} - -/********************************************************************//** -Returns the value of the modify clock. The caller must have an s-lock -or x-lock on the block. -@return value */ -UNIV_INLINE -ib_uint64_t -buf_block_get_modify_clock( -/*=======================*/ - buf_block_t* block) /*!< in: block */ -{ -#ifdef UNIV_DEBUG - /* No latch is acquired for the shared temporary tablespace. */ - if (!fsp_is_system_temporary(block->page.id.space())) { - ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S) - || rw_lock_own(&(block->lock), RW_LOCK_X) - || rw_lock_own(&(block->lock), RW_LOCK_SX)); - } -#endif /* UNIV_DEBUG */ - - 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 -void -buf_block_buf_fix_inc_func( -/*=======================*/ -#ifdef UNIV_DEBUG - const char* file, /*!< in: file name */ - unsigned line, /*!< in: line */ -#endif /* UNIV_DEBUG */ - buf_block_t* block) /*!< in/out: block to bufferfix */ -{ -#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())) { - ibool ret; - 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); -} - -/*******************************************************************//** -Decrements the bufferfix count. */ -UNIV_INLINE -void -buf_block_buf_fix_dec( -/*==================*/ - buf_block_t* block) /*!< in/out: block to bufferunfix */ -{ -#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); - } -#endif /* UNIV_DEBUG */ - - buf_block_unfix(block); -} - -/** Returns the buffer pool instance given a page id. -@param[in] page_id page id -@return buffer pool */ -inline buf_pool_t* buf_pool_get(const page_id_t page_id) -{ - /* 2log of BUF_READ_AHEAD_AREA (64) */ - ulint ignored_page_no = page_id.page_no() >> 6; - - page_id_t id(page_id.space(), ignored_page_no); - - ulint i = id.fold() % srv_buf_pool_instances; - - return(&buf_pool_ptr[i]); -} - -/******************************************************************//** -Returns the buffer pool instance given its array index -@return buffer pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_array( -/*================*/ - ulint index) /*!< in: array index to get - buffer pool instance from */ -{ - ut_ad(index < MAX_BUFFER_POOLS); - ut_ad(index < srv_buf_pool_instances); - return(&buf_pool_ptr[index]); -} - -/** Returns the control block of a file page, NULL if not found. -@param[in] buf_pool buffer pool instance -@param[in] page_id page id -@return block, NULL if not found */ -UNIV_INLINE -buf_page_t* -buf_page_hash_get_low( - buf_pool_t* buf_pool, - const page_id_t page_id) -{ - buf_page_t* bpage; - -#ifdef UNIV_DEBUG - rw_lock_t* hash_lock; - - hash_lock = hash_get_lock(buf_pool->page_hash, page_id.fold()); - ut_ad(rw_lock_own(hash_lock, RW_LOCK_X) - || rw_lock_own(hash_lock, RW_LOCK_S)); -#endif /* UNIV_DEBUG */ - - /* Look for the page in the hash table */ - - HASH_SEARCH(hash, buf_pool->page_hash, page_id.fold(), buf_page_t*, - bpage, - ut_ad(bpage->in_page_hash && !bpage->in_zip_hash - && buf_page_in_file(bpage)), - page_id == bpage->id); - if (bpage) { - ut_a(buf_page_in_file(bpage)); - ut_ad(bpage->in_page_hash); - ut_ad(!bpage->in_zip_hash); - ut_ad(buf_pool_from_bpage(bpage) == buf_pool); - } - - return(bpage); -} - -/** Returns the control block of a file page, NULL if not found. -If the block is found and lock is not NULL then the appropriate -page_hash lock is acquired in the specified lock mode. Otherwise, -mode value is ignored. It is up to the caller to release the -lock. If the block is found and the lock is NULL then the page_hash -lock is released by this function. -@param[in] buf_pool buffer pool instance -@param[in] page_id page id -@param[in,out] lock lock of the page hash acquired if bpage is -found, NULL otherwise. If NULL is passed then the hash_lock is released by -this function. -@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if -lock == NULL -@param[in] watch if true, return watch sentinel also. -@return pointer to the bpage or NULL; if NULL, lock is also NULL or -a watch sentinel. */ -UNIV_INLINE -buf_page_t* -buf_page_hash_get_locked( - buf_pool_t* buf_pool, - const page_id_t page_id, - rw_lock_t** lock, - ulint lock_mode, - bool watch) -{ - buf_page_t* bpage = NULL; - rw_lock_t* hash_lock; - ulint mode = RW_LOCK_S; - - if (lock != NULL) { - *lock = NULL; - ut_ad(lock_mode == RW_LOCK_X - || lock_mode == RW_LOCK_S); - mode = lock_mode; - } - - hash_lock = hash_get_lock(buf_pool->page_hash, page_id.fold()); - - ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X) - && !rw_lock_own(hash_lock, RW_LOCK_S)); - - if (mode == RW_LOCK_S) { - rw_lock_s_lock(hash_lock); - - /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = hash_lock_s_confirm( - hash_lock, buf_pool->page_hash, page_id.fold()); - } else { - rw_lock_x_lock(hash_lock); - /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = hash_lock_x_confirm( - hash_lock, buf_pool->page_hash, page_id.fold()); - } - - bpage = buf_page_hash_get_low(buf_pool, page_id); - - if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) { - if (!watch) { - bpage = NULL; - } - goto unlock_and_exit; - } - - ut_ad(buf_page_in_file(bpage)); - ut_ad(page_id == bpage->id); - - if (lock == NULL) { - /* The caller wants us to release the page_hash lock */ - goto unlock_and_exit; - } else { - /* To be released by the caller */ - *lock = hash_lock; - goto exit; - } - -unlock_and_exit: - if (mode == RW_LOCK_S) { - rw_lock_s_unlock(hash_lock); - } else { - rw_lock_x_unlock(hash_lock); - } -exit: - return(bpage); -} - -/** Returns the control block of a file page, NULL if not found. -If the block is found and lock is not NULL then the appropriate -page_hash lock is acquired in the specified lock mode. Otherwise, -mode value is ignored. It is up to the caller to release the -lock. If the block is found and the lock is NULL then the page_hash -lock is released by this function. -@param[in] buf_pool buffer pool instance -@param[in] page_id page id -@param[in,out] lock lock of the page hash acquired if bpage is -found, NULL otherwise. If NULL is passed then the hash_lock is released by -this function. -@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if -lock == NULL -@return pointer to the block or NULL; if NULL, lock is also NULL. */ -UNIV_INLINE -buf_block_t* -buf_block_hash_get_locked( - buf_pool_t* buf_pool, - const page_id_t page_id, - rw_lock_t** lock, - ulint lock_mode) -{ - buf_page_t* bpage = buf_page_hash_get_locked(buf_pool, - page_id, - lock, - lock_mode); - buf_block_t* block = buf_page_get_block(bpage); - - if (block != NULL) { - - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_ad(!lock || rw_lock_own(*lock, lock_mode)); - - return(block); - } else if (bpage) { - /* It is not a block. Just a bpage */ - ut_ad(buf_page_in_file(bpage)); - - if (lock) { - if (lock_mode == RW_LOCK_S) { - rw_lock_s_unlock(*lock); - } else { - rw_lock_x_unlock(*lock); - } - } - *lock = NULL; - return(NULL); - } - - ut_ad(!bpage); - ut_ad(lock == NULL ||*lock == NULL); - return(NULL); -} - -/** Returns TRUE if the page can be found in the buffer pool hash table. -NOTE that it is possible that the page is not yet read from disk, -though. -@param[in] page_id page id -@return true if found in the page hash table */ -inline bool buf_page_peek(const page_id_t page_id) -{ - buf_pool_t* buf_pool = buf_pool_get(page_id); - - return(buf_page_hash_get(buf_pool, page_id) != NULL); -} - -/********************************************************************//** -Releases a compressed-only page acquired with buf_page_get_zip(). */ -UNIV_INLINE -void -buf_page_release_zip( -/*=================*/ - buf_page_t* bpage) /*!< in: buffer block */ -{ - ut_ad(bpage); - ut_a(bpage->buf_fix_count > 0); - - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_FILE_PAGE: -#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. */ - buf_block_t* block = reinterpret_cast(bpage); - if (!fsp_is_system_temporary(block->page.id.space())) { - 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(bpage)); - return; - - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - break; - } - - ut_error; -} - -/********************************************************************//** -Releases a latch, if specified. */ -UNIV_INLINE -void -buf_page_release_latch( -/*===================*/ - buf_block_t* block, /*!< in: buffer block */ - ulint rw_latch) /*!< in: RW_S_LATCH, RW_X_LATCH, - RW_NO_LATCH */ -{ -#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); - } -#endif /* UNIV_DEBUG */ - - if (rw_latch == RW_S_LATCH) { - rw_lock_s_unlock(&block->lock); - } else if (rw_latch == RW_SX_LATCH) { - rw_lock_sx_unlock(&block->lock); - } else if (rw_latch == RW_X_LATCH) { - rw_lock_x_unlock(&block->lock); - } -} - -#ifdef UNIV_DEBUG -/*********************************************************************//** -Adds latch level info for the rw-lock protecting the buffer frame. This -should be called in the debug version after a successful latching of a -page if we know the latching order level of the acquired latch. */ -UNIV_INLINE -void -buf_block_dbg_add_level( -/*====================*/ - buf_block_t* block, /*!< in: buffer page - where we have acquired latch */ - latch_level_t level) /*!< in: latching order level */ -{ - sync_check_lock(&block->lock, level); -} - -#endif /* UNIV_DEBUG */ -/********************************************************************//** -Acquire mutex on all buffer pool instances. */ -UNIV_INLINE -void -buf_pool_mutex_enter_all(void) -/*==========================*/ -{ - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - - buf_pool_mutex_enter(buf_pool); - } -} - -/********************************************************************//** -Release mutex on all buffer pool instances. */ -UNIV_INLINE -void -buf_pool_mutex_exit_all(void) -/*=========================*/ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - buf_pool_mutex_exit(buf_pool); - } -} -/*********************************************************************//** -Get the nth chunk's buffer block in the specified buffer pool. -@return the nth chunk's buffer block. */ -UNIV_INLINE -buf_block_t* -buf_get_nth_chunk_block( -/*====================*/ - const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint n, /*!< in: nth chunk in the buffer pool */ - ulint* chunk_size) /*!< in: chunk size */ -{ - const buf_chunk_t* chunk; - - chunk = buf_pool->chunks + n; - *chunk_size = chunk->size; - return(chunk->blocks); -} - -/********************************************************************//** -Get buf frame. */ -UNIV_INLINE -void * -buf_page_get_frame( -/*===============*/ - const buf_page_t* bpage) /*!< in: buffer pool page */ -{ - /* In encryption/compression buffer pool page may contain extra - buffer where result is stored. */ - if (bpage->slot && bpage->slot->out_buf) { - return bpage->slot->out_buf; - } else if (bpage->zip.data) { - return bpage->zip.data; - } else { - return ((buf_block_t*) bpage)->frame; - } -} - -/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit, -if needed. -@param[in] size size in bytes -@return aligned size */ -UNIV_INLINE -ulint -buf_pool_size_align( - ulint size) -{ - const ib_uint64_t m = ((ib_uint64_t)srv_buf_pool_instances) * srv_buf_pool_chunk_unit; - size = ut_max(size, srv_buf_pool_min_size); - - if (size % m == 0) { - return(size); - } else { - return (ulint)((size / m + 1) * m); - } -} diff --git a/storage/innobase/include/buf0buf.inl b/storage/innobase/include/buf0buf.inl new file mode 100644 index 00000000000..49b741ab5c8 --- /dev/null +++ b/storage/innobase/include/buf0buf.inl @@ -0,0 +1,1478 @@ +/***************************************************************************** + +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2008, Google Inc. +Copyright (c) 2014, 2019, MariaDB Corporation. + +Portions of this file contain modifications contributed and copyrighted by +Google, Inc. Those modifications are gratefully acknowledged and are described +briefly in the InnoDB documentation. The contributions by Google are +incorporated with their permission, and subject to the conditions contained in +the file COPYING.Google. + +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/buf0buf.ic +The database buffer buf_pool + +Created 11/5/1995 Heikki Tuuri +*******************************************************/ + +#include "mtr0mtr.h" +#include "buf0flu.h" +#include "buf0lru.h" +#include "buf0rea.h" +#include "fsp0types.h" + +/** A chunk of buffers. The buffer pool is allocated in chunks. */ +struct buf_chunk_t{ + ulint size; /*!< size of frames[] and blocks[] */ + unsigned char* mem; /*!< pointer to the memory area which + was allocated for the frames */ + ut_new_pfx_t mem_pfx; /*!< Auxiliary structure, describing + "mem". It is filled by the allocator's + alloc method and later passed to the + deallocate method. */ + buf_block_t* blocks; /*!< array of buffer control blocks */ + + /** Get the size of 'mem' in bytes. */ + size_t mem_size() const { + return(mem_pfx.m_size); + } +}; + +bool buf_pool_t::is_block_field(const void *ptr) const +{ + const buf_chunk_t* chunk= chunks; + const buf_chunk_t *const echunk= chunk + ut_min(n_chunks, + n_chunks_new); + /* TODO: protect chunks with a mutex (the older pointer will + currently remain during resize()) */ + while (chunk < echunk) + { + if (ptr >= reinterpret_cast(chunk->blocks) && + ptr < reinterpret_cast( + chunk->blocks + chunk->size)) + return true; + chunk++; + } + + return false; +} + +/*********************************************************************//** +Gets the current size of buffer buf_pool in bytes. +@return size in bytes */ +UNIV_INLINE +ulint +buf_pool_get_curr_size(void) +/*========================*/ +{ + return(srv_buf_pool_curr_size); +} + +/********************************************************************//** +Calculates the index of a buffer pool to the buf_pool[] array. +@return the position of the buffer pool in buf_pool[] */ +UNIV_INLINE +unsigned +buf_pool_index( +/*===========*/ + const buf_pool_t* buf_pool) /*!< in: buffer pool */ +{ + unsigned i = unsigned(buf_pool - buf_pool_ptr); + ut_ad(i < MAX_BUFFER_POOLS); + ut_ad(i < srv_buf_pool_instances); + return(i); +} + +/******************************************************************//** +Returns the buffer pool instance given a page instance +@return buf_pool */ +UNIV_INLINE +buf_pool_t* +buf_pool_from_bpage( +/*================*/ + const buf_page_t* bpage) /*!< in: buffer pool page */ +{ + ut_ad(bpage->buf_pool_index < srv_buf_pool_instances); + return(&buf_pool_ptr[bpage->buf_pool_index]); +} + +/******************************************************************//** +Returns the buffer pool instance given a block instance +@return buf_pool */ +UNIV_INLINE +buf_pool_t* +buf_pool_from_block( +/*================*/ + const buf_block_t* block) /*!< in: block */ +{ + return(buf_pool_from_bpage(&block->page)); +} + +/*********************************************************************//** +Gets the current size of buffer buf_pool in pages. +@return size in pages*/ +UNIV_INLINE +ulint +buf_pool_get_n_pages(void) +/*======================*/ +{ + if (!buf_pool_ptr) + return buf_pool_get_curr_size() >> srv_page_size_shift; + + ulint chunk_size= 0; + for (uint i= 0; i < srv_buf_pool_instances; i++) + { + buf_pool_t* buf_pool = buf_pool_from_array(i); + for (uint j= 0; j < buf_pool->n_chunks; j++) + chunk_size+= buf_pool->chunks[j].size; + } + return chunk_size; +} + +/********************************************************************//** +Reads the freed_page_clock of a buffer block. +@return freed_page_clock */ +UNIV_INLINE +unsigned +buf_page_get_freed_page_clock( +/*==========================*/ + const buf_page_t* bpage) /*!< in: block */ +{ + /* This is sometimes read without holding buf_pool->mutex. */ + return(bpage->freed_page_clock); +} + +/********************************************************************//** +Reads the freed_page_clock of a buffer block. +@return freed_page_clock */ +UNIV_INLINE +unsigned +buf_block_get_freed_page_clock( +/*===========================*/ + const buf_block_t* block) /*!< in: block */ +{ + return(buf_page_get_freed_page_clock(&block->page)); +} + +/********************************************************************//** +Tells if a block is still close enough to the MRU end of the LRU list +meaning that it is not in danger of getting evicted and also implying +that it has been accessed recently. +Note that this is for heuristics only and does not reserve buffer pool +mutex. +@return TRUE if block is close to MRU end of LRU */ +UNIV_INLINE +ibool +buf_page_peek_if_young( +/*===================*/ + const buf_page_t* bpage) /*!< in: block */ +{ + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + + /* FIXME: bpage->freed_page_clock is 31 bits */ + return((buf_pool->freed_page_clock & ((1UL << 31) - 1)) + < (bpage->freed_page_clock + + (buf_pool->curr_size + * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio) + / (BUF_LRU_OLD_RATIO_DIV * 4)))); +} + +/********************************************************************//** +Recommends a move of a block to the start of the LRU list if there is danger +of dropping from the buffer pool. NOTE: does not reserve the buffer pool +mutex. +@return TRUE if should be made younger */ +UNIV_INLINE +ibool +buf_page_peek_if_too_old( +/*=====================*/ + const buf_page_t* bpage) /*!< in: block to make younger */ +{ + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + + if (buf_pool->freed_page_clock == 0) { + /* If eviction has not started yet, do not update the + statistics or move blocks in the LRU list. This is + either the warm-up phase or an in-memory workload. */ + return(FALSE); + } else if (buf_LRU_old_threshold_ms && bpage->old) { + unsigned access_time = buf_page_is_accessed(bpage); + + /* It is possible that the below comparison returns an + unexpected result. 2^32 milliseconds pass in about 50 days, + so if the difference between ut_time_ms() and access_time + is e.g. 50 days + 15 ms, then the below will behave as if + it is 15 ms. This is known and fixing it would require to + increase buf_page_t::access_time from 32 to 64 bits. */ + if (access_time > 0 + && ((ib_uint32_t) (ut_time_ms() - access_time)) + >= buf_LRU_old_threshold_ms) { + return(TRUE); + } + + buf_pool->stat.n_pages_not_made_young++; + return(FALSE); + } else { + return(!buf_page_peek_if_young(bpage)); + } +} + +/*********************************************************************//** +Gets the state of a block. +@return state */ +UNIV_INLINE +enum buf_page_state +buf_page_get_state( +/*===============*/ + const buf_page_t* bpage) /*!< in: pointer to the control block */ +{ + enum buf_page_state state = bpage->state; + +#ifdef UNIV_DEBUG + switch (state) { + case BUF_BLOCK_POOL_WATCH: + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_FILE_PAGE: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + break; + default: + ut_error; + } +#endif /* UNIV_DEBUG */ + + return(state); +} +/*********************************************************************//** +Gets the state of a block. +@return state */ +UNIV_INLINE +enum buf_page_state +buf_block_get_state( +/*================*/ + const buf_block_t* block) /*!< in: pointer to the control block */ +{ + return(buf_page_get_state(&block->page)); +} + +/*********************************************************************//** +Gets the state name for state of a block +@return name or "CORRUPTED" */ +UNIV_INLINE +const char* +buf_get_state_name( +/*===============*/ + const buf_block_t* block) /*!< in: pointer to the control + block */ +{ + enum buf_page_state state = buf_page_get_state(&block->page); + + switch (state) { + case BUF_BLOCK_POOL_WATCH: + return (const char *) "BUF_BLOCK_POOL_WATCH"; + case BUF_BLOCK_ZIP_PAGE: + return (const char *) "BUF_BLOCK_ZIP_PAGE"; + case BUF_BLOCK_ZIP_DIRTY: + return (const char *) "BUF_BLOCK_ZIP_DIRTY"; + case BUF_BLOCK_NOT_USED: + return (const char *) "BUF_BLOCK_NOT_USED"; + case BUF_BLOCK_READY_FOR_USE: + return (const char *) "BUF_BLOCK_NOT_USED"; + case BUF_BLOCK_FILE_PAGE: + return (const char *) "BUF_BLOCK_FILE_PAGE"; + case BUF_BLOCK_MEMORY: + return (const char *) "BUF_BLOCK_MEMORY"; + case BUF_BLOCK_REMOVE_HASH: + return (const char *) "BUF_BLOCK_REMOVE_HASH"; + default: + return (const char *) "CORRUPTED"; + } +} + +/*********************************************************************//** +Sets the state of a block. */ +UNIV_INLINE +void +buf_page_set_state( +/*===============*/ + buf_page_t* bpage, /*!< in/out: pointer to control block */ + enum buf_page_state state) /*!< in: state */ +{ +#ifdef UNIV_DEBUG + enum buf_page_state old_state = buf_page_get_state(bpage); + + switch (old_state) { + case BUF_BLOCK_POOL_WATCH: + ut_error; + break; + case BUF_BLOCK_ZIP_PAGE: + ut_a(state == BUF_BLOCK_ZIP_DIRTY); + break; + case BUF_BLOCK_ZIP_DIRTY: + ut_a(state == BUF_BLOCK_ZIP_PAGE); + break; + case BUF_BLOCK_NOT_USED: + ut_a(state == BUF_BLOCK_READY_FOR_USE); + break; + case BUF_BLOCK_READY_FOR_USE: + ut_a(state == BUF_BLOCK_MEMORY + || state == BUF_BLOCK_FILE_PAGE + || state == BUF_BLOCK_NOT_USED); + break; + case BUF_BLOCK_MEMORY: + ut_a(state == BUF_BLOCK_NOT_USED); + break; + case BUF_BLOCK_FILE_PAGE: + if (!(state == BUF_BLOCK_NOT_USED + || state == BUF_BLOCK_REMOVE_HASH + || state == BUF_BLOCK_FILE_PAGE)) { + const char *old_state_name = buf_get_state_name((buf_block_t*)bpage); + bpage->state = state; + + fprintf(stderr, + "InnoDB: Error: block old state %d (%s) " + " new state %d (%s) not correct\n", + old_state, + old_state_name, + state, + buf_get_state_name((buf_block_t*)bpage)); + ut_a(state == BUF_BLOCK_NOT_USED + || state == BUF_BLOCK_REMOVE_HASH + || state == BUF_BLOCK_FILE_PAGE); + } + + break; + case BUF_BLOCK_REMOVE_HASH: + ut_a(state == BUF_BLOCK_MEMORY); + break; + } +#endif /* UNIV_DEBUG */ + bpage->state = state; +} + +/*********************************************************************//** +Sets the state of a block. */ +UNIV_INLINE +void +buf_block_set_state( +/*================*/ + buf_block_t* block, /*!< in/out: pointer to control block */ + enum buf_page_state state) /*!< in: state */ +{ + buf_page_set_state(&block->page, state); +} + +/*********************************************************************//** +Determines if a block is mapped to a tablespace. +@return TRUE if mapped */ +UNIV_INLINE +ibool +buf_page_in_file( +/*=============*/ + const buf_page_t* bpage) /*!< in: pointer to control block */ +{ + switch (buf_page_get_state(bpage)) { + case BUF_BLOCK_POOL_WATCH: + ut_error; + break; + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + case BUF_BLOCK_FILE_PAGE: + return(TRUE); + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + break; + } + + return(FALSE); +} + +/*********************************************************************//** +Determines if a block should be on unzip_LRU list. +@return TRUE if block belongs to unzip_LRU */ +UNIV_INLINE +ibool +buf_page_belongs_to_unzip_LRU( +/*==========================*/ + const buf_page_t* bpage) /*!< in: pointer to control block */ +{ + ut_ad(buf_page_in_file(bpage)); + + return(bpage->zip.data + && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); +} + +/*********************************************************************//** +Gets the mutex of a block. +@return pointer to mutex protecting bpage */ +UNIV_INLINE +BPageMutex* +buf_page_get_mutex( +/*===============*/ + const buf_page_t* bpage) /*!< in: pointer to control block */ +{ + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + + switch (buf_page_get_state(bpage)) { + case BUF_BLOCK_POOL_WATCH: + ut_error; + return(NULL); + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + return(&buf_pool->zip_mutex); + default: + return(&((buf_block_t*) bpage)->mutex); + } +} + +/*********************************************************************//** +Get the flush type of a page. +@return flush type */ +UNIV_INLINE +buf_flush_t +buf_page_get_flush_type( +/*====================*/ + const buf_page_t* bpage) /*!< in: buffer page */ +{ + buf_flush_t flush_type = (buf_flush_t) bpage->flush_type; + +#ifdef UNIV_DEBUG + switch (flush_type) { + case BUF_FLUSH_LRU: + case BUF_FLUSH_LIST: + case BUF_FLUSH_SINGLE_PAGE: + return(flush_type); + case BUF_FLUSH_N_TYPES: + ut_error; + } + ut_error; +#endif /* UNIV_DEBUG */ + return(flush_type); +} +/*********************************************************************//** +Set the flush type of a page. */ +UNIV_INLINE +void +buf_page_set_flush_type( +/*====================*/ + buf_page_t* bpage, /*!< in: buffer page */ + buf_flush_t flush_type) /*!< in: flush type */ +{ + bpage->flush_type = flush_type; + ut_ad(buf_page_get_flush_type(bpage) == flush_type); +} + +/** Map a block to a file page. +@param[in,out] block pointer to control block +@param[in] page_id page id */ +UNIV_INLINE +void +buf_block_set_file_page( + buf_block_t* block, + const page_id_t page_id) +{ + buf_block_set_state(block, BUF_BLOCK_FILE_PAGE); + block->page.id = page_id; +} + +/*********************************************************************//** +Gets the io_fix state of a block. +@return io_fix state */ +UNIV_INLINE +enum buf_io_fix +buf_page_get_io_fix( +/*================*/ + const buf_page_t* bpage) /*!< in: pointer to the control block */ +{ + ut_ad(bpage != NULL); + + enum buf_io_fix io_fix = bpage->io_fix; + +#ifdef UNIV_DEBUG + switch (io_fix) { + case BUF_IO_NONE: + case BUF_IO_READ: + case BUF_IO_WRITE: + case BUF_IO_PIN: + return(io_fix); + } + ut_error; +#endif /* UNIV_DEBUG */ + return(io_fix); +} + +/*********************************************************************//** +Gets the io_fix state of a block. +@return io_fix state */ +UNIV_INLINE +enum buf_io_fix +buf_block_get_io_fix( +/*=================*/ + const buf_block_t* block) /*!< in: pointer to the control block */ +{ + return(buf_page_get_io_fix(&block->page)); +} + +/*********************************************************************//** +Sets the io_fix state of a block. */ +UNIV_INLINE +void +buf_page_set_io_fix( +/*================*/ + buf_page_t* bpage, /*!< in/out: control block */ + enum buf_io_fix io_fix) /*!< in: io_fix state */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(buf_pool_mutex_own(buf_pool)); +#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(buf_page_get_mutex(bpage))); + + bpage->io_fix = io_fix; + ut_ad(buf_page_get_io_fix(bpage) == io_fix); +} + +/*********************************************************************//** +Sets the io_fix state of a block. */ +UNIV_INLINE +void +buf_block_set_io_fix( +/*=================*/ + buf_block_t* block, /*!< in/out: control block */ + enum buf_io_fix io_fix) /*!< in: io_fix state */ +{ + buf_page_set_io_fix(&block->page, io_fix); +} + +/*********************************************************************//** +Makes a block sticky. A sticky block implies that even after we release +the buf_pool->mutex and the block->mutex: +* it cannot be removed from the flush_list +* the block descriptor cannot be relocated +* it cannot be removed from the LRU list +Note that: +* the block can still change its position in the LRU list +* the next and previous pointers can change. */ +UNIV_INLINE +void +buf_page_set_sticky( +/*================*/ + buf_page_t* bpage) /*!< in/out: control block */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(buf_pool_mutex_own(buf_pool)); +#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(buf_page_get_mutex(bpage))); + ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE); + + bpage->io_fix = BUF_IO_PIN; +} + +/*********************************************************************//** +Removes stickiness of a block. */ +UNIV_INLINE +void +buf_page_unset_sticky( +/*==================*/ + buf_page_t* bpage) /*!< in/out: control block */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(buf_pool_mutex_own(buf_pool)); +#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(buf_page_get_mutex(bpage))); + ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN); + + bpage->io_fix = BUF_IO_NONE; +} + +/********************************************************************//** +Determine if a buffer block can be relocated in memory. The block +can be dirty, but it must not be I/O-fixed or bufferfixed. */ +UNIV_INLINE +ibool +buf_page_can_relocate( +/*==================*/ + const buf_page_t* bpage) /*!< control block being relocated */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(buf_pool_mutex_own(buf_pool)); +#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(buf_page_get_mutex(bpage))); + ut_ad(buf_page_in_file(bpage)); + ut_ad(bpage->in_LRU_list); + + return(buf_page_get_io_fix(bpage) == BUF_IO_NONE + && bpage->buf_fix_count == 0); +} + +/*********************************************************************//** +Determine if a block has been flagged old. +@return TRUE if old */ +UNIV_INLINE +ibool +buf_page_is_old( +/*============*/ + const buf_page_t* bpage) /*!< in: control block */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(buf_pool_mutex_own(buf_pool)); +#endif /* UNIV_DEBUG */ + ut_ad(buf_page_in_file(bpage)); + + return(bpage->old); +} + +/*********************************************************************//** +Flag a block old. */ +UNIV_INLINE +void +buf_page_set_old( +/*=============*/ + buf_page_t* bpage, /*!< in/out: control block */ + bool old) /*!< in: old */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); +#endif /* UNIV_DEBUG */ + ut_a(buf_page_in_file(bpage)); + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(bpage->in_LRU_list); + +#ifdef UNIV_LRU_DEBUG + ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL)); + /* If a block is flagged "old", the LRU_old list must exist. */ + ut_a(!old || buf_pool->LRU_old); + + if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) { + const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); + const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage); + if (prev->old == next->old) { + ut_a(prev->old == old); + } else { + ut_a(!prev->old); + ut_a(buf_pool->LRU_old == (old ? bpage : next)); + } + } +#endif /* UNIV_LRU_DEBUG */ + + bpage->old = old; +} + +/*********************************************************************//** +Determine the time of first access of a block in the buffer pool. +@return ut_time_ms() at the time of first access, 0 if not accessed */ +UNIV_INLINE +unsigned +buf_page_is_accessed( +/*=================*/ + const buf_page_t* bpage) /*!< in: control block */ +{ + ut_ad(buf_page_in_file(bpage)); + + return(bpage->access_time); +} + +/*********************************************************************//** +Flag a block accessed. */ +UNIV_INLINE +void +buf_page_set_accessed( +/*==================*/ + buf_page_t* bpage) /*!< in/out: control block */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(!buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(buf_page_get_mutex(bpage))); +#endif /* UNIV_DEBUG */ + + ut_a(buf_page_in_file(bpage)); + + if (bpage->access_time == 0) { + /* Make this the time of the first access. */ + bpage->access_time = static_cast(ut_time_ms()); + } +} + +/*********************************************************************//** +Gets the buf_block_t handle of a buffered file block if an uncompressed +page frame exists, or NULL. +@return control block, or NULL */ +UNIV_INLINE +buf_block_t* +buf_page_get_block( +/*===============*/ + buf_page_t* bpage) /*!< in: control block, or NULL */ +{ + if (bpage != NULL) { + ut_ad(buf_page_in_file(bpage)); + + if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { + return((buf_block_t*) bpage); + } + } + + return(NULL); +} + +#ifdef UNIV_DEBUG +/*********************************************************************//** +Gets a pointer to the memory frame of a block. +@return pointer to the frame */ +UNIV_INLINE +buf_frame_t* +buf_block_get_frame( +/*================*/ + const buf_block_t* block) /*!< in: pointer to the control block */ +{ + if (!block) { + return NULL; + } + + switch (buf_block_get_state(block)) { + case BUF_BLOCK_POOL_WATCH: + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + case BUF_BLOCK_NOT_USED: + ut_error; + break; + case BUF_BLOCK_FILE_PAGE: + ut_a(block->page.buf_fix_count > 0); + /* fall through */ + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + goto ok; + } + ut_error; +ok: + return((buf_frame_t*) block->frame); +} +#endif /* UNIV_DEBUG */ + +/*********************************************************************** +FIXME_FTS Gets the frame the pointer is pointing to. */ +UNIV_INLINE +buf_frame_t* +buf_frame_align( +/*============*/ + /* out: pointer to frame */ + byte* ptr) /* in: pointer to a frame */ +{ + buf_frame_t* frame; + + ut_ad(ptr); + + frame = (buf_frame_t*) ut_align_down(ptr, UNIV_PAGE_SIZE); + + return(frame); +} + +/**********************************************************************//** +Gets the space id, page offset, and byte offset within page of a +pointer pointing to a buffer frame containing a file page. */ +UNIV_INLINE +void +buf_ptr_get_fsp_addr( +/*=================*/ + const void* ptr, /*!< in: pointer to a buffer frame */ + ulint* space, /*!< out: space id */ + fil_addr_t* addr) /*!< out: page offset and byte offset */ +{ + const page_t* page = (const page_t*) ut_align_down(ptr, + UNIV_PAGE_SIZE); + + *space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET); + addr->boffset = ut_align_offset(ptr, UNIV_PAGE_SIZE); +} + +/**********************************************************************//** +Gets the hash value of the page the pointer is pointing to. This can be used +in searches in the lock hash table. +@return lock hash value */ +UNIV_INLINE +unsigned +buf_block_get_lock_hash_val( +/*========================*/ + const buf_block_t* block) /*!< in: block */ +{ + ut_ad(block); + ut_ad(buf_page_in_file(&block->page)); + ut_ad(rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_X) + || rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_S)); + + return(block->lock_hash_val); +} + +/********************************************************************//** +Allocates a buf_page_t descriptor. This function must succeed. In case +of failure we assert in this function. +@return: the allocated descriptor. */ +UNIV_INLINE +buf_page_t* +buf_page_alloc_descriptor(void) +/*===========================*/ +{ + buf_page_t* bpage; + + bpage = (buf_page_t*) ut_zalloc_nokey(sizeof *bpage); + ut_ad(bpage); + MEM_UNDEFINED(bpage, sizeof *bpage); + + return(bpage); +} + +/********************************************************************//** +Free a buf_page_t descriptor. */ +UNIV_INLINE +void +buf_page_free_descriptor( +/*=====================*/ + buf_page_t* bpage) /*!< in: bpage descriptor to free. */ +{ + ut_free(bpage); +} + +/********************************************************************//** +Frees a buffer block which does not contain a file page. */ +UNIV_INLINE +void +buf_block_free( +/*===========*/ + buf_block_t* block) /*!< in, own: block to be freed */ +{ + buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); + + buf_pool_mutex_enter(buf_pool); + + buf_page_mutex_enter(block); + + ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE); + + buf_LRU_block_free_non_file_page(block); + + buf_page_mutex_exit(block); + + buf_pool_mutex_exit(buf_pool); +} + +/*********************************************************************//** +Copies contents of a buffer frame to a given buffer. +@return buf */ +UNIV_INLINE +byte* +buf_frame_copy( +/*===========*/ + byte* buf, /*!< in: buffer to copy to */ + const buf_frame_t* frame) /*!< in: buffer frame */ +{ + ut_ad(buf && frame); + + ut_memcpy(buf, frame, UNIV_PAGE_SIZE); + + return(buf); +} + +/********************************************************************//** +Gets the youngest modification log sequence number for a frame. +Returns zero if not file page or no modification occurred yet. +@return newest modification to page */ +UNIV_INLINE +lsn_t +buf_page_get_newest_modification( +/*=============================*/ + const buf_page_t* bpage) /*!< in: block containing the + page frame */ +{ + lsn_t lsn; + BPageMutex* block_mutex = buf_page_get_mutex(bpage); + + mutex_enter(block_mutex); + + if (buf_page_in_file(bpage)) { + lsn = bpage->newest_modification; + } else { + lsn = 0; + } + + mutex_exit(block_mutex); + + return(lsn); +} + +/********************************************************************//** +Increments the modify clock of a frame by 1. The caller must (1) own the +buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock +on the block. */ +UNIV_INLINE +void +buf_block_modify_clock_inc( +/*=======================*/ + buf_block_t* block) /*!< in: block */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); + + /* No latch is acquired for the shared temporary tablespace. */ + if (!fsp_is_system_temporary(block->page.id.space())) { + ut_ad((buf_pool_mutex_own(buf_pool) + && (block->page.buf_fix_count == 0)) + || rw_lock_own_flagged(&block->lock, + RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); + } +#endif /* UNIV_DEBUG */ + assert_block_ahi_valid(block); + + block->modify_clock++; +} + +/********************************************************************//** +Returns the value of the modify clock. The caller must have an s-lock +or x-lock on the block. +@return value */ +UNIV_INLINE +ib_uint64_t +buf_block_get_modify_clock( +/*=======================*/ + buf_block_t* block) /*!< in: block */ +{ +#ifdef UNIV_DEBUG + /* No latch is acquired for the shared temporary tablespace. */ + if (!fsp_is_system_temporary(block->page.id.space())) { + ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S) + || rw_lock_own(&(block->lock), RW_LOCK_X) + || rw_lock_own(&(block->lock), RW_LOCK_SX)); + } +#endif /* UNIV_DEBUG */ + + 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 +void +buf_block_buf_fix_inc_func( +/*=======================*/ +#ifdef UNIV_DEBUG + const char* file, /*!< in: file name */ + unsigned line, /*!< in: line */ +#endif /* UNIV_DEBUG */ + buf_block_t* block) /*!< in/out: block to bufferfix */ +{ +#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())) { + ibool ret; + 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); +} + +/*******************************************************************//** +Decrements the bufferfix count. */ +UNIV_INLINE +void +buf_block_buf_fix_dec( +/*==================*/ + buf_block_t* block) /*!< in/out: block to bufferunfix */ +{ +#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); + } +#endif /* UNIV_DEBUG */ + + buf_block_unfix(block); +} + +/** Returns the buffer pool instance given a page id. +@param[in] page_id page id +@return buffer pool */ +inline buf_pool_t* buf_pool_get(const page_id_t page_id) +{ + /* 2log of BUF_READ_AHEAD_AREA (64) */ + ulint ignored_page_no = page_id.page_no() >> 6; + + page_id_t id(page_id.space(), ignored_page_no); + + ulint i = id.fold() % srv_buf_pool_instances; + + return(&buf_pool_ptr[i]); +} + +/******************************************************************//** +Returns the buffer pool instance given its array index +@return buffer pool */ +UNIV_INLINE +buf_pool_t* +buf_pool_from_array( +/*================*/ + ulint index) /*!< in: array index to get + buffer pool instance from */ +{ + ut_ad(index < MAX_BUFFER_POOLS); + ut_ad(index < srv_buf_pool_instances); + return(&buf_pool_ptr[index]); +} + +/** Returns the control block of a file page, NULL if not found. +@param[in] buf_pool buffer pool instance +@param[in] page_id page id +@return block, NULL if not found */ +UNIV_INLINE +buf_page_t* +buf_page_hash_get_low( + buf_pool_t* buf_pool, + const page_id_t page_id) +{ + buf_page_t* bpage; + +#ifdef UNIV_DEBUG + rw_lock_t* hash_lock; + + hash_lock = hash_get_lock(buf_pool->page_hash, page_id.fold()); + ut_ad(rw_lock_own(hash_lock, RW_LOCK_X) + || rw_lock_own(hash_lock, RW_LOCK_S)); +#endif /* UNIV_DEBUG */ + + /* Look for the page in the hash table */ + + HASH_SEARCH(hash, buf_pool->page_hash, page_id.fold(), buf_page_t*, + bpage, + ut_ad(bpage->in_page_hash && !bpage->in_zip_hash + && buf_page_in_file(bpage)), + page_id == bpage->id); + if (bpage) { + ut_a(buf_page_in_file(bpage)); + ut_ad(bpage->in_page_hash); + ut_ad(!bpage->in_zip_hash); + ut_ad(buf_pool_from_bpage(bpage) == buf_pool); + } + + return(bpage); +} + +/** Returns the control block of a file page, NULL if not found. +If the block is found and lock is not NULL then the appropriate +page_hash lock is acquired in the specified lock mode. Otherwise, +mode value is ignored. It is up to the caller to release the +lock. If the block is found and the lock is NULL then the page_hash +lock is released by this function. +@param[in] buf_pool buffer pool instance +@param[in] page_id page id +@param[in,out] lock lock of the page hash acquired if bpage is +found, NULL otherwise. If NULL is passed then the hash_lock is released by +this function. +@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if +lock == NULL +@param[in] watch if true, return watch sentinel also. +@return pointer to the bpage or NULL; if NULL, lock is also NULL or +a watch sentinel. */ +UNIV_INLINE +buf_page_t* +buf_page_hash_get_locked( + buf_pool_t* buf_pool, + const page_id_t page_id, + rw_lock_t** lock, + ulint lock_mode, + bool watch) +{ + buf_page_t* bpage = NULL; + rw_lock_t* hash_lock; + ulint mode = RW_LOCK_S; + + if (lock != NULL) { + *lock = NULL; + ut_ad(lock_mode == RW_LOCK_X + || lock_mode == RW_LOCK_S); + mode = lock_mode; + } + + hash_lock = hash_get_lock(buf_pool->page_hash, page_id.fold()); + + ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X) + && !rw_lock_own(hash_lock, RW_LOCK_S)); + + if (mode == RW_LOCK_S) { + rw_lock_s_lock(hash_lock); + + /* If not own buf_pool_mutex, page_hash can be changed. */ + hash_lock = hash_lock_s_confirm( + hash_lock, buf_pool->page_hash, page_id.fold()); + } else { + rw_lock_x_lock(hash_lock); + /* If not own buf_pool_mutex, page_hash can be changed. */ + hash_lock = hash_lock_x_confirm( + hash_lock, buf_pool->page_hash, page_id.fold()); + } + + bpage = buf_page_hash_get_low(buf_pool, page_id); + + if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) { + if (!watch) { + bpage = NULL; + } + goto unlock_and_exit; + } + + ut_ad(buf_page_in_file(bpage)); + ut_ad(page_id == bpage->id); + + if (lock == NULL) { + /* The caller wants us to release the page_hash lock */ + goto unlock_and_exit; + } else { + /* To be released by the caller */ + *lock = hash_lock; + goto exit; + } + +unlock_and_exit: + if (mode == RW_LOCK_S) { + rw_lock_s_unlock(hash_lock); + } else { + rw_lock_x_unlock(hash_lock); + } +exit: + return(bpage); +} + +/** Returns the control block of a file page, NULL if not found. +If the block is found and lock is not NULL then the appropriate +page_hash lock is acquired in the specified lock mode. Otherwise, +mode value is ignored. It is up to the caller to release the +lock. If the block is found and the lock is NULL then the page_hash +lock is released by this function. +@param[in] buf_pool buffer pool instance +@param[in] page_id page id +@param[in,out] lock lock of the page hash acquired if bpage is +found, NULL otherwise. If NULL is passed then the hash_lock is released by +this function. +@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if +lock == NULL +@return pointer to the block or NULL; if NULL, lock is also NULL. */ +UNIV_INLINE +buf_block_t* +buf_block_hash_get_locked( + buf_pool_t* buf_pool, + const page_id_t page_id, + rw_lock_t** lock, + ulint lock_mode) +{ + buf_page_t* bpage = buf_page_hash_get_locked(buf_pool, + page_id, + lock, + lock_mode); + buf_block_t* block = buf_page_get_block(bpage); + + if (block != NULL) { + + ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(!lock || rw_lock_own(*lock, lock_mode)); + + return(block); + } else if (bpage) { + /* It is not a block. Just a bpage */ + ut_ad(buf_page_in_file(bpage)); + + if (lock) { + if (lock_mode == RW_LOCK_S) { + rw_lock_s_unlock(*lock); + } else { + rw_lock_x_unlock(*lock); + } + } + *lock = NULL; + return(NULL); + } + + ut_ad(!bpage); + ut_ad(lock == NULL ||*lock == NULL); + return(NULL); +} + +/** Returns TRUE if the page can be found in the buffer pool hash table. +NOTE that it is possible that the page is not yet read from disk, +though. +@param[in] page_id page id +@return true if found in the page hash table */ +inline bool buf_page_peek(const page_id_t page_id) +{ + buf_pool_t* buf_pool = buf_pool_get(page_id); + + return(buf_page_hash_get(buf_pool, page_id) != NULL); +} + +/********************************************************************//** +Releases a compressed-only page acquired with buf_page_get_zip(). */ +UNIV_INLINE +void +buf_page_release_zip( +/*=================*/ + buf_page_t* bpage) /*!< in: buffer block */ +{ + ut_ad(bpage); + ut_a(bpage->buf_fix_count > 0); + + switch (buf_page_get_state(bpage)) { + case BUF_BLOCK_FILE_PAGE: +#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. */ + buf_block_t* block = reinterpret_cast(bpage); + if (!fsp_is_system_temporary(block->page.id.space())) { + 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(bpage)); + return; + + case BUF_BLOCK_POOL_WATCH: + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + break; + } + + ut_error; +} + +/********************************************************************//** +Releases a latch, if specified. */ +UNIV_INLINE +void +buf_page_release_latch( +/*===================*/ + buf_block_t* block, /*!< in: buffer block */ + ulint rw_latch) /*!< in: RW_S_LATCH, RW_X_LATCH, + RW_NO_LATCH */ +{ +#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); + } +#endif /* UNIV_DEBUG */ + + if (rw_latch == RW_S_LATCH) { + rw_lock_s_unlock(&block->lock); + } else if (rw_latch == RW_SX_LATCH) { + rw_lock_sx_unlock(&block->lock); + } else if (rw_latch == RW_X_LATCH) { + rw_lock_x_unlock(&block->lock); + } +} + +#ifdef UNIV_DEBUG +/*********************************************************************//** +Adds latch level info for the rw-lock protecting the buffer frame. This +should be called in the debug version after a successful latching of a +page if we know the latching order level of the acquired latch. */ +UNIV_INLINE +void +buf_block_dbg_add_level( +/*====================*/ + buf_block_t* block, /*!< in: buffer page + where we have acquired latch */ + latch_level_t level) /*!< in: latching order level */ +{ + sync_check_lock(&block->lock, level); +} + +#endif /* UNIV_DEBUG */ +/********************************************************************//** +Acquire mutex on all buffer pool instances. */ +UNIV_INLINE +void +buf_pool_mutex_enter_all(void) +/*==========================*/ +{ + for (ulint i = 0; i < srv_buf_pool_instances; ++i) { + buf_pool_t* buf_pool = buf_pool_from_array(i); + + buf_pool_mutex_enter(buf_pool); + } +} + +/********************************************************************//** +Release mutex on all buffer pool instances. */ +UNIV_INLINE +void +buf_pool_mutex_exit_all(void) +/*=========================*/ +{ + ulint i; + + for (i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool; + + buf_pool = buf_pool_from_array(i); + buf_pool_mutex_exit(buf_pool); + } +} +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size) /*!< in: chunk size */ +{ + const buf_chunk_t* chunk; + + chunk = buf_pool->chunks + n; + *chunk_size = chunk->size; + return(chunk->blocks); +} + +/********************************************************************//** +Get buf frame. */ +UNIV_INLINE +void * +buf_page_get_frame( +/*===============*/ + const buf_page_t* bpage) /*!< in: buffer pool page */ +{ + /* In encryption/compression buffer pool page may contain extra + buffer where result is stored. */ + if (bpage->slot && bpage->slot->out_buf) { + return bpage->slot->out_buf; + } else if (bpage->zip.data) { + return bpage->zip.data; + } else { + return ((buf_block_t*) bpage)->frame; + } +} + +/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit, +if needed. +@param[in] size size in bytes +@return aligned size */ +UNIV_INLINE +ulint +buf_pool_size_align( + ulint size) +{ + const ib_uint64_t m = ((ib_uint64_t)srv_buf_pool_instances) * srv_buf_pool_chunk_unit; + size = ut_max(size, srv_buf_pool_min_size); + + if (size % m == 0) { + return(size); + } else { + return (ulint)((size / m + 1) * m); + } +} diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index c7f5d410099..393d209a6b1 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -453,6 +453,6 @@ buf_flush_batch( counts */ -#include "buf0flu.ic" +#include "buf0flu.inl" #endif diff --git a/storage/innobase/include/buf0flu.ic b/storage/innobase/include/buf0flu.ic deleted file mode 100644 index 8d06a53c547..00000000000 --- a/storage/innobase/include/buf0flu.ic +++ /dev/null @@ -1,149 +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/buf0flu.ic -The database buffer pool flush algorithm - -Created 11/5/1995 Heikki Tuuri -*******************************************************/ - -#include "buf0buf.h" -#include "mtr0mtr.h" -#include "srv0srv.h" -#include "fsp0types.h" - -/********************************************************************//** -Inserts a modified block into the flush list. */ -void -buf_flush_insert_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 */ - -/********************************************************************//** -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. */ -UNIV_INLINE -void -buf_flush_note_modification( -/*========================*/ - buf_block_t* block, /*!< in: block which is modified */ - lsn_t start_lsn, /*!< in: start lsn of the mtr that - modified this block */ - lsn_t end_lsn, /*!< in: end lsn of the mtr that - 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(block->page.newest_modification <= end_lsn); - block->page.newest_modification = end_lsn; - - /* Don't allow to set flush observer from non-null to null, - or from one observer to another. */ - ut_ad(block->page.flush_observer == NULL - || block->page.flush_observer == observer); - block->page.flush_observer = observer; - - if (block->page.oldest_modification == 0) { - buf_pool_t* buf_pool = buf_pool_from_block(block); - - buf_flush_insert_into_flush_list(buf_pool, block, start_lsn); - } else { - ut_ad(block->page.oldest_modification <= start_lsn); - } - - buf_page_mutex_exit(block); - - 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/buf0flu.inl b/storage/innobase/include/buf0flu.inl new file mode 100644 index 00000000000..8d06a53c547 --- /dev/null +++ b/storage/innobase/include/buf0flu.inl @@ -0,0 +1,149 @@ +/***************************************************************************** + +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/buf0flu.ic +The database buffer pool flush algorithm + +Created 11/5/1995 Heikki Tuuri +*******************************************************/ + +#include "buf0buf.h" +#include "mtr0mtr.h" +#include "srv0srv.h" +#include "fsp0types.h" + +/********************************************************************//** +Inserts a modified block into the flush list. */ +void +buf_flush_insert_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 */ + +/********************************************************************//** +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. */ +UNIV_INLINE +void +buf_flush_note_modification( +/*========================*/ + buf_block_t* block, /*!< in: block which is modified */ + lsn_t start_lsn, /*!< in: start lsn of the mtr that + modified this block */ + lsn_t end_lsn, /*!< in: end lsn of the mtr that + 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(block->page.newest_modification <= end_lsn); + block->page.newest_modification = end_lsn; + + /* Don't allow to set flush observer from non-null to null, + or from one observer to another. */ + ut_ad(block->page.flush_observer == NULL + || block->page.flush_observer == observer); + block->page.flush_observer = observer; + + if (block->page.oldest_modification == 0) { + buf_pool_t* buf_pool = buf_pool_from_block(block); + + buf_flush_insert_into_flush_list(buf_pool, block, start_lsn); + } else { + ut_ad(block->page.oldest_modification <= start_lsn); + } + + buf_page_mutex_exit(block); + + 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/data0data.h b/storage/innobase/include/data0data.h index fdf1a14feee..68033079268 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -637,6 +637,6 @@ struct big_rec_t { ulint n_fld); }; -#include "data0data.ic" +#include "data0data.inl" #endif diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic deleted file mode 100644 index 9b7a3132873..00000000000 --- a/storage/innobase/include/data0data.ic +++ /dev/null @@ -1,634 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. -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 -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/data0data.ic -SQL data field and tuple - -Created 5/30/1994 Heikki Tuuri -*************************************************************************/ - -#include "ut0rnd.h" - -/*********************************************************************//** -Sets the type struct of SQL data field. */ -UNIV_INLINE -void -dfield_set_type( -/*============*/ - dfield_t* field, /*!< in: SQL data field */ - const dtype_t* type) /*!< in: pointer to data type struct */ -{ - ut_ad(field != NULL); - ut_ad(type != NULL); - - field->type = *type; -} - -/*********************************************************************//** -Sets length in a field. */ -UNIV_INLINE -void -dfield_set_len( -/*===========*/ - dfield_t* field, /*!< in: field */ - ulint len) /*!< in: length or UNIV_SQL_NULL */ -{ - field->ext = 0; - field->len = static_cast(len); -} - -/** Gets spatial status for "external storage" -@param[in,out] field field */ -UNIV_INLINE -spatial_status_t -dfield_get_spatial_status( - const dfield_t* field) -{ - ut_ad(field); - ut_ad(dfield_is_ext(field)); - - return(static_cast(field->spatial_status)); -} - -/** Sets spatial status for "external storage" -@param[in,out] field field -@param[in] spatial_status spatial status */ -UNIV_INLINE -void -dfield_set_spatial_status( - dfield_t* field, - spatial_status_t spatial_status) -{ - ut_ad(field); - ut_ad(dfield_is_ext(field)); - - field->spatial_status = spatial_status; -} - -/*********************************************************************//** -Sets pointer to the data and length in a field. */ -UNIV_INLINE -void -dfield_set_data( -/*============*/ - dfield_t* field, /*!< in: field */ - const void* data, /*!< in: data */ - ulint len) /*!< in: length or UNIV_SQL_NULL */ -{ - field->data = (void*) data; - field->ext = 0; - field->len = static_cast(len); -} - -/*********************************************************************//** -Sets pointer to the data and length in a field. */ -UNIV_INLINE -void -dfield_write_mbr( -/*=============*/ - dfield_t* field, /*!< in: field */ - const double* mbr) /*!< in: data */ -{ - MEM_CHECK_DEFINED(mbr, sizeof *mbr); - field->ext = 0; - - for (unsigned i = 0; i < SPDIMS * 2; i++) { - mach_double_write(static_cast(field->data) - + i * sizeof(double), mbr[i]); - } - - field->len = DATA_MBR_LEN; -} - -/*********************************************************************//** -Sets a data field to SQL NULL. */ -UNIV_INLINE -void -dfield_set_null( -/*============*/ - dfield_t* field) /*!< in/out: field */ -{ - dfield_set_data(field, NULL, UNIV_SQL_NULL); -} - -/*********************************************************************//** -Copies the data and len fields. */ -UNIV_INLINE -void -dfield_copy_data( -/*=============*/ - dfield_t* field1, /*!< out: field to copy to */ - const dfield_t* field2) /*!< in: field to copy from */ -{ - ut_ad(field1 != NULL); - ut_ad(field2 != NULL); - - field1->data = field2->data; - field1->len = field2->len; - field1->ext = field2->ext; - field1->spatial_status = field2->spatial_status; -} - -/*********************************************************************//** -Copies a data field to another. */ -UNIV_INLINE -void -dfield_copy( -/*========*/ - dfield_t* field1, /*!< out: field to copy to */ - const dfield_t* field2) /*!< in: field to copy from */ -{ - *field1 = *field2; -} - -/*********************************************************************//** -Copies the data pointed to by a data field. */ -UNIV_INLINE -void -dfield_dup( -/*=======*/ - dfield_t* field, /*!< in/out: data field */ - mem_heap_t* heap) /*!< in: memory heap where allocated */ -{ - if (!dfield_is_null(field)) { - MEM_CHECK_DEFINED(field->data, field->len); - field->data = mem_heap_dup(heap, field->data, field->len); - } -} - -/*********************************************************************//** -Tests if two data fields are equal. -If len==0, tests the data length and content for equality. -If len>0, tests the first len bytes of the content for equality. -@return TRUE if both fields are NULL or if they are equal */ -UNIV_INLINE -ibool -dfield_datas_are_binary_equal( -/*==========================*/ - const dfield_t* field1, /*!< in: field */ - const dfield_t* field2, /*!< in: field */ - ulint len) /*!< in: maximum prefix to compare, - or 0 to compare the whole field length */ -{ - ulint len2 = len; - - if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) { - len = field1->len; - } - - if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) { - len2 = field2->len; - } - - return(len == len2 - && (len == UNIV_SQL_NULL - || !memcmp(field1->data, field2->data, len))); -} - -/*********************************************************************//** -Tests if dfield data length and content is equal to the given. -@return TRUE if equal */ -UNIV_INLINE -ibool -dfield_data_is_binary_equal( -/*========================*/ - const dfield_t* field, /*!< in: field */ - ulint len, /*!< in: data length or UNIV_SQL_NULL */ - const byte* data) /*!< in: data */ -{ - return(len == dfield_get_len(field) - && (!len || len == UNIV_SQL_NULL - || !memcmp(dfield_get_data(field), data, len))); -} - -/*********************************************************************//** -Gets info bits in a data tuple. -@return info bits */ -UNIV_INLINE -ulint -dtuple_get_info_bits( -/*=================*/ - const dtuple_t* tuple) /*!< in: tuple */ -{ - return(tuple->info_bits); -} - -/*********************************************************************//** -Sets info bits in a data tuple. */ -UNIV_INLINE -void -dtuple_set_info_bits( -/*=================*/ - dtuple_t* tuple, /*!< in: tuple */ - ulint info_bits) /*!< in: info bits */ -{ - tuple->info_bits = info_bits; -} - -/*********************************************************************//** -Gets number of fields used in record comparisons. -@return number of fields used in comparisons in rem0cmp.* */ -UNIV_INLINE -ulint -dtuple_get_n_fields_cmp( -/*====================*/ - const dtuple_t* tuple) /*!< in: tuple */ -{ - return(tuple->n_fields_cmp); -} - -/*********************************************************************//** -Sets number of fields used in record comparisons. */ -UNIV_INLINE -void -dtuple_set_n_fields_cmp( -/*====================*/ - dtuple_t* tuple, /*!< in: tuple */ - ulint n_fields_cmp) /*!< in: number of fields used in - comparisons in rem0cmp.* */ -{ - ut_ad(n_fields_cmp <= tuple->n_fields); - tuple->n_fields_cmp = n_fields_cmp; -} - -/** Creates a data tuple from an already allocated chunk of memory. -The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields). -The default value for number of fields used in record comparisons -for this tuple is n_fields. -@param[in,out] buf buffer to use -@param[in] buf_size buffer size -@param[in] n_fields number of field -@param[in] n_v_fields number of fields on virtual columns -@return created tuple (inside buf) */ -UNIV_INLINE -dtuple_t* -dtuple_create_from_mem( - void* buf, - ulint buf_size, - ulint n_fields, - ulint n_v_fields) -{ - dtuple_t* tuple; - ulint n_t_fields = n_fields + n_v_fields; - - ut_a(buf_size >= DTUPLE_EST_ALLOC(n_t_fields)); - - tuple = (dtuple_t*) buf; - tuple->info_bits = 0; - tuple->n_fields = n_fields; - tuple->n_v_fields = n_v_fields; - tuple->n_fields_cmp = n_fields; - tuple->fields = (dfield_t*) &tuple[1]; - if (n_v_fields > 0) { - tuple->v_fields = &tuple->fields[n_fields]; - } else { - tuple->v_fields = NULL; - } - -#ifdef UNIV_DEBUG - tuple->magic_n = DATA_TUPLE_MAGIC_N; - - { /* In the debug version, initialize fields to an error value */ - ulint i; - - for (i = 0; i < n_t_fields; i++) { - dfield_t* field; - - if (i >= n_fields) { - field = dtuple_get_nth_v_field( - tuple, i - n_fields); - } else { - field = dtuple_get_nth_field(tuple, i); - } - - dfield_set_len(field, UNIV_SQL_NULL); - field->data = &data_error; - dfield_get_type(field)->mtype = DATA_ERROR; - dfield_get_type(field)->prtype = DATA_ERROR; - } - } -#endif - MEM_CHECK_ADDRESSABLE(tuple->fields, n_t_fields - * sizeof *tuple->fields); - MEM_UNDEFINED(tuple->fields, n_t_fields * sizeof *tuple->fields); - return(tuple); -} - -/** Duplicate the virtual field data in a dtuple_t -@param[in,out] vrow dtuple contains the virtual fields -@param[in,out] heap heap memory to use */ -UNIV_INLINE -void -dtuple_dup_v_fld(dtuple_t* vrow, mem_heap_t* heap) -{ - for (ulint i = 0; i < vrow->n_v_fields; i++) { - dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); - dfield_dup(dfield, heap); - } -} - -/** Initialize the virtual field data in a dtuple_t -@param[in,out] vrow dtuple contains the virtual fields */ -UNIV_INLINE -void -dtuple_init_v_fld(dtuple_t* vrow) -{ - for (ulint i = 0; i < vrow->n_v_fields; i++) { - dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); - dfield_get_type(dfield)->mtype = DATA_MISSING; - dfield_set_len(dfield, UNIV_SQL_NULL); - } -} - -/**********************************************************//** -Creates a data tuple to a memory heap. The default value for number -of fields used in record comparisons for this tuple is n_fields. -@return own: created tuple */ -UNIV_INLINE -dtuple_t* -dtuple_create( -/*==========*/ - mem_heap_t* heap, /*!< in: memory heap where the tuple - is created, DTUPLE_EST_ALLOC(n_fields) - bytes will be allocated from this heap */ - ulint n_fields) /*!< in: number of fields */ -{ - return(dtuple_create_with_vcol(heap, n_fields, 0)); -} - -/** Creates a data tuple with virtual columns to a memory heap. -@param[in] heap memory heap where the tuple is created -@param[in] n_fields number of fields -@param[in] n_v_fields number of fields on virtual col -@return own: created tuple */ -UNIV_INLINE -dtuple_t* -dtuple_create_with_vcol( - mem_heap_t* heap, - ulint n_fields, - ulint n_v_fields) -{ - void* buf; - ulint buf_size; - dtuple_t* tuple; - - ut_ad(heap); - - buf_size = DTUPLE_EST_ALLOC(n_fields + n_v_fields); - buf = mem_heap_alloc(heap, buf_size); - - tuple = dtuple_create_from_mem(buf, buf_size, n_fields, n_v_fields); - - return(tuple); -} - -/** Copies a data tuple's virtual fields to another. This is a shallow copy; -@param[in,out] d_tuple destination tuple -@param[in] s_tuple source tuple */ -UNIV_INLINE -void -dtuple_copy_v_fields( - dtuple_t* d_tuple, - const dtuple_t* s_tuple) -{ - - ulint n_v_fields = dtuple_get_n_v_fields(d_tuple); - ut_ad(n_v_fields == dtuple_get_n_v_fields(s_tuple)); - - for (ulint i = 0; i < n_v_fields; i++) { - dfield_copy(dtuple_get_nth_v_field(d_tuple, i), - dtuple_get_nth_v_field(s_tuple, i)); - } -} - -/*********************************************************************//** -Copies a data tuple to another. This is a shallow copy; if a deep copy -is desired, dfield_dup() will have to be invoked on each field. -@return own: copy of tuple */ -UNIV_INLINE -dtuple_t* -dtuple_copy( -/*========*/ - const dtuple_t* tuple, /*!< in: tuple to copy from */ - mem_heap_t* heap) /*!< in: memory heap - where the tuple is created */ -{ - ulint n_fields = dtuple_get_n_fields(tuple); - ulint n_v_fields = dtuple_get_n_v_fields(tuple); - dtuple_t* new_tuple = dtuple_create_with_vcol( - heap, n_fields, n_v_fields); - ulint i; - - for (i = 0; i < n_fields; i++) { - dfield_copy(dtuple_get_nth_field(new_tuple, i), - dtuple_get_nth_field(tuple, i)); - } - - for (i = 0; i < n_v_fields; i++) { - dfield_copy(dtuple_get_nth_v_field(new_tuple, i), - dtuple_get_nth_v_field(tuple, i)); - } - - return(new_tuple); -} - -/**********************************************************//** -The following function returns the sum of data lengths of a tuple. The space -occupied by the field structs or the tuple struct is not counted. Neither -is possible space in externally stored parts of the field. -@return sum of data lengths */ -UNIV_INLINE -ulint -dtuple_get_data_size( -/*=================*/ - const dtuple_t* tuple, /*!< in: typed data tuple */ - ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ -{ - const dfield_t* field; - ulint n_fields; - ulint len; - ulint i; - ulint sum = 0; - - ut_ad(dtuple_check_typed(tuple)); - ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); - - n_fields = tuple->n_fields; - - for (i = 0; i < n_fields; i++) { - field = dtuple_get_nth_field(tuple, i); - len = dfield_get_len(field); - - if (len == UNIV_SQL_NULL) { - len = dtype_get_sql_null_size(dfield_get_type(field), - comp); - } - - sum += len; - } - - return(sum); -} - -/*********************************************************************//** -Computes the number of externally stored fields in a data tuple. -@return number of externally stored fields */ -UNIV_INLINE -ulint -dtuple_get_n_ext( -/*=============*/ - const dtuple_t* tuple) /*!< in: tuple */ -{ - ulint n_ext = 0; - ulint n_fields = tuple->n_fields; - ulint i; - - ut_ad(dtuple_check_typed(tuple)); - ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); - - for (i = 0; i < n_fields; i++) { - n_ext += dtuple_get_nth_field(tuple, i)->ext; - } - - return(n_ext); -} - -/*******************************************************************//** -Sets types of fields binary in a tuple. */ -UNIV_INLINE -void -dtuple_set_types_binary( -/*====================*/ - dtuple_t* tuple, /*!< in: data tuple */ - ulint n) /*!< in: number of fields to set */ -{ - dtype_t* dfield_type; - ulint i; - - for (i = 0; i < n; i++) { - dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i)); - dtype_set(dfield_type, DATA_BINARY, 0, 0); - } -} - -/** Fold a prefix given as the number of fields of a tuple. -@param[in] tuple index record -@param[in] n_fields number of complete fields to fold -@param[in] n_bytes number of bytes to fold in the last field -@param[in] index_id index tree ID -@return the folded value */ -UNIV_INLINE -ulint -dtuple_fold( - const dtuple_t* tuple, - ulint n_fields, - ulint n_bytes, - index_id_t tree_id) -{ - const dfield_t* field; - ulint i; - const byte* data; - ulint len; - ulint fold; - - ut_ad(tuple); - ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); - ut_ad(dtuple_check_typed(tuple)); - - fold = ut_fold_ull(tree_id); - - for (i = 0; i < n_fields; i++) { - field = dtuple_get_nth_field(tuple, i); - - data = (const byte*) dfield_get_data(field); - len = dfield_get_len(field); - - if (len != UNIV_SQL_NULL) { - fold = ut_fold_ulint_pair(fold, - ut_fold_binary(data, len)); - } - } - - if (n_bytes > 0) { - field = dtuple_get_nth_field(tuple, i); - - data = (const byte*) dfield_get_data(field); - len = dfield_get_len(field); - - if (len != UNIV_SQL_NULL) { - if (len > n_bytes) { - len = n_bytes; - } - - fold = ut_fold_ulint_pair(fold, - ut_fold_binary(data, len)); - } - } - - return(fold); -} - -/**********************************************************************//** -Writes an SQL null field full of zeros. */ -UNIV_INLINE -void -data_write_sql_null( -/*================*/ - byte* data, /*!< in: pointer to a buffer of size len */ - ulint len) /*!< in: SQL null size in bytes */ -{ - memset(data, 0, len); -} - -/**********************************************************************//** -Checks if a dtuple contains an SQL null value. -@return TRUE if some field is SQL null */ -UNIV_INLINE -ibool -dtuple_contains_null( -/*=================*/ - const dtuple_t* tuple) /*!< in: dtuple */ -{ - ulint n; - ulint i; - - n = dtuple_get_n_fields(tuple); - - for (i = 0; i < n; i++) { - if (dfield_is_null(dtuple_get_nth_field(tuple, i))) { - - return(TRUE); - } - } - - return(FALSE); -} - -/**************************************************************//** -Frees the memory in a big rec vector. */ -UNIV_INLINE -void -dtuple_big_rec_free( -/*================*/ - big_rec_t* vector) /*!< in, own: big rec vector; it is - freed in this function */ -{ - mem_heap_free(vector->heap); -} diff --git a/storage/innobase/include/data0data.inl b/storage/innobase/include/data0data.inl new file mode 100644 index 00000000000..9b7a3132873 --- /dev/null +++ b/storage/innobase/include/data0data.inl @@ -0,0 +1,634 @@ +/***************************************************************************** + +Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. +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 +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/data0data.ic +SQL data field and tuple + +Created 5/30/1994 Heikki Tuuri +*************************************************************************/ + +#include "ut0rnd.h" + +/*********************************************************************//** +Sets the type struct of SQL data field. */ +UNIV_INLINE +void +dfield_set_type( +/*============*/ + dfield_t* field, /*!< in: SQL data field */ + const dtype_t* type) /*!< in: pointer to data type struct */ +{ + ut_ad(field != NULL); + ut_ad(type != NULL); + + field->type = *type; +} + +/*********************************************************************//** +Sets length in a field. */ +UNIV_INLINE +void +dfield_set_len( +/*===========*/ + dfield_t* field, /*!< in: field */ + ulint len) /*!< in: length or UNIV_SQL_NULL */ +{ + field->ext = 0; + field->len = static_cast(len); +} + +/** Gets spatial status for "external storage" +@param[in,out] field field */ +UNIV_INLINE +spatial_status_t +dfield_get_spatial_status( + const dfield_t* field) +{ + ut_ad(field); + ut_ad(dfield_is_ext(field)); + + return(static_cast(field->spatial_status)); +} + +/** Sets spatial status for "external storage" +@param[in,out] field field +@param[in] spatial_status spatial status */ +UNIV_INLINE +void +dfield_set_spatial_status( + dfield_t* field, + spatial_status_t spatial_status) +{ + ut_ad(field); + ut_ad(dfield_is_ext(field)); + + field->spatial_status = spatial_status; +} + +/*********************************************************************//** +Sets pointer to the data and length in a field. */ +UNIV_INLINE +void +dfield_set_data( +/*============*/ + dfield_t* field, /*!< in: field */ + const void* data, /*!< in: data */ + ulint len) /*!< in: length or UNIV_SQL_NULL */ +{ + field->data = (void*) data; + field->ext = 0; + field->len = static_cast(len); +} + +/*********************************************************************//** +Sets pointer to the data and length in a field. */ +UNIV_INLINE +void +dfield_write_mbr( +/*=============*/ + dfield_t* field, /*!< in: field */ + const double* mbr) /*!< in: data */ +{ + MEM_CHECK_DEFINED(mbr, sizeof *mbr); + field->ext = 0; + + for (unsigned i = 0; i < SPDIMS * 2; i++) { + mach_double_write(static_cast(field->data) + + i * sizeof(double), mbr[i]); + } + + field->len = DATA_MBR_LEN; +} + +/*********************************************************************//** +Sets a data field to SQL NULL. */ +UNIV_INLINE +void +dfield_set_null( +/*============*/ + dfield_t* field) /*!< in/out: field */ +{ + dfield_set_data(field, NULL, UNIV_SQL_NULL); +} + +/*********************************************************************//** +Copies the data and len fields. */ +UNIV_INLINE +void +dfield_copy_data( +/*=============*/ + dfield_t* field1, /*!< out: field to copy to */ + const dfield_t* field2) /*!< in: field to copy from */ +{ + ut_ad(field1 != NULL); + ut_ad(field2 != NULL); + + field1->data = field2->data; + field1->len = field2->len; + field1->ext = field2->ext; + field1->spatial_status = field2->spatial_status; +} + +/*********************************************************************//** +Copies a data field to another. */ +UNIV_INLINE +void +dfield_copy( +/*========*/ + dfield_t* field1, /*!< out: field to copy to */ + const dfield_t* field2) /*!< in: field to copy from */ +{ + *field1 = *field2; +} + +/*********************************************************************//** +Copies the data pointed to by a data field. */ +UNIV_INLINE +void +dfield_dup( +/*=======*/ + dfield_t* field, /*!< in/out: data field */ + mem_heap_t* heap) /*!< in: memory heap where allocated */ +{ + if (!dfield_is_null(field)) { + MEM_CHECK_DEFINED(field->data, field->len); + field->data = mem_heap_dup(heap, field->data, field->len); + } +} + +/*********************************************************************//** +Tests if two data fields are equal. +If len==0, tests the data length and content for equality. +If len>0, tests the first len bytes of the content for equality. +@return TRUE if both fields are NULL or if they are equal */ +UNIV_INLINE +ibool +dfield_datas_are_binary_equal( +/*==========================*/ + const dfield_t* field1, /*!< in: field */ + const dfield_t* field2, /*!< in: field */ + ulint len) /*!< in: maximum prefix to compare, + or 0 to compare the whole field length */ +{ + ulint len2 = len; + + if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) { + len = field1->len; + } + + if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) { + len2 = field2->len; + } + + return(len == len2 + && (len == UNIV_SQL_NULL + || !memcmp(field1->data, field2->data, len))); +} + +/*********************************************************************//** +Tests if dfield data length and content is equal to the given. +@return TRUE if equal */ +UNIV_INLINE +ibool +dfield_data_is_binary_equal( +/*========================*/ + const dfield_t* field, /*!< in: field */ + ulint len, /*!< in: data length or UNIV_SQL_NULL */ + const byte* data) /*!< in: data */ +{ + return(len == dfield_get_len(field) + && (!len || len == UNIV_SQL_NULL + || !memcmp(dfield_get_data(field), data, len))); +} + +/*********************************************************************//** +Gets info bits in a data tuple. +@return info bits */ +UNIV_INLINE +ulint +dtuple_get_info_bits( +/*=================*/ + const dtuple_t* tuple) /*!< in: tuple */ +{ + return(tuple->info_bits); +} + +/*********************************************************************//** +Sets info bits in a data tuple. */ +UNIV_INLINE +void +dtuple_set_info_bits( +/*=================*/ + dtuple_t* tuple, /*!< in: tuple */ + ulint info_bits) /*!< in: info bits */ +{ + tuple->info_bits = info_bits; +} + +/*********************************************************************//** +Gets number of fields used in record comparisons. +@return number of fields used in comparisons in rem0cmp.* */ +UNIV_INLINE +ulint +dtuple_get_n_fields_cmp( +/*====================*/ + const dtuple_t* tuple) /*!< in: tuple */ +{ + return(tuple->n_fields_cmp); +} + +/*********************************************************************//** +Sets number of fields used in record comparisons. */ +UNIV_INLINE +void +dtuple_set_n_fields_cmp( +/*====================*/ + dtuple_t* tuple, /*!< in: tuple */ + ulint n_fields_cmp) /*!< in: number of fields used in + comparisons in rem0cmp.* */ +{ + ut_ad(n_fields_cmp <= tuple->n_fields); + tuple->n_fields_cmp = n_fields_cmp; +} + +/** Creates a data tuple from an already allocated chunk of memory. +The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields). +The default value for number of fields used in record comparisons +for this tuple is n_fields. +@param[in,out] buf buffer to use +@param[in] buf_size buffer size +@param[in] n_fields number of field +@param[in] n_v_fields number of fields on virtual columns +@return created tuple (inside buf) */ +UNIV_INLINE +dtuple_t* +dtuple_create_from_mem( + void* buf, + ulint buf_size, + ulint n_fields, + ulint n_v_fields) +{ + dtuple_t* tuple; + ulint n_t_fields = n_fields + n_v_fields; + + ut_a(buf_size >= DTUPLE_EST_ALLOC(n_t_fields)); + + tuple = (dtuple_t*) buf; + tuple->info_bits = 0; + tuple->n_fields = n_fields; + tuple->n_v_fields = n_v_fields; + tuple->n_fields_cmp = n_fields; + tuple->fields = (dfield_t*) &tuple[1]; + if (n_v_fields > 0) { + tuple->v_fields = &tuple->fields[n_fields]; + } else { + tuple->v_fields = NULL; + } + +#ifdef UNIV_DEBUG + tuple->magic_n = DATA_TUPLE_MAGIC_N; + + { /* In the debug version, initialize fields to an error value */ + ulint i; + + for (i = 0; i < n_t_fields; i++) { + dfield_t* field; + + if (i >= n_fields) { + field = dtuple_get_nth_v_field( + tuple, i - n_fields); + } else { + field = dtuple_get_nth_field(tuple, i); + } + + dfield_set_len(field, UNIV_SQL_NULL); + field->data = &data_error; + dfield_get_type(field)->mtype = DATA_ERROR; + dfield_get_type(field)->prtype = DATA_ERROR; + } + } +#endif + MEM_CHECK_ADDRESSABLE(tuple->fields, n_t_fields + * sizeof *tuple->fields); + MEM_UNDEFINED(tuple->fields, n_t_fields * sizeof *tuple->fields); + return(tuple); +} + +/** Duplicate the virtual field data in a dtuple_t +@param[in,out] vrow dtuple contains the virtual fields +@param[in,out] heap heap memory to use */ +UNIV_INLINE +void +dtuple_dup_v_fld(dtuple_t* vrow, mem_heap_t* heap) +{ + for (ulint i = 0; i < vrow->n_v_fields; i++) { + dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); + dfield_dup(dfield, heap); + } +} + +/** Initialize the virtual field data in a dtuple_t +@param[in,out] vrow dtuple contains the virtual fields */ +UNIV_INLINE +void +dtuple_init_v_fld(dtuple_t* vrow) +{ + for (ulint i = 0; i < vrow->n_v_fields; i++) { + dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); + dfield_get_type(dfield)->mtype = DATA_MISSING; + dfield_set_len(dfield, UNIV_SQL_NULL); + } +} + +/**********************************************************//** +Creates a data tuple to a memory heap. The default value for number +of fields used in record comparisons for this tuple is n_fields. +@return own: created tuple */ +UNIV_INLINE +dtuple_t* +dtuple_create( +/*==========*/ + mem_heap_t* heap, /*!< in: memory heap where the tuple + is created, DTUPLE_EST_ALLOC(n_fields) + bytes will be allocated from this heap */ + ulint n_fields) /*!< in: number of fields */ +{ + return(dtuple_create_with_vcol(heap, n_fields, 0)); +} + +/** Creates a data tuple with virtual columns to a memory heap. +@param[in] heap memory heap where the tuple is created +@param[in] n_fields number of fields +@param[in] n_v_fields number of fields on virtual col +@return own: created tuple */ +UNIV_INLINE +dtuple_t* +dtuple_create_with_vcol( + mem_heap_t* heap, + ulint n_fields, + ulint n_v_fields) +{ + void* buf; + ulint buf_size; + dtuple_t* tuple; + + ut_ad(heap); + + buf_size = DTUPLE_EST_ALLOC(n_fields + n_v_fields); + buf = mem_heap_alloc(heap, buf_size); + + tuple = dtuple_create_from_mem(buf, buf_size, n_fields, n_v_fields); + + return(tuple); +} + +/** Copies a data tuple's virtual fields to another. This is a shallow copy; +@param[in,out] d_tuple destination tuple +@param[in] s_tuple source tuple */ +UNIV_INLINE +void +dtuple_copy_v_fields( + dtuple_t* d_tuple, + const dtuple_t* s_tuple) +{ + + ulint n_v_fields = dtuple_get_n_v_fields(d_tuple); + ut_ad(n_v_fields == dtuple_get_n_v_fields(s_tuple)); + + for (ulint i = 0; i < n_v_fields; i++) { + dfield_copy(dtuple_get_nth_v_field(d_tuple, i), + dtuple_get_nth_v_field(s_tuple, i)); + } +} + +/*********************************************************************//** +Copies a data tuple to another. This is a shallow copy; if a deep copy +is desired, dfield_dup() will have to be invoked on each field. +@return own: copy of tuple */ +UNIV_INLINE +dtuple_t* +dtuple_copy( +/*========*/ + const dtuple_t* tuple, /*!< in: tuple to copy from */ + mem_heap_t* heap) /*!< in: memory heap + where the tuple is created */ +{ + ulint n_fields = dtuple_get_n_fields(tuple); + ulint n_v_fields = dtuple_get_n_v_fields(tuple); + dtuple_t* new_tuple = dtuple_create_with_vcol( + heap, n_fields, n_v_fields); + ulint i; + + for (i = 0; i < n_fields; i++) { + dfield_copy(dtuple_get_nth_field(new_tuple, i), + dtuple_get_nth_field(tuple, i)); + } + + for (i = 0; i < n_v_fields; i++) { + dfield_copy(dtuple_get_nth_v_field(new_tuple, i), + dtuple_get_nth_v_field(tuple, i)); + } + + return(new_tuple); +} + +/**********************************************************//** +The following function returns the sum of data lengths of a tuple. The space +occupied by the field structs or the tuple struct is not counted. Neither +is possible space in externally stored parts of the field. +@return sum of data lengths */ +UNIV_INLINE +ulint +dtuple_get_data_size( +/*=================*/ + const dtuple_t* tuple, /*!< in: typed data tuple */ + ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ +{ + const dfield_t* field; + ulint n_fields; + ulint len; + ulint i; + ulint sum = 0; + + ut_ad(dtuple_check_typed(tuple)); + ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); + + n_fields = tuple->n_fields; + + for (i = 0; i < n_fields; i++) { + field = dtuple_get_nth_field(tuple, i); + len = dfield_get_len(field); + + if (len == UNIV_SQL_NULL) { + len = dtype_get_sql_null_size(dfield_get_type(field), + comp); + } + + sum += len; + } + + return(sum); +} + +/*********************************************************************//** +Computes the number of externally stored fields in a data tuple. +@return number of externally stored fields */ +UNIV_INLINE +ulint +dtuple_get_n_ext( +/*=============*/ + const dtuple_t* tuple) /*!< in: tuple */ +{ + ulint n_ext = 0; + ulint n_fields = tuple->n_fields; + ulint i; + + ut_ad(dtuple_check_typed(tuple)); + ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); + + for (i = 0; i < n_fields; i++) { + n_ext += dtuple_get_nth_field(tuple, i)->ext; + } + + return(n_ext); +} + +/*******************************************************************//** +Sets types of fields binary in a tuple. */ +UNIV_INLINE +void +dtuple_set_types_binary( +/*====================*/ + dtuple_t* tuple, /*!< in: data tuple */ + ulint n) /*!< in: number of fields to set */ +{ + dtype_t* dfield_type; + ulint i; + + for (i = 0; i < n; i++) { + dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i)); + dtype_set(dfield_type, DATA_BINARY, 0, 0); + } +} + +/** Fold a prefix given as the number of fields of a tuple. +@param[in] tuple index record +@param[in] n_fields number of complete fields to fold +@param[in] n_bytes number of bytes to fold in the last field +@param[in] index_id index tree ID +@return the folded value */ +UNIV_INLINE +ulint +dtuple_fold( + const dtuple_t* tuple, + ulint n_fields, + ulint n_bytes, + index_id_t tree_id) +{ + const dfield_t* field; + ulint i; + const byte* data; + ulint len; + ulint fold; + + ut_ad(tuple); + ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); + ut_ad(dtuple_check_typed(tuple)); + + fold = ut_fold_ull(tree_id); + + for (i = 0; i < n_fields; i++) { + field = dtuple_get_nth_field(tuple, i); + + data = (const byte*) dfield_get_data(field); + len = dfield_get_len(field); + + if (len != UNIV_SQL_NULL) { + fold = ut_fold_ulint_pair(fold, + ut_fold_binary(data, len)); + } + } + + if (n_bytes > 0) { + field = dtuple_get_nth_field(tuple, i); + + data = (const byte*) dfield_get_data(field); + len = dfield_get_len(field); + + if (len != UNIV_SQL_NULL) { + if (len > n_bytes) { + len = n_bytes; + } + + fold = ut_fold_ulint_pair(fold, + ut_fold_binary(data, len)); + } + } + + return(fold); +} + +/**********************************************************************//** +Writes an SQL null field full of zeros. */ +UNIV_INLINE +void +data_write_sql_null( +/*================*/ + byte* data, /*!< in: pointer to a buffer of size len */ + ulint len) /*!< in: SQL null size in bytes */ +{ + memset(data, 0, len); +} + +/**********************************************************************//** +Checks if a dtuple contains an SQL null value. +@return TRUE if some field is SQL null */ +UNIV_INLINE +ibool +dtuple_contains_null( +/*=================*/ + const dtuple_t* tuple) /*!< in: dtuple */ +{ + ulint n; + ulint i; + + n = dtuple_get_n_fields(tuple); + + for (i = 0; i < n; i++) { + if (dfield_is_null(dtuple_get_nth_field(tuple, i))) { + + return(TRUE); + } + } + + return(FALSE); +} + +/**************************************************************//** +Frees the memory in a big rec vector. */ +UNIV_INLINE +void +dtuple_big_rec_free( +/*================*/ + big_rec_t* vector) /*!< in, own: big rec vector; it is + freed in this function */ +{ + mem_heap_free(vector->heap); +} diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index f641af8a6c1..54bc85008a1 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -531,6 +531,6 @@ struct dtype_t{ in bytes */ }; -#include "data0type.ic" +#include "data0type.inl" #endif diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic deleted file mode 100644 index 1956016c58b..00000000000 --- a/storage/innobase/include/data0type.ic +++ /dev/null @@ -1,638 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2014, 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 include/data0type.ic -Data types - -Created 1/16/1996 Heikki Tuuri -*******************************************************/ - -#include "mach0data.h" -#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. -@return TRUE if a subset of UTF-8 */ -UNIV_INLINE -ibool -dtype_is_utf8( -/*==========*/ - ulint prtype) /*!< in: precise data type */ -{ - /* These codes have been copied from strings/ctype-extra.c - and strings/ctype-utf8.c. */ - switch (dtype_get_charset_coll(prtype)) { - case 11: /* ascii_general_ci */ - case 65: /* ascii_bin */ - case 33: /* utf8_general_ci */ - case 83: /* utf8_bin */ - case 254: /* utf8_general_cs */ - return(TRUE); - } - - return(FALSE); -} - -/*********************************************************************//** -Gets the MySQL type code from a dtype. -@return MySQL type code; this is NOT an InnoDB type code! */ -UNIV_INLINE -ulint -dtype_get_mysql_type( -/*=================*/ - const dtype_t* type) /*!< in: type struct */ -{ - return(type->prtype & 0xFFUL); -} - -/*********************************************************************//** -Compute the mbminlen and mbmaxlen members of a data type structure. */ -UNIV_INLINE -void -dtype_get_mblen( -/*============*/ - ulint mtype, /*!< in: main type */ - ulint prtype, /*!< in: precise type (and collation) */ - ulint* mbminlen, /*!< out: minimum length of a - multi-byte character */ - ulint* mbmaxlen) /*!< out: maximum length of a - multi-byte character */ -{ - if (dtype_is_string_type(mtype)) { - innobase_get_cset_width(dtype_get_charset_coll(prtype), - mbminlen, mbmaxlen); - ut_ad(*mbminlen <= *mbmaxlen); - ut_ad(*mbminlen < DATA_MBMAX); - ut_ad(*mbmaxlen < DATA_MBMAX); - } else { - *mbminlen = *mbmaxlen = 0; - } -} - -/*********************************************************************//** -Compute the mbminlen and mbmaxlen members of a data type structure. */ -UNIV_INLINE -void -dtype_set_mblen( -/*============*/ - dtype_t* type) /*!< in/out: type */ -{ - ulint mbminlen; - ulint mbmaxlen; - - dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); - type->mbminlen = mbminlen; - type->mbmaxlen = mbmaxlen; - - ut_ad(dtype_validate(type)); -} - -/*********************************************************************//** -Sets a data type structure. */ -UNIV_INLINE -void -dtype_set( -/*======*/ - dtype_t* type, /*!< in: type struct to init */ - ulint mtype, /*!< in: main data type */ - ulint prtype, /*!< in: precise type */ - ulint len) /*!< in: precision of type */ -{ - ut_ad(type); - ut_ad(mtype <= DATA_MTYPE_MAX); - - type->mtype = unsigned(mtype); - type->prtype = unsigned(prtype); - type->len = unsigned(len); - - dtype_set_mblen(type); -} - -/*********************************************************************//** -Copies a data type structure. */ -UNIV_INLINE -void -dtype_copy( -/*=======*/ - dtype_t* type1, /*!< in: type struct to copy to */ - const dtype_t* type2) /*!< in: type struct to copy from */ -{ - *type1 = *type2; - - ut_ad(dtype_validate(type1)); -} - -/*********************************************************************//** -Gets the SQL main data type. -@return SQL main data type */ -UNIV_INLINE -ulint -dtype_get_mtype( -/*============*/ - const dtype_t* type) /*!< in: data type */ -{ - ut_ad(type); - - return(type->mtype); -} - -/*********************************************************************//** -Gets the precise data type. -@return precise data type */ -UNIV_INLINE -ulint -dtype_get_prtype( -/*=============*/ - const dtype_t* type) /*!< in: data type */ -{ - ut_ad(type); - - return(type->prtype); -} - -/*********************************************************************//** -Gets the type length. -@return fixed length of the type, in bytes, or 0 if variable-length */ -UNIV_INLINE -ulint -dtype_get_len( -/*==========*/ - const dtype_t* type) /*!< in: data type */ -{ - ut_ad(type); - - return(type->len); -} - -/*********************************************************************//** -Gets the minimum length of a character, in bytes. -@return minimum length of a char, in bytes, or 0 if this is not a -character type */ -UNIV_INLINE -ulint -dtype_get_mbminlen( -/*===============*/ - const dtype_t* type) /*!< in: type */ -{ - return type->mbminlen; -} -/*********************************************************************//** -Gets the maximum length of a character, in bytes. -@return maximum length of a char, in bytes, or 0 if this is not a -character type */ -UNIV_INLINE -ulint -dtype_get_mbmaxlen( -/*===============*/ - const dtype_t* type) /*!< in: type */ -{ - return type->mbmaxlen; -} - -/**********************************************************************//** -Stores for a type the information which determines its alphabetical ordering -and the storage size of an SQL NULL value. This is the >= 4.1.x storage -format. */ -UNIV_INLINE -void -dtype_new_store_for_order_and_null_size( -/*====================================*/ - byte* buf, /*!< in: buffer for - DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE - bytes where we store the info */ - const dtype_t* type, /*!< in: type struct */ - ulint prefix_len)/*!< in: prefix length to - replace type->len, or 0 */ -{ -#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE -#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" -#endif - ulint len; - - ut_ad(type); - ut_ad(type->mtype >= DATA_VARCHAR); - ut_ad(type->mtype <= DATA_MTYPE_MAX); - - buf[0] = (byte)(type->mtype & 0xFFUL); - - if (type->prtype & DATA_BINARY_TYPE) { - buf[0] |= 128; - } - - /* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) { - buf[0] |= 64; - } - */ - - buf[1] = (byte)(type->prtype & 0xFFUL); - - len = prefix_len ? prefix_len : type->len; - - mach_write_to_2(buf + 2, len & 0xFFFFUL); - - ut_ad(dtype_get_charset_coll(type->prtype) <= MAX_CHAR_COLL_NUM); - mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype)); - - if (type->prtype & DATA_NOT_NULL) { - buf[4] |= 128; - } -} - -/**********************************************************************//** -Reads to a type the stored information which determines its alphabetical -ordering and the storage size of an SQL NULL value. This is the < 4.1.x -storage format. */ -UNIV_INLINE -void -dtype_read_for_order_and_null_size( -/*===============================*/ - dtype_t* type, /*!< in: type struct */ - const byte* buf) /*!< in: buffer for stored type order info */ -{ -#if 4 != DATA_ORDER_NULL_TYPE_BUF_SIZE -# error "4 != DATA_ORDER_NULL_TYPE_BUF_SIZE" -#endif - - type->mtype = buf[0] & 63; - type->prtype = buf[1]; - - if (buf[0] & 128) { - type->prtype |= DATA_BINARY_TYPE; - } - - type->len = mach_read_from_2(buf + 2); - - type->prtype = dtype_form_prtype(type->prtype, - data_mysql_default_charset_coll); - dtype_set_mblen(type); -} - -/**********************************************************************//** -Reads to a type the stored information which determines its alphabetical -ordering and the storage size of an SQL NULL value. This is the >= 4.1.x -storage format. */ -UNIV_INLINE -void -dtype_new_read_for_order_and_null_size( -/*===================================*/ - dtype_t* type, /*!< in: type struct */ - const byte* buf) /*!< in: buffer for stored type order info */ -{ - ulint charset_coll; - -#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE -#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" -#endif - - type->mtype = buf[0] & 63; - type->prtype = buf[1]; - - if (buf[0] & 128) { - type->prtype |= DATA_BINARY_TYPE; - } - - if (buf[4] & 128) { - type->prtype |= DATA_NOT_NULL; - } - - type->len = mach_read_from_2(buf + 2); - - charset_coll = mach_read_from_2(buf + 4) & CHAR_COLL_MASK; - - if (dtype_is_string_type(type->mtype)) { - ut_a(charset_coll <= MAX_CHAR_COLL_NUM); - - if (charset_coll == 0) { - /* This insert buffer record was inserted with MySQL - version < 4.1.2, and the charset-collation code was not - explicitly stored to dtype->prtype at that time. It - must be the default charset-collation of this MySQL - installation. */ - - charset_coll = data_mysql_default_charset_coll; - } - - type->prtype = dtype_form_prtype(type->prtype, charset_coll); - } - dtype_set_mblen(type); -} - -/*********************************************************************//** -Returns the type's SQL name (e.g. BIGINT UNSIGNED) from mtype,prtype,len -@return the SQL type name */ -UNIV_INLINE -char* -dtype_sql_name( -/*===========*/ - unsigned mtype, /*!< in: mtype */ - unsigned prtype, /*!< in: prtype */ - unsigned len, /*!< in: len */ - char* name, /*!< out: SQL name */ - unsigned name_sz)/*!< in: size of the name buffer */ -{ - -#define APPEND_UNSIGNED() \ - do { \ - if (prtype & DATA_UNSIGNED) { \ - snprintf(name + strlen(name), \ - name_sz - strlen(name), \ - " UNSIGNED"); \ - } \ - } while (0) - - snprintf(name, name_sz, "UNKNOWN"); - - switch (mtype) { - case DATA_INT: - switch (len) { - case 1: - snprintf(name, name_sz, "TINYINT"); - break; - case 2: - snprintf(name, name_sz, "SMALLINT"); - break; - case 3: - snprintf(name, name_sz, "MEDIUMINT"); - break; - case 4: - snprintf(name, name_sz, "INT"); - break; - case 8: - snprintf(name, name_sz, "BIGINT"); - break; - } - APPEND_UNSIGNED(); - break; - case DATA_FLOAT: - snprintf(name, name_sz, "FLOAT"); - APPEND_UNSIGNED(); - break; - case DATA_DOUBLE: - snprintf(name, name_sz, "DOUBLE"); - APPEND_UNSIGNED(); - break; - case DATA_FIXBINARY: - snprintf(name, name_sz, "BINARY(%u)", len); - break; - case DATA_CHAR: - case DATA_MYSQL: - snprintf(name, name_sz, "CHAR(%u)", len); - break; - case DATA_VARCHAR: - case DATA_VARMYSQL: - snprintf(name, name_sz, "VARCHAR(%u)", len); - break; - case DATA_BINARY: - snprintf(name, name_sz, "VARBINARY(%u)", len); - break; - case DATA_GEOMETRY: - snprintf(name, name_sz, "GEOMETRY"); - break; - case DATA_BLOB: - switch (len) { - case 9: - snprintf(name, name_sz, "TINYBLOB"); - break; - case 10: - snprintf(name, name_sz, "BLOB"); - break; - case 11: - snprintf(name, name_sz, "MEDIUMBLOB"); - break; - case 12: - snprintf(name, name_sz, "LONGBLOB"); - break; - } - } - - if (prtype & DATA_NOT_NULL) { - snprintf(name + strlen(name), - name_sz - strlen(name), - " NOT NULL"); - } - - return(name); -} - -/***********************************************************************//** -Returns the size of a fixed size data type, 0 if not a fixed size type. -@return fixed size, or 0 */ -UNIV_INLINE -ulint -dtype_get_fixed_size_low( -/*=====================*/ - ulint mtype, /*!< in: main type */ - ulint prtype, /*!< in: precise type */ - ulint len, /*!< in: length */ - ulint mbminlen, /*!< in: minimum length of a - multibyte character, in bytes */ - ulint mbmaxlen, /*!< in: maximum length of a - multibyte character, in bytes */ - ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ -{ - switch (mtype) { - case DATA_SYS: -#ifdef UNIV_DEBUG - switch (prtype & DATA_MYSQL_TYPE_MASK) { - case DATA_ROW_ID: - ut_ad(len == DATA_ROW_ID_LEN); - break; - case DATA_TRX_ID: - ut_ad(len == DATA_TRX_ID_LEN); - break; - case DATA_ROLL_PTR: - ut_ad(len == DATA_ROLL_PTR_LEN); - break; - default: - ut_ad(0); - return(0); - } -#endif /* UNIV_DEBUG */ - /* fall through */ - case DATA_CHAR: - case DATA_FIXBINARY: - case DATA_INT: - case DATA_FLOAT: - case DATA_DOUBLE: - return(len); - case DATA_MYSQL: - if (prtype & DATA_BINARY_TYPE) { - return(len); - } else if (!comp) { - return(len); - } else { -#ifdef UNIV_DEBUG - ulint i_mbminlen, i_mbmaxlen; - - innobase_get_cset_width( - dtype_get_charset_coll(prtype), - &i_mbminlen, &i_mbmaxlen); - - ut_ad(i_mbminlen == mbminlen); - ut_ad(i_mbmaxlen == mbmaxlen); -#endif /* UNIV_DEBUG */ - if (mbminlen == mbmaxlen) { - return(len); - } - } - /* Treat as variable-length. */ - /* fall through */ - case DATA_VARCHAR: - case DATA_BINARY: - case DATA_DECIMAL: - case DATA_VARMYSQL: - case DATA_GEOMETRY: - case DATA_BLOB: - return(0); - default: - ut_error; - } - - return(0); -} - -/***********************************************************************//** -Returns the minimum size of a data type. -@return minimum size */ -UNIV_INLINE -ulint -dtype_get_min_size_low( -/*===================*/ - ulint mtype, /*!< in: main type */ - ulint prtype, /*!< in: precise type */ - ulint len, /*!< in: length */ - ulint mbminlen, /*!< in: minimum length of a character */ - ulint mbmaxlen) /*!< in: maximum length of a character */ -{ - switch (mtype) { - case DATA_SYS: -#ifdef UNIV_DEBUG - switch (prtype & DATA_MYSQL_TYPE_MASK) { - case DATA_ROW_ID: - ut_ad(len == DATA_ROW_ID_LEN); - break; - case DATA_TRX_ID: - ut_ad(len == DATA_TRX_ID_LEN); - break; - case DATA_ROLL_PTR: - ut_ad(len == DATA_ROLL_PTR_LEN); - break; - default: - ut_ad(0); - return(0); - } -#endif /* UNIV_DEBUG */ - /* fall through */ - case DATA_CHAR: - case DATA_FIXBINARY: - case DATA_INT: - case DATA_FLOAT: - case DATA_DOUBLE: - return(len); - case DATA_MYSQL: - if (prtype & DATA_BINARY_TYPE) { - return(len); - } else { - if (mbminlen == mbmaxlen) { - return(len); - } - - /* this is a variable-length character set */ - ut_a(mbminlen > 0); - ut_a(mbmaxlen > mbminlen); - ut_a(len % mbmaxlen == 0); - return(len * mbminlen / mbmaxlen); - } - case DATA_VARCHAR: - case DATA_BINARY: - case DATA_DECIMAL: - case DATA_VARMYSQL: - case DATA_GEOMETRY: - case DATA_BLOB: - return(0); - default: - ut_error; - } - - return(0); -} - -/***********************************************************************//** -Returns the maximum size of a data type. Note: types in system tables may be -incomplete and return incorrect information. -@return maximum size */ -UNIV_INLINE -ulint -dtype_get_max_size_low( -/*===================*/ - ulint mtype, /*!< in: main type */ - ulint len) /*!< in: length */ -{ - switch (mtype) { - case DATA_SYS: - case DATA_CHAR: - case DATA_FIXBINARY: - case DATA_INT: - case DATA_FLOAT: - case DATA_DOUBLE: - case DATA_MYSQL: - case DATA_VARCHAR: - case DATA_BINARY: - case DATA_DECIMAL: - case DATA_VARMYSQL: - return(len); - case DATA_GEOMETRY: - case DATA_BLOB: - break; - default: - ut_error; - } - - return(ULINT_MAX); -} - -/***********************************************************************//** -Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a type. -For fixed length types it is the fixed length of the type, otherwise 0. -@return SQL null storage size in ROW_FORMAT=REDUNDANT */ -UNIV_INLINE -ulint -dtype_get_sql_null_size( -/*====================*/ - const dtype_t* type, /*!< in: type */ - ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ -{ - return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - type->mbminlen, type->mbmaxlen, comp)); -} diff --git a/storage/innobase/include/data0type.inl b/storage/innobase/include/data0type.inl new file mode 100644 index 00000000000..1956016c58b --- /dev/null +++ b/storage/innobase/include/data0type.inl @@ -0,0 +1,638 @@ +/***************************************************************************** + +Copyright (c) 1996, 2014, 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 include/data0type.ic +Data types + +Created 1/16/1996 Heikki Tuuri +*******************************************************/ + +#include "mach0data.h" +#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. +@return TRUE if a subset of UTF-8 */ +UNIV_INLINE +ibool +dtype_is_utf8( +/*==========*/ + ulint prtype) /*!< in: precise data type */ +{ + /* These codes have been copied from strings/ctype-extra.c + and strings/ctype-utf8.c. */ + switch (dtype_get_charset_coll(prtype)) { + case 11: /* ascii_general_ci */ + case 65: /* ascii_bin */ + case 33: /* utf8_general_ci */ + case 83: /* utf8_bin */ + case 254: /* utf8_general_cs */ + return(TRUE); + } + + return(FALSE); +} + +/*********************************************************************//** +Gets the MySQL type code from a dtype. +@return MySQL type code; this is NOT an InnoDB type code! */ +UNIV_INLINE +ulint +dtype_get_mysql_type( +/*=================*/ + const dtype_t* type) /*!< in: type struct */ +{ + return(type->prtype & 0xFFUL); +} + +/*********************************************************************//** +Compute the mbminlen and mbmaxlen members of a data type structure. */ +UNIV_INLINE +void +dtype_get_mblen( +/*============*/ + ulint mtype, /*!< in: main type */ + ulint prtype, /*!< in: precise type (and collation) */ + ulint* mbminlen, /*!< out: minimum length of a + multi-byte character */ + ulint* mbmaxlen) /*!< out: maximum length of a + multi-byte character */ +{ + if (dtype_is_string_type(mtype)) { + innobase_get_cset_width(dtype_get_charset_coll(prtype), + mbminlen, mbmaxlen); + ut_ad(*mbminlen <= *mbmaxlen); + ut_ad(*mbminlen < DATA_MBMAX); + ut_ad(*mbmaxlen < DATA_MBMAX); + } else { + *mbminlen = *mbmaxlen = 0; + } +} + +/*********************************************************************//** +Compute the mbminlen and mbmaxlen members of a data type structure. */ +UNIV_INLINE +void +dtype_set_mblen( +/*============*/ + dtype_t* type) /*!< in/out: type */ +{ + ulint mbminlen; + ulint mbmaxlen; + + dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); + type->mbminlen = mbminlen; + type->mbmaxlen = mbmaxlen; + + ut_ad(dtype_validate(type)); +} + +/*********************************************************************//** +Sets a data type structure. */ +UNIV_INLINE +void +dtype_set( +/*======*/ + dtype_t* type, /*!< in: type struct to init */ + ulint mtype, /*!< in: main data type */ + ulint prtype, /*!< in: precise type */ + ulint len) /*!< in: precision of type */ +{ + ut_ad(type); + ut_ad(mtype <= DATA_MTYPE_MAX); + + type->mtype = unsigned(mtype); + type->prtype = unsigned(prtype); + type->len = unsigned(len); + + dtype_set_mblen(type); +} + +/*********************************************************************//** +Copies a data type structure. */ +UNIV_INLINE +void +dtype_copy( +/*=======*/ + dtype_t* type1, /*!< in: type struct to copy to */ + const dtype_t* type2) /*!< in: type struct to copy from */ +{ + *type1 = *type2; + + ut_ad(dtype_validate(type1)); +} + +/*********************************************************************//** +Gets the SQL main data type. +@return SQL main data type */ +UNIV_INLINE +ulint +dtype_get_mtype( +/*============*/ + const dtype_t* type) /*!< in: data type */ +{ + ut_ad(type); + + return(type->mtype); +} + +/*********************************************************************//** +Gets the precise data type. +@return precise data type */ +UNIV_INLINE +ulint +dtype_get_prtype( +/*=============*/ + const dtype_t* type) /*!< in: data type */ +{ + ut_ad(type); + + return(type->prtype); +} + +/*********************************************************************//** +Gets the type length. +@return fixed length of the type, in bytes, or 0 if variable-length */ +UNIV_INLINE +ulint +dtype_get_len( +/*==========*/ + const dtype_t* type) /*!< in: data type */ +{ + ut_ad(type); + + return(type->len); +} + +/*********************************************************************//** +Gets the minimum length of a character, in bytes. +@return minimum length of a char, in bytes, or 0 if this is not a +character type */ +UNIV_INLINE +ulint +dtype_get_mbminlen( +/*===============*/ + const dtype_t* type) /*!< in: type */ +{ + return type->mbminlen; +} +/*********************************************************************//** +Gets the maximum length of a character, in bytes. +@return maximum length of a char, in bytes, or 0 if this is not a +character type */ +UNIV_INLINE +ulint +dtype_get_mbmaxlen( +/*===============*/ + const dtype_t* type) /*!< in: type */ +{ + return type->mbmaxlen; +} + +/**********************************************************************//** +Stores for a type the information which determines its alphabetical ordering +and the storage size of an SQL NULL value. This is the >= 4.1.x storage +format. */ +UNIV_INLINE +void +dtype_new_store_for_order_and_null_size( +/*====================================*/ + byte* buf, /*!< in: buffer for + DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE + bytes where we store the info */ + const dtype_t* type, /*!< in: type struct */ + ulint prefix_len)/*!< in: prefix length to + replace type->len, or 0 */ +{ +#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE +#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" +#endif + ulint len; + + ut_ad(type); + ut_ad(type->mtype >= DATA_VARCHAR); + ut_ad(type->mtype <= DATA_MTYPE_MAX); + + buf[0] = (byte)(type->mtype & 0xFFUL); + + if (type->prtype & DATA_BINARY_TYPE) { + buf[0] |= 128; + } + + /* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) { + buf[0] |= 64; + } + */ + + buf[1] = (byte)(type->prtype & 0xFFUL); + + len = prefix_len ? prefix_len : type->len; + + mach_write_to_2(buf + 2, len & 0xFFFFUL); + + ut_ad(dtype_get_charset_coll(type->prtype) <= MAX_CHAR_COLL_NUM); + mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype)); + + if (type->prtype & DATA_NOT_NULL) { + buf[4] |= 128; + } +} + +/**********************************************************************//** +Reads to a type the stored information which determines its alphabetical +ordering and the storage size of an SQL NULL value. This is the < 4.1.x +storage format. */ +UNIV_INLINE +void +dtype_read_for_order_and_null_size( +/*===============================*/ + dtype_t* type, /*!< in: type struct */ + const byte* buf) /*!< in: buffer for stored type order info */ +{ +#if 4 != DATA_ORDER_NULL_TYPE_BUF_SIZE +# error "4 != DATA_ORDER_NULL_TYPE_BUF_SIZE" +#endif + + type->mtype = buf[0] & 63; + type->prtype = buf[1]; + + if (buf[0] & 128) { + type->prtype |= DATA_BINARY_TYPE; + } + + type->len = mach_read_from_2(buf + 2); + + type->prtype = dtype_form_prtype(type->prtype, + data_mysql_default_charset_coll); + dtype_set_mblen(type); +} + +/**********************************************************************//** +Reads to a type the stored information which determines its alphabetical +ordering and the storage size of an SQL NULL value. This is the >= 4.1.x +storage format. */ +UNIV_INLINE +void +dtype_new_read_for_order_and_null_size( +/*===================================*/ + dtype_t* type, /*!< in: type struct */ + const byte* buf) /*!< in: buffer for stored type order info */ +{ + ulint charset_coll; + +#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE +#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" +#endif + + type->mtype = buf[0] & 63; + type->prtype = buf[1]; + + if (buf[0] & 128) { + type->prtype |= DATA_BINARY_TYPE; + } + + if (buf[4] & 128) { + type->prtype |= DATA_NOT_NULL; + } + + type->len = mach_read_from_2(buf + 2); + + charset_coll = mach_read_from_2(buf + 4) & CHAR_COLL_MASK; + + if (dtype_is_string_type(type->mtype)) { + ut_a(charset_coll <= MAX_CHAR_COLL_NUM); + + if (charset_coll == 0) { + /* This insert buffer record was inserted with MySQL + version < 4.1.2, and the charset-collation code was not + explicitly stored to dtype->prtype at that time. It + must be the default charset-collation of this MySQL + installation. */ + + charset_coll = data_mysql_default_charset_coll; + } + + type->prtype = dtype_form_prtype(type->prtype, charset_coll); + } + dtype_set_mblen(type); +} + +/*********************************************************************//** +Returns the type's SQL name (e.g. BIGINT UNSIGNED) from mtype,prtype,len +@return the SQL type name */ +UNIV_INLINE +char* +dtype_sql_name( +/*===========*/ + unsigned mtype, /*!< in: mtype */ + unsigned prtype, /*!< in: prtype */ + unsigned len, /*!< in: len */ + char* name, /*!< out: SQL name */ + unsigned name_sz)/*!< in: size of the name buffer */ +{ + +#define APPEND_UNSIGNED() \ + do { \ + if (prtype & DATA_UNSIGNED) { \ + snprintf(name + strlen(name), \ + name_sz - strlen(name), \ + " UNSIGNED"); \ + } \ + } while (0) + + snprintf(name, name_sz, "UNKNOWN"); + + switch (mtype) { + case DATA_INT: + switch (len) { + case 1: + snprintf(name, name_sz, "TINYINT"); + break; + case 2: + snprintf(name, name_sz, "SMALLINT"); + break; + case 3: + snprintf(name, name_sz, "MEDIUMINT"); + break; + case 4: + snprintf(name, name_sz, "INT"); + break; + case 8: + snprintf(name, name_sz, "BIGINT"); + break; + } + APPEND_UNSIGNED(); + break; + case DATA_FLOAT: + snprintf(name, name_sz, "FLOAT"); + APPEND_UNSIGNED(); + break; + case DATA_DOUBLE: + snprintf(name, name_sz, "DOUBLE"); + APPEND_UNSIGNED(); + break; + case DATA_FIXBINARY: + snprintf(name, name_sz, "BINARY(%u)", len); + break; + case DATA_CHAR: + case DATA_MYSQL: + snprintf(name, name_sz, "CHAR(%u)", len); + break; + case DATA_VARCHAR: + case DATA_VARMYSQL: + snprintf(name, name_sz, "VARCHAR(%u)", len); + break; + case DATA_BINARY: + snprintf(name, name_sz, "VARBINARY(%u)", len); + break; + case DATA_GEOMETRY: + snprintf(name, name_sz, "GEOMETRY"); + break; + case DATA_BLOB: + switch (len) { + case 9: + snprintf(name, name_sz, "TINYBLOB"); + break; + case 10: + snprintf(name, name_sz, "BLOB"); + break; + case 11: + snprintf(name, name_sz, "MEDIUMBLOB"); + break; + case 12: + snprintf(name, name_sz, "LONGBLOB"); + break; + } + } + + if (prtype & DATA_NOT_NULL) { + snprintf(name + strlen(name), + name_sz - strlen(name), + " NOT NULL"); + } + + return(name); +} + +/***********************************************************************//** +Returns the size of a fixed size data type, 0 if not a fixed size type. +@return fixed size, or 0 */ +UNIV_INLINE +ulint +dtype_get_fixed_size_low( +/*=====================*/ + ulint mtype, /*!< in: main type */ + ulint prtype, /*!< in: precise type */ + ulint len, /*!< in: length */ + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a + multibyte character, in bytes */ + ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ +{ + switch (mtype) { + case DATA_SYS: +#ifdef UNIV_DEBUG + switch (prtype & DATA_MYSQL_TYPE_MASK) { + case DATA_ROW_ID: + ut_ad(len == DATA_ROW_ID_LEN); + break; + case DATA_TRX_ID: + ut_ad(len == DATA_TRX_ID_LEN); + break; + case DATA_ROLL_PTR: + ut_ad(len == DATA_ROLL_PTR_LEN); + break; + default: + ut_ad(0); + return(0); + } +#endif /* UNIV_DEBUG */ + /* fall through */ + case DATA_CHAR: + case DATA_FIXBINARY: + case DATA_INT: + case DATA_FLOAT: + case DATA_DOUBLE: + return(len); + case DATA_MYSQL: + if (prtype & DATA_BINARY_TYPE) { + return(len); + } else if (!comp) { + return(len); + } else { +#ifdef UNIV_DEBUG + ulint i_mbminlen, i_mbmaxlen; + + innobase_get_cset_width( + dtype_get_charset_coll(prtype), + &i_mbminlen, &i_mbmaxlen); + + ut_ad(i_mbminlen == mbminlen); + ut_ad(i_mbmaxlen == mbmaxlen); +#endif /* UNIV_DEBUG */ + if (mbminlen == mbmaxlen) { + return(len); + } + } + /* Treat as variable-length. */ + /* fall through */ + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_DECIMAL: + case DATA_VARMYSQL: + case DATA_GEOMETRY: + case DATA_BLOB: + return(0); + default: + ut_error; + } + + return(0); +} + +/***********************************************************************//** +Returns the minimum size of a data type. +@return minimum size */ +UNIV_INLINE +ulint +dtype_get_min_size_low( +/*===================*/ + ulint mtype, /*!< in: main type */ + ulint prtype, /*!< in: precise type */ + ulint len, /*!< in: length */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen) /*!< in: maximum length of a character */ +{ + switch (mtype) { + case DATA_SYS: +#ifdef UNIV_DEBUG + switch (prtype & DATA_MYSQL_TYPE_MASK) { + case DATA_ROW_ID: + ut_ad(len == DATA_ROW_ID_LEN); + break; + case DATA_TRX_ID: + ut_ad(len == DATA_TRX_ID_LEN); + break; + case DATA_ROLL_PTR: + ut_ad(len == DATA_ROLL_PTR_LEN); + break; + default: + ut_ad(0); + return(0); + } +#endif /* UNIV_DEBUG */ + /* fall through */ + case DATA_CHAR: + case DATA_FIXBINARY: + case DATA_INT: + case DATA_FLOAT: + case DATA_DOUBLE: + return(len); + case DATA_MYSQL: + if (prtype & DATA_BINARY_TYPE) { + return(len); + } else { + if (mbminlen == mbmaxlen) { + return(len); + } + + /* this is a variable-length character set */ + ut_a(mbminlen > 0); + ut_a(mbmaxlen > mbminlen); + ut_a(len % mbmaxlen == 0); + return(len * mbminlen / mbmaxlen); + } + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_DECIMAL: + case DATA_VARMYSQL: + case DATA_GEOMETRY: + case DATA_BLOB: + return(0); + default: + ut_error; + } + + return(0); +} + +/***********************************************************************//** +Returns the maximum size of a data type. Note: types in system tables may be +incomplete and return incorrect information. +@return maximum size */ +UNIV_INLINE +ulint +dtype_get_max_size_low( +/*===================*/ + ulint mtype, /*!< in: main type */ + ulint len) /*!< in: length */ +{ + switch (mtype) { + case DATA_SYS: + case DATA_CHAR: + case DATA_FIXBINARY: + case DATA_INT: + case DATA_FLOAT: + case DATA_DOUBLE: + case DATA_MYSQL: + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_DECIMAL: + case DATA_VARMYSQL: + return(len); + case DATA_GEOMETRY: + case DATA_BLOB: + break; + default: + ut_error; + } + + return(ULINT_MAX); +} + +/***********************************************************************//** +Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a type. +For fixed length types it is the fixed length of the type, otherwise 0. +@return SQL null storage size in ROW_FORMAT=REDUNDANT */ +UNIV_INLINE +ulint +dtype_get_sql_null_size( +/*====================*/ + const dtype_t* type, /*!< in: type */ + ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ +{ + return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, + type->mbminlen, type->mbmaxlen, comp)); +} diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index 3baefdd1132..4dbd0bcc78d 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -350,6 +350,6 @@ two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is updated */ #define DICT_HDR_ROW_ID_WRITE_MARGIN 256 -#include "dict0boot.ic" +#include "dict0boot.inl" #endif diff --git a/storage/innobase/include/dict0boot.ic b/storage/innobase/include/dict0boot.ic deleted file mode 100644 index c3862b5c76a..00000000000 --- a/storage/innobase/include/dict0boot.ic +++ /dev/null @@ -1,96 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2013, 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/dict0boot.ic -Data dictionary creation and booting - -Created 4/18/1996 Heikki Tuuri -*******************************************************/ - -/**********************************************************************//** -Returns a new row id. -@return the new id */ -UNIV_INLINE -row_id_t -dict_sys_get_new_row_id(void) -/*=========================*/ -{ - row_id_t id; - - mutex_enter(&dict_sys->mutex); - - id = dict_sys->row_id; - - if (0 == (id % DICT_HDR_ROW_ID_WRITE_MARGIN)) { - - dict_hdr_flush_row_id(); - } - - dict_sys->row_id++; - - mutex_exit(&dict_sys->mutex); - - return(id); -} - -/**********************************************************************//** -Reads a row id from a record or other 6-byte stored form. -@return row id */ -UNIV_INLINE -row_id_t -dict_sys_read_row_id( -/*=================*/ - const byte* field) /*!< in: record field */ -{ -#if DATA_ROW_ID_LEN != 6 -# error "DATA_ROW_ID_LEN != 6" -#endif - - return(mach_read_from_6(field)); -} - -/**********************************************************************//** -Writes a row id to a record or other 6-byte stored form. */ -UNIV_INLINE -void -dict_sys_write_row_id( -/*==================*/ - byte* field, /*!< in: record field */ - row_id_t row_id) /*!< in: row id */ -{ -#if DATA_ROW_ID_LEN != 6 -# error "DATA_ROW_ID_LEN != 6" -#endif - - mach_write_to_6(field, row_id); -} - -/*********************************************************************//** -Check if a table id belongs to system table. -@return true if the table id belongs to a system table. */ -UNIV_INLINE -bool -dict_is_sys_table( -/*==============*/ - table_id_t id) /*!< in: table id to check */ -{ - return(id < DICT_HDR_FIRST_ID); -} - - diff --git a/storage/innobase/include/dict0boot.inl b/storage/innobase/include/dict0boot.inl new file mode 100644 index 00000000000..c3862b5c76a --- /dev/null +++ b/storage/innobase/include/dict0boot.inl @@ -0,0 +1,96 @@ +/***************************************************************************** + +Copyright (c) 1996, 2013, 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/dict0boot.ic +Data dictionary creation and booting + +Created 4/18/1996 Heikki Tuuri +*******************************************************/ + +/**********************************************************************//** +Returns a new row id. +@return the new id */ +UNIV_INLINE +row_id_t +dict_sys_get_new_row_id(void) +/*=========================*/ +{ + row_id_t id; + + mutex_enter(&dict_sys->mutex); + + id = dict_sys->row_id; + + if (0 == (id % DICT_HDR_ROW_ID_WRITE_MARGIN)) { + + dict_hdr_flush_row_id(); + } + + dict_sys->row_id++; + + mutex_exit(&dict_sys->mutex); + + return(id); +} + +/**********************************************************************//** +Reads a row id from a record or other 6-byte stored form. +@return row id */ +UNIV_INLINE +row_id_t +dict_sys_read_row_id( +/*=================*/ + const byte* field) /*!< in: record field */ +{ +#if DATA_ROW_ID_LEN != 6 +# error "DATA_ROW_ID_LEN != 6" +#endif + + return(mach_read_from_6(field)); +} + +/**********************************************************************//** +Writes a row id to a record or other 6-byte stored form. */ +UNIV_INLINE +void +dict_sys_write_row_id( +/*==================*/ + byte* field, /*!< in: record field */ + row_id_t row_id) /*!< in: row id */ +{ +#if DATA_ROW_ID_LEN != 6 +# error "DATA_ROW_ID_LEN != 6" +#endif + + mach_write_to_6(field, row_id); +} + +/*********************************************************************//** +Check if a table id belongs to system table. +@return true if the table id belongs to a system table. */ +UNIV_INLINE +bool +dict_is_sys_table( +/*==============*/ + table_id_t id) /*!< in: table id to check */ +{ + return(id < DICT_HDR_FIRST_ID); +} + + diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index 359d9f556e5..4495c039df6 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -358,6 +358,6 @@ dict_get_v_col_pos( #define INDEX_CREATE_INDEX_TREE 3 #define INDEX_ADD_TO_CACHE 4 -#include "dict0crea.ic" +#include "dict0crea.inl" #endif diff --git a/storage/innobase/include/dict0crea.ic b/storage/innobase/include/dict0crea.ic deleted file mode 100644 index 5641206d313..00000000000 --- a/storage/innobase/include/dict0crea.ic +++ /dev/null @@ -1,136 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 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 -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/dict0crea.ic -Database object creation - -Created 1/8/1996 Heikki Tuuri -*******************************************************/ - -#include "ha_prototypes.h" - -#include "mem0mem.h" - -/********************************************************************//** -Generate a foreign key constraint name when it was not named by the user. -A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER, -where the numbers start from 1, and are given locally for this table, that is, -the number is not global, as it used to be before MySQL 4.0.18. */ -UNIV_INLINE -dberr_t -dict_create_add_foreign_id( -/*=======================*/ - ulint* id_nr, /*!< in/out: number to use in id generation; - incremented if used */ - const char* name, /*!< in: table name */ - dict_foreign_t* foreign)/*!< in/out: foreign key */ -{ - DBUG_ENTER("dict_create_add_foreign_id"); - - if (foreign->id == NULL) { - /* Generate a new constraint id */ - ulint namelen = strlen(name); - char* id = static_cast( - mem_heap_alloc(foreign->heap, - namelen + 20)); - - if (dict_table_t::is_temporary_name(name)) { - - /* no overflow if number < 1e13 */ - sprintf(id, "%s_ibfk_%lu", name, - (ulong) (*id_nr)++); - } else { - char table_name[MAX_TABLE_NAME_LEN + 21]; - uint errors = 0; - - strncpy(table_name, name, (sizeof table_name) - 1); - table_name[(sizeof table_name) - 1] = '\0'; - - innobase_convert_to_system_charset( - strchr(table_name, '/') + 1, - strchr(name, '/') + 1, - MAX_TABLE_NAME_LEN, &errors); - - if (errors) { - strncpy(table_name, name, - (sizeof table_name) - 1); - table_name[(sizeof table_name) - 1] = '\0'; - } - - /* no overflow if number < 1e13 */ - sprintf(id, "%s_ibfk_%lu", table_name, - (ulong) (*id_nr)++); - - if (innobase_check_identifier_length( - strchr(id,'/') + 1)) { - DBUG_RETURN(DB_IDENTIFIER_TOO_LONG); - } - } - foreign->id = id; - - DBUG_PRINT("dict_create_add_foreign_id", - ("generated foreign id: %s", id)); - } - - - DBUG_RETURN(DB_SUCCESS); -} - -/** Compose a column number for a virtual column, stored in the "POS" field -of Sys_columns. The column number includes both its virtual column sequence -(the "nth" virtual column) and its actual column position in original table -@param[in] v_pos virtual column sequence -@param[in] col_pos column position in original table definition -@return composed column position number */ -UNIV_INLINE -ulint -dict_create_v_col_pos( - ulint v_pos, - ulint col_pos) -{ - ut_ad(v_pos <= REC_MAX_N_FIELDS); - ut_ad(col_pos <= REC_MAX_N_FIELDS); - - return(((v_pos + 1) << 16) + col_pos); -} - -/** Get the column number for a virtual column (the column position in -original table), stored in the "POS" field of Sys_columns -@param[in] pos virtual column position -@return column position in original table */ -UNIV_INLINE -ulint -dict_get_v_col_mysql_pos( - ulint pos) -{ - return(pos & 0xFFFF); -} - -/** Get a virtual column sequence (the "nth" virtual column) for a -virtual column, stord in the "POS" field of Sys_columns -@param[in] pos virtual column position -@return virtual column sequence */ -UNIV_INLINE -ulint -dict_get_v_col_pos( - ulint pos) -{ - return((pos >> 16) - 1); -} diff --git a/storage/innobase/include/dict0crea.inl b/storage/innobase/include/dict0crea.inl new file mode 100644 index 00000000000..5641206d313 --- /dev/null +++ b/storage/innobase/include/dict0crea.inl @@ -0,0 +1,136 @@ +/***************************************************************************** + +Copyright (c) 1996, 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 +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/dict0crea.ic +Database object creation + +Created 1/8/1996 Heikki Tuuri +*******************************************************/ + +#include "ha_prototypes.h" + +#include "mem0mem.h" + +/********************************************************************//** +Generate a foreign key constraint name when it was not named by the user. +A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER, +where the numbers start from 1, and are given locally for this table, that is, +the number is not global, as it used to be before MySQL 4.0.18. */ +UNIV_INLINE +dberr_t +dict_create_add_foreign_id( +/*=======================*/ + ulint* id_nr, /*!< in/out: number to use in id generation; + incremented if used */ + const char* name, /*!< in: table name */ + dict_foreign_t* foreign)/*!< in/out: foreign key */ +{ + DBUG_ENTER("dict_create_add_foreign_id"); + + if (foreign->id == NULL) { + /* Generate a new constraint id */ + ulint namelen = strlen(name); + char* id = static_cast( + mem_heap_alloc(foreign->heap, + namelen + 20)); + + if (dict_table_t::is_temporary_name(name)) { + + /* no overflow if number < 1e13 */ + sprintf(id, "%s_ibfk_%lu", name, + (ulong) (*id_nr)++); + } else { + char table_name[MAX_TABLE_NAME_LEN + 21]; + uint errors = 0; + + strncpy(table_name, name, (sizeof table_name) - 1); + table_name[(sizeof table_name) - 1] = '\0'; + + innobase_convert_to_system_charset( + strchr(table_name, '/') + 1, + strchr(name, '/') + 1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + strncpy(table_name, name, + (sizeof table_name) - 1); + table_name[(sizeof table_name) - 1] = '\0'; + } + + /* no overflow if number < 1e13 */ + sprintf(id, "%s_ibfk_%lu", table_name, + (ulong) (*id_nr)++); + + if (innobase_check_identifier_length( + strchr(id,'/') + 1)) { + DBUG_RETURN(DB_IDENTIFIER_TOO_LONG); + } + } + foreign->id = id; + + DBUG_PRINT("dict_create_add_foreign_id", + ("generated foreign id: %s", id)); + } + + + DBUG_RETURN(DB_SUCCESS); +} + +/** Compose a column number for a virtual column, stored in the "POS" field +of Sys_columns. The column number includes both its virtual column sequence +(the "nth" virtual column) and its actual column position in original table +@param[in] v_pos virtual column sequence +@param[in] col_pos column position in original table definition +@return composed column position number */ +UNIV_INLINE +ulint +dict_create_v_col_pos( + ulint v_pos, + ulint col_pos) +{ + ut_ad(v_pos <= REC_MAX_N_FIELDS); + ut_ad(col_pos <= REC_MAX_N_FIELDS); + + return(((v_pos + 1) << 16) + col_pos); +} + +/** Get the column number for a virtual column (the column position in +original table), stored in the "POS" field of Sys_columns +@param[in] pos virtual column position +@return column position in original table */ +UNIV_INLINE +ulint +dict_get_v_col_mysql_pos( + ulint pos) +{ + return(pos & 0xFFFF); +} + +/** Get a virtual column sequence (the "nth" virtual column) for a +virtual column, stord in the "POS" field of Sys_columns +@param[in] pos virtual column position +@return virtual column sequence */ +UNIV_INLINE +ulint +dict_get_v_col_pos( + ulint pos) +{ + return((pos >> 16) - 1); +} diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 6cfb92a94d3..ccf7da259d6 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1912,6 +1912,6 @@ bool dict_table_have_virtual_index( dict_table_t* table); -#include "dict0dict.ic" +#include "dict0dict.inl" #endif diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic deleted file mode 100644 index 554bfdd50ac..00000000000 --- a/storage/innobase/include/dict0dict.ic +++ /dev/null @@ -1,1545 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -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 -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/dict0dict.ic -Data dictionary system - -Created 1/8/1996 Heikki Tuuri -***********************************************************************/ - -#include "fsp0sysspace.h" - -/*********************************************************************//** -Gets the minimum number of bytes per character. -@return minimum multi-byte char size, in bytes */ -UNIV_INLINE -ulint -dict_col_get_mbminlen( -/*==================*/ - const dict_col_t* col) /*!< in: column */ -{ - return col->mbminlen; -} -/*********************************************************************//** -Gets the maximum number of bytes per character. -@return maximum multi-byte char size, in bytes */ -UNIV_INLINE -ulint -dict_col_get_mbmaxlen( -/*==================*/ - const dict_col_t* col) /*!< in: column */ -{ - return col->mbmaxlen; -} -/*********************************************************************//** -Gets the column data type. */ -UNIV_INLINE -void -dict_col_copy_type( -/*===============*/ - const dict_col_t* col, /*!< in: column */ - dtype_t* type) /*!< out: data type */ -{ - ut_ad(col != NULL); - ut_ad(type != NULL); - - type->mtype = col->mtype; - type->prtype = col->prtype; - type->len = col->len; - type->mbminlen = col->mbminlen; - type->mbmaxlen = col->mbmaxlen; -} - -#ifdef UNIV_DEBUG -/*********************************************************************//** -Assert that a column and a data type match. -@return TRUE */ -UNIV_INLINE -ibool -dict_col_type_assert_equal( -/*=======================*/ - const dict_col_t* col, /*!< in: column */ - const dtype_t* type) /*!< in: data type */ -{ - ut_ad(col->mtype == type->mtype); - ut_ad(col->prtype == type->prtype); - //ut_ad(col->len == type->len); - ut_ad(col->mbminlen == type->mbminlen); - ut_ad(col->mbmaxlen == type->mbmaxlen); - - return(TRUE); -} -#endif /* UNIV_DEBUG */ - -/***********************************************************************//** -Returns the minimum size of the column. -@return minimum size */ -UNIV_INLINE -ulint -dict_col_get_min_size( -/*==================*/ - const dict_col_t* col) /*!< in: column */ -{ - return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, - col->mbminlen, col->mbmaxlen)); -} -/***********************************************************************//** -Returns the maximum size of the column. -@return maximum size */ -UNIV_INLINE -ulint -dict_col_get_max_size( -/*==================*/ - const dict_col_t* col) /*!< in: column */ -{ - return(dtype_get_max_size_low(col->mtype, col->len)); -} -/***********************************************************************//** -Returns the size of a fixed size column, 0 if not a fixed size column. -@return fixed size, or 0 */ -UNIV_INLINE -ulint -dict_col_get_fixed_size( -/*====================*/ - const dict_col_t* col, /*!< in: column */ - ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ -{ - return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, - col->mbminlen, col->mbmaxlen, comp)); -} -/***********************************************************************//** -Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. -For fixed length types it is the fixed length of the type, otherwise 0. -@return SQL null storage size in ROW_FORMAT=REDUNDANT */ -UNIV_INLINE -ulint -dict_col_get_sql_null_size( -/*=======================*/ - const dict_col_t* col, /*!< in: column */ - ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ -{ - return(dict_col_get_fixed_size(col, comp)); -} - -/*********************************************************************//** -Gets the column number. -@return col->ind, table column position (starting from 0) */ -UNIV_INLINE -ulint -dict_col_get_no( -/*============*/ - const dict_col_t* col) /*!< in: column */ -{ - return(col->ind); -} - -/*********************************************************************//** -Gets the column position in the clustered index. */ -UNIV_INLINE -ulint -dict_col_get_clust_pos( -/*===================*/ - const dict_col_t* col, /*!< in: table column */ - const dict_index_t* clust_index) /*!< in: clustered index */ -{ - ulint i; - - ut_ad(dict_index_is_clust(clust_index)); - - for (i = 0; i < clust_index->n_def; i++) { - const dict_field_t* field = &clust_index->fields[i]; - - if (!field->prefix_len && field->col == col) { - return(i); - } - } - - return(ULINT_UNDEFINED); -} - -/** Gets the column position in the given index. -@param[in] col table column -@param[in] index index to be searched for column -@return position of column in the given index. */ -UNIV_INLINE -ulint -dict_col_get_index_pos( - const dict_col_t* col, - const dict_index_t* index) -{ - ulint i; - - for (i = 0; i < index->n_def; i++) { - const dict_field_t* field = &index->fields[i]; - - if (!field->prefix_len && field->col == col) { - return(i); - } - } - - return(ULINT_UNDEFINED); -} - -#ifdef UNIV_DEBUG -/********************************************************************//** -Gets the first index on the table (the clustered index). -@return index, NULL if none exists */ -UNIV_INLINE -dict_index_t* -dict_table_get_first_index( -/*=======================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - - return(UT_LIST_GET_FIRST(((dict_table_t*) table)->indexes)); -} - -/********************************************************************//** -Gets the last index on the table. -@return index, NULL if none exists */ -UNIV_INLINE -dict_index_t* -dict_table_get_last_index( -/*=======================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - return(UT_LIST_GET_LAST((const_cast(table)) - ->indexes)); -} - -/********************************************************************//** -Gets the next index on the table. -@return index, NULL if none left */ -UNIV_INLINE -dict_index_t* -dict_table_get_next_index( -/*======================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - return(UT_LIST_GET_NEXT(indexes, (dict_index_t*) 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(index->type & DICT_SPATIAL); -} - -/********************************************************************//** -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 -columns of a table */ -UNIV_INLINE -ulint -dict_table_get_n_user_cols( -/*=======================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - return(table->n_cols - DATA_N_SYS_COLS); -} - -/********************************************************************//** -Gets the number of all non-virtual columns (also system) in a table -in the dictionary cache. -@return number of non-virtual columns of a table */ -UNIV_INLINE -ulint -dict_table_get_n_cols( -/*==================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - return(table->n_cols); -} - -/** Gets the number of virtual columns in a table in the dictionary cache. -@param[in] table the table to check -@return number of virtual columns of a table */ -UNIV_INLINE -ulint -dict_table_get_n_v_cols( - const dict_table_t* table) -{ - ut_ad(table); - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - - return(table->n_v_cols); -} - -/** Check if a table has indexed virtual columns -@param[in] table the table to check -@return true is the table has indexed virtual columns */ -UNIV_INLINE -bool -dict_table_has_indexed_v_cols( - const dict_table_t* table) -{ - - for (ulint i = 0; i < table->n_v_cols; i++) { - const dict_v_col_t* col = dict_table_get_nth_v_col(table, i); - if (col->m_col.ord_part) { - return(true); - } - } - - return(false); -} - -/********************************************************************//** -Gets the approximately estimated number of rows in the table. -@return estimated number of rows */ -UNIV_INLINE -ib_uint64_t -dict_table_get_n_rows( -/*==================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table->stat_initialized); - - return(table->stat_n_rows); -} - -/********************************************************************//** -Increment the number of rows in the table by one. -Notice that this operation is not protected by any latch, the number is -approximate. */ -UNIV_INLINE -void -dict_table_n_rows_inc( -/*==================*/ - dict_table_t* table) /*!< in/out: table */ -{ - if (table->stat_initialized) { - ib_uint64_t n_rows = table->stat_n_rows; - if (n_rows < 0xFFFFFFFFFFFFFFFFULL) { - table->stat_n_rows = n_rows + 1; - } - } -} - -/********************************************************************//** -Decrement the number of rows in the table by one. -Notice that this operation is not protected by any latch, the number is -approximate. */ -UNIV_INLINE -void -dict_table_n_rows_dec( -/*==================*/ - dict_table_t* table) /*!< in/out: table */ -{ - if (table->stat_initialized) { - ib_uint64_t n_rows = table->stat_n_rows; - if (n_rows > 0) { - table->stat_n_rows = n_rows - 1; - } - } -} - -#ifdef UNIV_DEBUG -/********************************************************************//** -Gets the nth column of a table. -@return pointer to column object */ -UNIV_INLINE -dict_col_t* -dict_table_get_nth_col( -/*===================*/ - const dict_table_t* table, /*!< in: table */ - ulint pos) /*!< in: position of column */ -{ - ut_ad(pos < table->n_def); - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - - return((dict_col_t*) (table->cols) + pos); -} - -/** Gets the nth virtual column of a table. -@param[in] table table -@param[in] pos position of virtual column -@return pointer to virtual column object */ -UNIV_INLINE -dict_v_col_t* -dict_table_get_nth_v_col( - const dict_table_t* table, - ulint pos) -{ - ut_ad(table); - ut_ad(pos < table->n_v_def); - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - - return(static_cast(table->v_cols) + pos); -} - -/********************************************************************//** -Gets the given system column of a table. -@return pointer to column object */ -UNIV_INLINE -dict_col_t* -dict_table_get_sys_col( -/*===================*/ - const dict_table_t* table, /*!< in: table */ - ulint sys) /*!< in: DATA_ROW_ID, ... */ -{ - dict_col_t* col; - - ut_ad(sys < DATA_N_SYS_COLS); - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - - col = dict_table_get_nth_col(table, table->n_cols - + (sys - DATA_N_SYS_COLS)); - ut_ad(col->mtype == DATA_SYS); - ut_ad(col->prtype == (sys | DATA_NOT_NULL)); - - return(col); -} -#endif /* UNIV_DEBUG */ - -/********************************************************************//** -Gets the given system column number of a table. -@return column number */ -UNIV_INLINE -ulint -dict_table_get_sys_col_no( -/*======================*/ - const dict_table_t* table, /*!< in: table */ - ulint sys) /*!< in: DATA_ROW_ID, ... */ -{ - ut_ad(sys < DATA_N_SYS_COLS); - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - return 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 -ibool -dict_table_is_comp( -/*===============*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table); - -#if DICT_TF_COMPACT != 1 -#error "DICT_TF_COMPACT must be 1" -#endif - - return(table->flags & DICT_TF_COMPACT); -} - -/************************************************************************ -Check if the table has an FTS index. */ -UNIV_INLINE -ibool -dict_table_has_fts_index( -/*=====================*/ - /* out: TRUE if table has an FTS index */ - dict_table_t* table) /* in: table */ -{ - return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS)); -} - -/** Validate the flags for tables that are not ROW_FORMAT=REDUNDANT. -@param[in] flags table flags -@return whether the flags are valid */ -inline -bool -dict_tf_is_valid_not_redundant(ulint flags) -{ - const bool atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags); - - ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags); - - if (!zip_ssize) { - /* Not ROW_FORMAT=COMPRESSED */ - } else if (!atomic_blobs) { - /* ROW_FORMAT=COMPRESSED implies ROW_FORMAT=DYNAMIC - for the uncompressed page format */ - return(false); - } else if (zip_ssize > PAGE_ZIP_SSIZE_MAX - || zip_ssize > UNIV_PAGE_SIZE_SHIFT - || UNIV_PAGE_SIZE_SHIFT > UNIV_ZIP_SIZE_SHIFT_MAX) { - /* KEY_BLOCK_SIZE is out of bounds, or - ROW_FORMAT=COMPRESSED is not supported with this - innodb_page_size (only up to 16KiB) */ - return(false); - } - - switch (DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags)) { - case 0: - /* PAGE_COMPRESSION_LEVEL=0 should imply PAGE_COMPRESSED=NO */ - return(!DICT_TF_GET_PAGE_COMPRESSION(flags)); - case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: - /* PAGE_COMPRESSION_LEVEL requires - ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC - (not ROW_FORMAT=COMPRESSED or ROW_FORMAT=REDUNDANT) - and PAGE_COMPRESSED=YES */ - return(!zip_ssize && DICT_TF_GET_PAGE_COMPRESSION(flags)); - default: - /* Invalid PAGE_COMPRESSION_LEVEL value */ - return(false); - } -} - -/** Validate the table flags. -@param[in] flags Table flags -@return true if valid. */ -UNIV_INLINE -bool -dict_tf_is_valid( - ulint flags) -{ - ut_ad(flags < 1U << DICT_TF_BITS); - /* The DATA_DIRECTORY flag can be assigned fully independently - of all other persistent table flags. */ - flags &= ~DICT_TF_MASK_DATA_DIR; - if (!(flags & 1)) { - /* Only ROW_FORMAT=REDUNDANT has 0 in the least significant - bit. For ROW_FORMAT=REDUNDANT, only the DATA_DIR flag - (which we cleared above) can be set. If any other flags - are set, the flags are invalid. */ - return(flags == 0); - } - - return(dict_tf_is_valid_not_redundant(flags)); -} - -/** Validate both table flags and table flags2 and make sure they -are compatible. -@param[in] flags Table flags -@param[in] flags2 Table flags2 -@return true if valid. */ -UNIV_INLINE -bool -dict_tf2_is_valid( - ulint flags, - ulint flags2) -{ - if (!dict_tf_is_valid(flags)) { - return(false); - } - - if ((flags2 & DICT_TF2_UNUSED_BIT_MASK) != 0) { - return(false); - } - - return(true); -} - -/********************************************************************//** -Determine the file format from dict_table_t::flags -The low order bit will be zero for REDUNDANT and 1 for COMPACT. For any -other row_format, file_format is > 0 and DICT_TF_COMPACT will also be set. -@return file format version */ -UNIV_INLINE -rec_format_t -dict_tf_get_rec_format( -/*===================*/ - ulint flags) /*!< in: dict_table_t::flags */ -{ - ut_a(dict_tf_is_valid(flags)); - - if (!DICT_TF_GET_COMPACT(flags)) { - return(REC_FORMAT_REDUNDANT); - } - - if (!DICT_TF_HAS_ATOMIC_BLOBS(flags)) { - return(REC_FORMAT_COMPACT); - } - - if (DICT_TF_GET_ZIP_SSIZE(flags)) { - return(REC_FORMAT_COMPRESSED); - } - - return(REC_FORMAT_DYNAMIC); -} - -/********************************************************************//** -Determine the file format from a dict_table_t::flags. -@return file format version */ -UNIV_INLINE -ulint -dict_tf_get_format( -/*===============*/ - ulint flags) /*!< in: dict_table_t::flags */ -{ - if (DICT_TF_HAS_ATOMIC_BLOBS(flags)) { - return(UNIV_FORMAT_B); - } - - return(UNIV_FORMAT_A); -} - -/********************************************************************//** -Determine the file format of a table. -@return file format version */ -UNIV_INLINE -ulint -dict_table_get_format( -/*==================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table); - - return(dict_tf_get_format(table->flags)); -} - -/** 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 -@param[in] zip_ssize Zip Shift Size -@param[in] use_data_dir Table uses DATA DIRECTORY -@param[in] page_compressed Table uses page compression -@param[in] page_compression_level Page compression level -@param[in] not_used For future */ -UNIV_INLINE -void -dict_tf_set( -/*========*/ - ulint* flags, - rec_format_t format, - ulint zip_ssize, - bool use_data_dir, - bool page_compressed, - ulint page_compression_level, - ulint not_used) -{ - *flags = use_data_dir ? 1 << DICT_TF_POS_DATA_DIR : 0; - - switch (format) { - case REC_FORMAT_REDUNDANT: - ut_ad(zip_ssize == 0); - /* no other options are allowed */ - ut_ad(!page_compressed); - return; - case REC_FORMAT_COMPACT: - *flags |= DICT_TF_COMPACT; - ut_ad(zip_ssize == 0); - break; - case REC_FORMAT_COMPRESSED: - *flags |= DICT_TF_COMPACT - | (1 << DICT_TF_POS_ATOMIC_BLOBS) - | (zip_ssize << DICT_TF_POS_ZIP_SSIZE); - break; - case REC_FORMAT_DYNAMIC: - *flags |= DICT_TF_COMPACT - | (1 << DICT_TF_POS_ATOMIC_BLOBS); - ut_ad(zip_ssize == 0); - break; - } - - if (page_compressed) { - *flags |= (1 << DICT_TF_POS_ATOMIC_BLOBS) - | (1 << DICT_TF_POS_PAGE_COMPRESSION) - | (page_compression_level << DICT_TF_POS_PAGE_COMPRESSION_LEVEL); - - ut_ad(zip_ssize == 0); - ut_ad(dict_tf_get_page_compression(*flags) == TRUE); - ut_ad(dict_tf_get_page_compression_level(*flags) == page_compression_level); - } -} - -/** Convert a 32 bit integer table flags to the 32 bit FSP Flags. -Fsp Flags are written into the tablespace header at the offset -FSP_SPACE_FLAGS and are also stored in the fil_space_t::flags field. -The following chart shows the translation of the low order bit. -Other bits are the same. -========================= Low order bit ========================== - | REDUNDANT | COMPACT | COMPRESSED | DYNAMIC -dict_table_t::flags | 0 | 1 | 1 | 1 -fil_space_t::flags | 0 | 0 | 1 | 1 -================================================================== -@param[in] table_flags dict_table_t::flags -@return tablespace flags (fil_space_t::flags) */ -UNIV_INLINE -ulint -dict_tf_to_fsp_flags(ulint table_flags) -{ - ulint fsp_flags; - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL( - table_flags); - - ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0) - == (page_compression_level == 0)); - - 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; - - /* 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(); - - if (page_compression_level) { - fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION; - } - - ut_a(fsp_flags_is_valid(fsp_flags, false)); - - if (DICT_TF_HAS_DATA_DIR(table_flags)) { - fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; - } - - fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL; - - return(fsp_flags); -} - -/********************************************************************//** -Convert a 32 bit integer table flags to the 32bit integer that is written -to a SYS_TABLES.TYPE field. The following chart shows the translation of -the low order bit. Other bits are the same. -========================= Low order bit ========================== - | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC -dict_table_t::flags | 0 | 1 | 1 -SYS_TABLES.TYPE | 1 | 1 | 1 -================================================================== -@return ulint containing SYS_TABLES.TYPE */ -UNIV_INLINE -ulint -dict_tf_to_sys_tables_type( -/*=======================*/ - ulint flags) /*!< in: dict_table_t::flags */ -{ - ulint type; - - ut_a(dict_tf_is_valid(flags)); - - /* Adjust bit zero. It is always 1 in SYS_TABLES.TYPE */ - type = 1; - - /* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION, - PAGE_COMPRESSION_LEVEL are the same. */ - type |= flags & (DICT_TF_MASK_ZIP_SSIZE - | DICT_TF_MASK_ATOMIC_BLOBS - | DICT_TF_MASK_DATA_DIR - | DICT_TF_MASK_PAGE_COMPRESSION - | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL); - - 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, univ_page_size.logical(), true)); -} - -/** Get the table page size. -@param[in] table table -@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_table_page_size( - const dict_table_t* table) -{ - ut_ad(table != NULL); - - return(dict_tf_get_page_size(table->flags)); -} - -/*********************************************************************//** -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 */ -{ - ut_ad(mutex_own(&dict_sys->mutex)); - - dict_index_t* clust_index = dict_table_get_first_index(table); - - /* Loop through each index of the table and lock them */ - for (dict_index_t* index = dict_table_get_next_index(clust_index); - index != NULL; - index = dict_table_get_next_index(index)) { - rw_lock_x_lock(dict_index_get_lock(index)); - } - - rw_lock_x_lock(dict_index_get_lock(clust_index)); -} - -/*********************************************************************//** -Returns true if the particular FTS index in the table is still syncing -in the background, false otherwise. -@param [in] table Table containing FTS index -@return True if sync of fts index is still going in the background */ -UNIV_INLINE -bool -dict_fts_index_syncing( - dict_table_t* table) -{ - dict_index_t* index; - - for (index = dict_table_get_first_index(table); - index != NULL; - index = dict_table_get_next_index(index)) { - if (index->index_fts_syncing) { - return(true); - } - } - 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, -including fields added by the dictionary system. -@return number of fields */ -UNIV_INLINE -ulint -dict_index_get_n_fields( -/*====================*/ - const dict_index_t* index) /*!< in: an internal - representation of index (in - the dictionary cache) */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - return(index->n_fields); -} - -/********************************************************************//** -Gets the number of fields in the internal representation of an index -that uniquely determine the position of an index entry in the index, if -we do not take multiversioning into account: in the B-tree use the value -returned by dict_index_get_n_unique_in_tree. -@return number of fields */ -UNIV_INLINE -ulint -dict_index_get_n_unique( -/*====================*/ - const dict_index_t* index) /*!< in: an internal representation - of index (in the dictionary cache) */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - ut_ad(index->cached); - return(index->n_uniq); -} - -/********************************************************************//** -Gets the number of fields in the internal representation of an index -which uniquely determine the position of an index entry in the index, if -we also take multiversioning into account. -@return number of fields */ -UNIV_INLINE -ulint -dict_index_get_n_unique_in_tree( -/*============================*/ - const dict_index_t* index) /*!< in: an internal representation - of index (in the dictionary cache) */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - ut_ad(index->cached); - - if (dict_index_is_clust(index)) { - - return(dict_index_get_n_unique(index)); - } - - return(dict_index_get_n_fields(index)); -} - -/** -Gets the number of fields on nonleaf page level in the internal representation -of an index which uniquely determine the position of an index entry in the -index, if we also take multiversioning into account. Note, it doesn't -include page no field. -@param[in] index index -@return number of fields */ -UNIV_INLINE -ulint -dict_index_get_n_unique_in_tree_nonleaf( - const dict_index_t* index) -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - ut_ad(index->cached); - - if (dict_index_is_spatial(index)) { - /* For spatial index, on non-leaf page, we have only - 2 fields(mbr+page_no). So, except page no field, - there's one field there. */ - return(DICT_INDEX_SPATIAL_NODEPTR_SIZE); - } else { - return(dict_index_get_n_unique_in_tree(index)); - } -} - -/********************************************************************//** -Gets the number of user-defined ordering fields in the index. In the internal -representation of clustered indexes we add the row id to the ordering fields -to make a clustered index unique, but this function returns the number of -fields the user defined in the index as ordering fields. -@return number of fields */ -UNIV_INLINE -ulint -dict_index_get_n_ordering_defined_by_user( -/*======================================*/ - const dict_index_t* index) /*!< in: an internal representation - of index (in the dictionary cache) */ -{ - return(index->n_user_defined_cols); -} - -#ifdef UNIV_DEBUG -/********************************************************************//** -Gets the nth field of an index. -@return pointer to field object */ -UNIV_INLINE -dict_field_t* -dict_index_get_nth_field( -/*=====================*/ - const dict_index_t* index, /*!< in: index */ - ulint pos) /*!< in: position of field */ -{ - ut_ad(pos < index->n_def); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return((dict_field_t*) (index->fields) + pos); -} -#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 */ -UNIV_INLINE -const dict_col_t* -dict_field_get_col( -/*===============*/ - const dict_field_t* field) /*!< in: index field */ -{ - return(field->col); -} - -/********************************************************************//** -Gets pointer to the nth column in an index. -@return column */ -UNIV_INLINE -const dict_col_t* -dict_index_get_nth_col( -/*===================*/ - const dict_index_t* index, /*!< in: index */ - ulint pos) /*!< in: position of the field */ -{ - return(dict_field_get_col(dict_index_get_nth_field(index, pos))); -} - -/********************************************************************//** -Gets the column number the nth field in an index. -@return column number */ -UNIV_INLINE -ulint -dict_index_get_nth_col_no( -/*======================*/ - const dict_index_t* index, /*!< in: index */ - ulint pos) /*!< in: position of the field */ -{ - return(dict_col_get_no(dict_index_get_nth_col(index, pos))); -} - -/********************************************************************//** -Looks for column n in an index. -@return position in internal representation of the index; -ULINT_UNDEFINED if not contained */ -UNIV_INLINE -ulint -dict_index_get_nth_col_pos( -/*=======================*/ - const dict_index_t* index, /*!< in: index */ - ulint n, /*!< in: column number */ - ulint* prefix_col_pos) /*!< out: col num if prefix */ -{ - return(dict_index_get_nth_col_or_prefix_pos(index, n, false, false, - prefix_col_pos)); -} - -/********************************************************************//** -Returns the minimum data size of an index record. -@return minimum data size in bytes */ -UNIV_INLINE -ulint -dict_index_get_min_size( -/*====================*/ - const dict_index_t* index) /*!< in: index */ -{ - ulint n = dict_index_get_n_fields(index); - ulint size = 0; - - while (n--) { - size += dict_col_get_min_size(dict_index_get_nth_col(index, - n)); - } - - return(size); -} - -/*********************************************************************//** -Gets the space id of the root of the index tree. -@return space id */ -UNIV_INLINE -ulint -dict_index_get_space( -/*=================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return(index->space); -} - -/*********************************************************************//** -Sets the space id of the root of the index tree. */ -UNIV_INLINE -void -dict_index_set_space( -/*=================*/ - dict_index_t* index, /*!< in/out: index */ - ulint space) /*!< in: space id */ -{ - ut_ad(index); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - index->space = unsigned(space); -} - -/*********************************************************************//** -Gets the page number of the root of the index tree. -@return page number */ -UNIV_INLINE -ulint -dict_index_get_page( -/*================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return(index->page); -} - -/*********************************************************************//** -Gets the read-write lock of the index tree. -@return read-write lock */ -UNIV_INLINE -rw_lock_t* -dict_index_get_lock( -/*================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return(&(index->lock)); -} - -/********************************************************************//** -Returns free space reserved for future updates of records. This is -relevant only in the case of many consecutive inserts, as updates -which make the records bigger might fragment the index. -@return number of free bytes on page, reserved for updates */ -UNIV_INLINE -ulint -dict_index_get_space_reserve(void) -/*==============================*/ -{ - return(UNIV_PAGE_SIZE / 16); -} - -/********************************************************************//** -Gets the status of online index creation. -@return the status */ -UNIV_INLINE -enum online_index_status -dict_index_get_online_status( -/*=========================*/ - const dict_index_t* index) /*!< in: secondary index */ -{ - enum online_index_status status; - - status = (enum online_index_status) index->online_status; - - /* Without the index->lock protection, the online - status can change from ONLINE_INDEX_CREATION to - ONLINE_INDEX_COMPLETE (or ONLINE_INDEX_ABORTED) in - row_log_apply() once log application is done. So to make - sure the status is ONLINE_INDEX_CREATION or ONLINE_INDEX_COMPLETE - you should always do the recheck after acquiring index->lock */ - -#ifdef UNIV_DEBUG - switch (status) { - case ONLINE_INDEX_COMPLETE: - case ONLINE_INDEX_CREATION: - case ONLINE_INDEX_ABORTED: - case ONLINE_INDEX_ABORTED_DROPPED: - return(status); - } - ut_error; -#endif /* UNIV_DEBUG */ - return(status); -} - -/********************************************************************//** -Sets the status of online index creation. */ -UNIV_INLINE -void -dict_index_set_online_status( -/*=========================*/ - dict_index_t* index, /*!< in/out: index */ - enum online_index_status status) /*!< in: status */ -{ - ut_ad(!(index->type & DICT_FTS)); - ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X)); - -#ifdef UNIV_DEBUG - switch (dict_index_get_online_status(index)) { - case ONLINE_INDEX_COMPLETE: - case ONLINE_INDEX_CREATION: - break; - case ONLINE_INDEX_ABORTED: - ut_ad(status == ONLINE_INDEX_ABORTED_DROPPED); - break; - case ONLINE_INDEX_ABORTED_DROPPED: - ut_error; - } -#endif /* UNIV_DEBUG */ - - index->online_status = status; - ut_ad(dict_index_get_online_status(index) == status); -} - -/********************************************************************//** -Determines if a secondary index is being or has been created online, -or if the table is being rebuilt online, allowing concurrent modifications -to the table. -@retval true if the index is being or has been built online, or -if this is a clustered index and the table is being or has been rebuilt online -@retval false if the index has been created or the table has been -rebuilt completely */ -UNIV_INLINE -bool -dict_index_is_online_ddl( -/*=====================*/ - const dict_index_t* index) /*!< in: index */ -{ -#ifdef UNIV_DEBUG - if (dict_index_is_clust(index)) { - switch (dict_index_get_online_status(index)) { - case ONLINE_INDEX_CREATION: - return(true); - case ONLINE_INDEX_COMPLETE: - return(false); - case ONLINE_INDEX_ABORTED: - case ONLINE_INDEX_ABORTED_DROPPED: - break; - } - ut_ad(0); - return(false); - } -#endif /* UNIV_DEBUG */ - - return(UNIV_UNLIKELY(dict_index_get_online_status(index) - != ONLINE_INDEX_COMPLETE)); -} - -/**********************************************************************//** -Check whether a column exists in an FTS index. -@return ULINT_UNDEFINED if no match else the offset within the vector */ -UNIV_INLINE -ulint -dict_table_is_fts_column( -/*=====================*/ - ib_vector_t* indexes,/*!< in: vector containing only FTS indexes */ - ulint col_no, /*!< in: col number to search for */ - bool is_virtual) /*!< in: whether it is a virtual column */ - -{ - ulint i; - - for (i = 0; i < ib_vector_size(indexes); ++i) { - dict_index_t* index; - - index = (dict_index_t*) ib_vector_getp(indexes, i); - - if (dict_index_contains_col_or_prefix( - index, col_no, is_virtual)) { - - return(i); - } - } - - return(ULINT_UNDEFINED); -} - -/**********************************************************************//** -Determine bytes of column prefix to be stored in the undo log. Please -note if the table format is UNIV_FORMAT_A (< UNIV_FORMAT_B), no prefix -needs to be stored in the undo log. -@return bytes of column prefix to be stored in the undo log */ -UNIV_INLINE -ulint -dict_max_field_len_store_undo( -/*==========================*/ - dict_table_t* table, /*!< in: table */ - const dict_col_t* col) /*!< in: column which index prefix - is based on */ -{ - ulint prefix_len = 0; - - if (dict_table_get_format(table) >= UNIV_FORMAT_B) - { - prefix_len = col->max_prefix - ? col->max_prefix - : DICT_MAX_FIELD_LEN_BY_FORMAT(table); - } - - return(prefix_len); -} - -/** Determine maximum bytes of a virtual column need to be stored -in the undo log. -@param[in] table dict_table_t for the table -@param[in] col_no virtual column number -@return maximum bytes of virtual column to be stored in the undo log */ -UNIV_INLINE -ulint -dict_max_v_field_len_store_undo( - dict_table_t* table, - ulint col_no) -{ - const dict_col_t* col - = &dict_table_get_nth_v_col(table, col_no)->m_col; - ulint max_log_len; - - /* This calculation conforms to the non-virtual column - maximum log length calculation: - 1) for UNIV_FORMAT_A, upto REC_ANTELOPE_MAX_INDEX_COL_LEN - for UNIV_FORMAT_B, upto col->max_prefix or - 2) REC_VERSION_56_MAX_INDEX_COL_LEN, whichever is less */ - if (dict_table_get_format(table) >= UNIV_FORMAT_B) { - if (DATA_BIG_COL(col) && col->max_prefix > 0) { - max_log_len = col->max_prefix; - } else { - max_log_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table); - } - } else { - max_log_len = REC_ANTELOPE_MAX_INDEX_COL_LEN; - } - - 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 */ -UNIV_INLINE -ulint -dict_table_is_corrupted( -/*====================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - return(table->corrupted); -} - -/********************************************************************//** -Check if the tablespace for the table has been discarded. -@return true if the tablespace has been discarded. */ -UNIV_INLINE -bool -dict_table_is_discarded( -/*====================*/ - const dict_table_t* table) /*!< in: table to check */ -{ - return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_DISCARDED)); -} - -/** Check if the table is found is a file_per_table tablespace. -This test does not use table flags2 since some REDUNDANT tables in the -system tablespace may have garbage in the MIX_LEN field where flags2 is -stored. These garbage MIX_LEN fields were written before v3.23.52. -A patch was added to v3.23.52 which initializes the MIX_LEN field to 0. -Since file-per-table tablespaces were added in 4.1, any SYS_TABLES -record with a non-zero space ID will have a reliable MIX_LEN field. -However, this test does not use flags2 from SYS_TABLES.MIX_LEN. Instead, -assume that if the tablespace is not a predefined system tablespace, - then it must be file-per-table. -Also, during ALTER TABLE, the DICT_TF2_USE_FILE_PER_TABLE flag may not be -set on one of the file-per-table tablespaces. -This test cannot be done on a table in the process of being created -because the space_id will be zero until the tablespace is created. -@param[in] table An existing open table to check -@return true if this table was created as a file-per-table tablespace. */ -UNIV_INLINE -bool -dict_table_is_file_per_table( - const dict_table_t* table) /*!< in: table to check */ -{ - return !is_system_tablespace(table->space); -} - -/** Acquire the table handle. */ -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); -} - -/** Release the table handle. -@return whether the last handle was released */ -inline -bool -dict_table_t::release() -{ - int32 n = my_atomic_add32_explicit( - &n_ref_count, -1, MY_MEMORY_ORDER_RELAXED); - ut_ad(n > 0); - return n == 1; -} - -/** Encode the number of columns and number of virtual columns in a -4 bytes value. We could do this because the number of columns in -InnoDB is limited to 1017 -@param[in] n_col number of non-virtual column -@param[in] n_v_col number of virtual column -@return encoded value */ -UNIV_INLINE -ulint -dict_table_encode_n_col( - ulint n_col, - ulint n_v_col) -{ - return(n_col + (n_v_col<<16)); -} - -/** decode number of virtual and non-virtual columns in one 4 bytes value. -@param[in] encoded encoded value -@param[in,out] n_col number of non-virtual column -@param[in,out] n_v_col number of virtual column */ -UNIV_INLINE -void -dict_table_decode_n_col( - ulint encoded, - ulint* n_col, - ulint* n_v_col) -{ - - ulint num = encoded & ~DICT_N_COLS_COMPACT; - *n_v_col = num >> 16; - *n_col = num & 0xFFFF; -} - -/** Free the virtual column template -@param[in,out] vc_templ virtual column template */ -void -dict_free_vc_templ( - dict_vcol_templ_t* vc_templ) -{ - UT_DELETE_ARRAY(vc_templ->default_rec); - vc_templ->default_rec = NULL; - - if (vc_templ->vtempl != NULL) { - ut_ad(vc_templ->n_v_col > 0); - for (ulint i = 0; i < vc_templ->n_col - + vc_templ->n_v_col; i++) { - if (vc_templ->vtempl[i] != NULL) { - ut_free(vc_templ->vtempl[i]); - } - } - ut_free(vc_templ->vtempl); - vc_templ->vtempl = NULL; - } -} - -/** Check whether the table have virtual index. -@param[in] table InnoDB table -@return true if the table have virtual index, false otherwise. */ -UNIV_INLINE -bool -dict_table_have_virtual_index( - dict_table_t* table) -{ - for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(table); - col_no++) { - const dict_v_col_t* col - = dict_table_get_nth_v_col(table, col_no); - - if (col->m_col.ord_part) { - return(true); - } - } - - return(false); -} diff --git a/storage/innobase/include/dict0dict.inl b/storage/innobase/include/dict0dict.inl new file mode 100644 index 00000000000..554bfdd50ac --- /dev/null +++ b/storage/innobase/include/dict0dict.inl @@ -0,0 +1,1545 @@ +/***************************************************************************** + +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. +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 +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/dict0dict.ic +Data dictionary system + +Created 1/8/1996 Heikki Tuuri +***********************************************************************/ + +#include "fsp0sysspace.h" + +/*********************************************************************//** +Gets the minimum number of bytes per character. +@return minimum multi-byte char size, in bytes */ +UNIV_INLINE +ulint +dict_col_get_mbminlen( +/*==================*/ + const dict_col_t* col) /*!< in: column */ +{ + return col->mbminlen; +} +/*********************************************************************//** +Gets the maximum number of bytes per character. +@return maximum multi-byte char size, in bytes */ +UNIV_INLINE +ulint +dict_col_get_mbmaxlen( +/*==================*/ + const dict_col_t* col) /*!< in: column */ +{ + return col->mbmaxlen; +} +/*********************************************************************//** +Gets the column data type. */ +UNIV_INLINE +void +dict_col_copy_type( +/*===============*/ + const dict_col_t* col, /*!< in: column */ + dtype_t* type) /*!< out: data type */ +{ + ut_ad(col != NULL); + ut_ad(type != NULL); + + type->mtype = col->mtype; + type->prtype = col->prtype; + type->len = col->len; + type->mbminlen = col->mbminlen; + type->mbmaxlen = col->mbmaxlen; +} + +#ifdef UNIV_DEBUG +/*********************************************************************//** +Assert that a column and a data type match. +@return TRUE */ +UNIV_INLINE +ibool +dict_col_type_assert_equal( +/*=======================*/ + const dict_col_t* col, /*!< in: column */ + const dtype_t* type) /*!< in: data type */ +{ + ut_ad(col->mtype == type->mtype); + ut_ad(col->prtype == type->prtype); + //ut_ad(col->len == type->len); + ut_ad(col->mbminlen == type->mbminlen); + ut_ad(col->mbmaxlen == type->mbmaxlen); + + return(TRUE); +} +#endif /* UNIV_DEBUG */ + +/***********************************************************************//** +Returns the minimum size of the column. +@return minimum size */ +UNIV_INLINE +ulint +dict_col_get_min_size( +/*==================*/ + const dict_col_t* col) /*!< in: column */ +{ + return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, + col->mbminlen, col->mbmaxlen)); +} +/***********************************************************************//** +Returns the maximum size of the column. +@return maximum size */ +UNIV_INLINE +ulint +dict_col_get_max_size( +/*==================*/ + const dict_col_t* col) /*!< in: column */ +{ + return(dtype_get_max_size_low(col->mtype, col->len)); +} +/***********************************************************************//** +Returns the size of a fixed size column, 0 if not a fixed size column. +@return fixed size, or 0 */ +UNIV_INLINE +ulint +dict_col_get_fixed_size( +/*====================*/ + const dict_col_t* col, /*!< in: column */ + ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ +{ + return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, + col->mbminlen, col->mbmaxlen, comp)); +} +/***********************************************************************//** +Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. +For fixed length types it is the fixed length of the type, otherwise 0. +@return SQL null storage size in ROW_FORMAT=REDUNDANT */ +UNIV_INLINE +ulint +dict_col_get_sql_null_size( +/*=======================*/ + const dict_col_t* col, /*!< in: column */ + ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ +{ + return(dict_col_get_fixed_size(col, comp)); +} + +/*********************************************************************//** +Gets the column number. +@return col->ind, table column position (starting from 0) */ +UNIV_INLINE +ulint +dict_col_get_no( +/*============*/ + const dict_col_t* col) /*!< in: column */ +{ + return(col->ind); +} + +/*********************************************************************//** +Gets the column position in the clustered index. */ +UNIV_INLINE +ulint +dict_col_get_clust_pos( +/*===================*/ + const dict_col_t* col, /*!< in: table column */ + const dict_index_t* clust_index) /*!< in: clustered index */ +{ + ulint i; + + ut_ad(dict_index_is_clust(clust_index)); + + for (i = 0; i < clust_index->n_def; i++) { + const dict_field_t* field = &clust_index->fields[i]; + + if (!field->prefix_len && field->col == col) { + return(i); + } + } + + return(ULINT_UNDEFINED); +} + +/** Gets the column position in the given index. +@param[in] col table column +@param[in] index index to be searched for column +@return position of column in the given index. */ +UNIV_INLINE +ulint +dict_col_get_index_pos( + const dict_col_t* col, + const dict_index_t* index) +{ + ulint i; + + for (i = 0; i < index->n_def; i++) { + const dict_field_t* field = &index->fields[i]; + + if (!field->prefix_len && field->col == col) { + return(i); + } + } + + return(ULINT_UNDEFINED); +} + +#ifdef UNIV_DEBUG +/********************************************************************//** +Gets the first index on the table (the clustered index). +@return index, NULL if none exists */ +UNIV_INLINE +dict_index_t* +dict_table_get_first_index( +/*=======================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + return(UT_LIST_GET_FIRST(((dict_table_t*) table)->indexes)); +} + +/********************************************************************//** +Gets the last index on the table. +@return index, NULL if none exists */ +UNIV_INLINE +dict_index_t* +dict_table_get_last_index( +/*=======================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + return(UT_LIST_GET_LAST((const_cast(table)) + ->indexes)); +} + +/********************************************************************//** +Gets the next index on the table. +@return index, NULL if none left */ +UNIV_INLINE +dict_index_t* +dict_table_get_next_index( +/*======================*/ + const dict_index_t* index) /*!< in: index */ +{ + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + return(UT_LIST_GET_NEXT(indexes, (dict_index_t*) 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(index->type & DICT_SPATIAL); +} + +/********************************************************************//** +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 +columns of a table */ +UNIV_INLINE +ulint +dict_table_get_n_user_cols( +/*=======================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + return(table->n_cols - DATA_N_SYS_COLS); +} + +/********************************************************************//** +Gets the number of all non-virtual columns (also system) in a table +in the dictionary cache. +@return number of non-virtual columns of a table */ +UNIV_INLINE +ulint +dict_table_get_n_cols( +/*==================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + return(table->n_cols); +} + +/** Gets the number of virtual columns in a table in the dictionary cache. +@param[in] table the table to check +@return number of virtual columns of a table */ +UNIV_INLINE +ulint +dict_table_get_n_v_cols( + const dict_table_t* table) +{ + ut_ad(table); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + return(table->n_v_cols); +} + +/** Check if a table has indexed virtual columns +@param[in] table the table to check +@return true is the table has indexed virtual columns */ +UNIV_INLINE +bool +dict_table_has_indexed_v_cols( + const dict_table_t* table) +{ + + for (ulint i = 0; i < table->n_v_cols; i++) { + const dict_v_col_t* col = dict_table_get_nth_v_col(table, i); + if (col->m_col.ord_part) { + return(true); + } + } + + return(false); +} + +/********************************************************************//** +Gets the approximately estimated number of rows in the table. +@return estimated number of rows */ +UNIV_INLINE +ib_uint64_t +dict_table_get_n_rows( +/*==================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table->stat_initialized); + + return(table->stat_n_rows); +} + +/********************************************************************//** +Increment the number of rows in the table by one. +Notice that this operation is not protected by any latch, the number is +approximate. */ +UNIV_INLINE +void +dict_table_n_rows_inc( +/*==================*/ + dict_table_t* table) /*!< in/out: table */ +{ + if (table->stat_initialized) { + ib_uint64_t n_rows = table->stat_n_rows; + if (n_rows < 0xFFFFFFFFFFFFFFFFULL) { + table->stat_n_rows = n_rows + 1; + } + } +} + +/********************************************************************//** +Decrement the number of rows in the table by one. +Notice that this operation is not protected by any latch, the number is +approximate. */ +UNIV_INLINE +void +dict_table_n_rows_dec( +/*==================*/ + dict_table_t* table) /*!< in/out: table */ +{ + if (table->stat_initialized) { + ib_uint64_t n_rows = table->stat_n_rows; + if (n_rows > 0) { + table->stat_n_rows = n_rows - 1; + } + } +} + +#ifdef UNIV_DEBUG +/********************************************************************//** +Gets the nth column of a table. +@return pointer to column object */ +UNIV_INLINE +dict_col_t* +dict_table_get_nth_col( +/*===================*/ + const dict_table_t* table, /*!< in: table */ + ulint pos) /*!< in: position of column */ +{ + ut_ad(pos < table->n_def); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + return((dict_col_t*) (table->cols) + pos); +} + +/** Gets the nth virtual column of a table. +@param[in] table table +@param[in] pos position of virtual column +@return pointer to virtual column object */ +UNIV_INLINE +dict_v_col_t* +dict_table_get_nth_v_col( + const dict_table_t* table, + ulint pos) +{ + ut_ad(table); + ut_ad(pos < table->n_v_def); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + return(static_cast(table->v_cols) + pos); +} + +/********************************************************************//** +Gets the given system column of a table. +@return pointer to column object */ +UNIV_INLINE +dict_col_t* +dict_table_get_sys_col( +/*===================*/ + const dict_table_t* table, /*!< in: table */ + ulint sys) /*!< in: DATA_ROW_ID, ... */ +{ + dict_col_t* col; + + ut_ad(sys < DATA_N_SYS_COLS); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + col = dict_table_get_nth_col(table, table->n_cols + + (sys - DATA_N_SYS_COLS)); + ut_ad(col->mtype == DATA_SYS); + ut_ad(col->prtype == (sys | DATA_NOT_NULL)); + + return(col); +} +#endif /* UNIV_DEBUG */ + +/********************************************************************//** +Gets the given system column number of a table. +@return column number */ +UNIV_INLINE +ulint +dict_table_get_sys_col_no( +/*======================*/ + const dict_table_t* table, /*!< in: table */ + ulint sys) /*!< in: DATA_ROW_ID, ... */ +{ + ut_ad(sys < DATA_N_SYS_COLS); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + return 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 +ibool +dict_table_is_comp( +/*===============*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table); + +#if DICT_TF_COMPACT != 1 +#error "DICT_TF_COMPACT must be 1" +#endif + + return(table->flags & DICT_TF_COMPACT); +} + +/************************************************************************ +Check if the table has an FTS index. */ +UNIV_INLINE +ibool +dict_table_has_fts_index( +/*=====================*/ + /* out: TRUE if table has an FTS index */ + dict_table_t* table) /* in: table */ +{ + return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS)); +} + +/** Validate the flags for tables that are not ROW_FORMAT=REDUNDANT. +@param[in] flags table flags +@return whether the flags are valid */ +inline +bool +dict_tf_is_valid_not_redundant(ulint flags) +{ + const bool atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags); + + ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags); + + if (!zip_ssize) { + /* Not ROW_FORMAT=COMPRESSED */ + } else if (!atomic_blobs) { + /* ROW_FORMAT=COMPRESSED implies ROW_FORMAT=DYNAMIC + for the uncompressed page format */ + return(false); + } else if (zip_ssize > PAGE_ZIP_SSIZE_MAX + || zip_ssize > UNIV_PAGE_SIZE_SHIFT + || UNIV_PAGE_SIZE_SHIFT > UNIV_ZIP_SIZE_SHIFT_MAX) { + /* KEY_BLOCK_SIZE is out of bounds, or + ROW_FORMAT=COMPRESSED is not supported with this + innodb_page_size (only up to 16KiB) */ + return(false); + } + + switch (DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags)) { + case 0: + /* PAGE_COMPRESSION_LEVEL=0 should imply PAGE_COMPRESSED=NO */ + return(!DICT_TF_GET_PAGE_COMPRESSION(flags)); + case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: + /* PAGE_COMPRESSION_LEVEL requires + ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC + (not ROW_FORMAT=COMPRESSED or ROW_FORMAT=REDUNDANT) + and PAGE_COMPRESSED=YES */ + return(!zip_ssize && DICT_TF_GET_PAGE_COMPRESSION(flags)); + default: + /* Invalid PAGE_COMPRESSION_LEVEL value */ + return(false); + } +} + +/** Validate the table flags. +@param[in] flags Table flags +@return true if valid. */ +UNIV_INLINE +bool +dict_tf_is_valid( + ulint flags) +{ + ut_ad(flags < 1U << DICT_TF_BITS); + /* The DATA_DIRECTORY flag can be assigned fully independently + of all other persistent table flags. */ + flags &= ~DICT_TF_MASK_DATA_DIR; + if (!(flags & 1)) { + /* Only ROW_FORMAT=REDUNDANT has 0 in the least significant + bit. For ROW_FORMAT=REDUNDANT, only the DATA_DIR flag + (which we cleared above) can be set. If any other flags + are set, the flags are invalid. */ + return(flags == 0); + } + + return(dict_tf_is_valid_not_redundant(flags)); +} + +/** Validate both table flags and table flags2 and make sure they +are compatible. +@param[in] flags Table flags +@param[in] flags2 Table flags2 +@return true if valid. */ +UNIV_INLINE +bool +dict_tf2_is_valid( + ulint flags, + ulint flags2) +{ + if (!dict_tf_is_valid(flags)) { + return(false); + } + + if ((flags2 & DICT_TF2_UNUSED_BIT_MASK) != 0) { + return(false); + } + + return(true); +} + +/********************************************************************//** +Determine the file format from dict_table_t::flags +The low order bit will be zero for REDUNDANT and 1 for COMPACT. For any +other row_format, file_format is > 0 and DICT_TF_COMPACT will also be set. +@return file format version */ +UNIV_INLINE +rec_format_t +dict_tf_get_rec_format( +/*===================*/ + ulint flags) /*!< in: dict_table_t::flags */ +{ + ut_a(dict_tf_is_valid(flags)); + + if (!DICT_TF_GET_COMPACT(flags)) { + return(REC_FORMAT_REDUNDANT); + } + + if (!DICT_TF_HAS_ATOMIC_BLOBS(flags)) { + return(REC_FORMAT_COMPACT); + } + + if (DICT_TF_GET_ZIP_SSIZE(flags)) { + return(REC_FORMAT_COMPRESSED); + } + + return(REC_FORMAT_DYNAMIC); +} + +/********************************************************************//** +Determine the file format from a dict_table_t::flags. +@return file format version */ +UNIV_INLINE +ulint +dict_tf_get_format( +/*===============*/ + ulint flags) /*!< in: dict_table_t::flags */ +{ + if (DICT_TF_HAS_ATOMIC_BLOBS(flags)) { + return(UNIV_FORMAT_B); + } + + return(UNIV_FORMAT_A); +} + +/********************************************************************//** +Determine the file format of a table. +@return file format version */ +UNIV_INLINE +ulint +dict_table_get_format( +/*==================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table); + + return(dict_tf_get_format(table->flags)); +} + +/** 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 +@param[in] zip_ssize Zip Shift Size +@param[in] use_data_dir Table uses DATA DIRECTORY +@param[in] page_compressed Table uses page compression +@param[in] page_compression_level Page compression level +@param[in] not_used For future */ +UNIV_INLINE +void +dict_tf_set( +/*========*/ + ulint* flags, + rec_format_t format, + ulint zip_ssize, + bool use_data_dir, + bool page_compressed, + ulint page_compression_level, + ulint not_used) +{ + *flags = use_data_dir ? 1 << DICT_TF_POS_DATA_DIR : 0; + + switch (format) { + case REC_FORMAT_REDUNDANT: + ut_ad(zip_ssize == 0); + /* no other options are allowed */ + ut_ad(!page_compressed); + return; + case REC_FORMAT_COMPACT: + *flags |= DICT_TF_COMPACT; + ut_ad(zip_ssize == 0); + break; + case REC_FORMAT_COMPRESSED: + *flags |= DICT_TF_COMPACT + | (1 << DICT_TF_POS_ATOMIC_BLOBS) + | (zip_ssize << DICT_TF_POS_ZIP_SSIZE); + break; + case REC_FORMAT_DYNAMIC: + *flags |= DICT_TF_COMPACT + | (1 << DICT_TF_POS_ATOMIC_BLOBS); + ut_ad(zip_ssize == 0); + break; + } + + if (page_compressed) { + *flags |= (1 << DICT_TF_POS_ATOMIC_BLOBS) + | (1 << DICT_TF_POS_PAGE_COMPRESSION) + | (page_compression_level << DICT_TF_POS_PAGE_COMPRESSION_LEVEL); + + ut_ad(zip_ssize == 0); + ut_ad(dict_tf_get_page_compression(*flags) == TRUE); + ut_ad(dict_tf_get_page_compression_level(*flags) == page_compression_level); + } +} + +/** Convert a 32 bit integer table flags to the 32 bit FSP Flags. +Fsp Flags are written into the tablespace header at the offset +FSP_SPACE_FLAGS and are also stored in the fil_space_t::flags field. +The following chart shows the translation of the low order bit. +Other bits are the same. +========================= Low order bit ========================== + | REDUNDANT | COMPACT | COMPRESSED | DYNAMIC +dict_table_t::flags | 0 | 1 | 1 | 1 +fil_space_t::flags | 0 | 0 | 1 | 1 +================================================================== +@param[in] table_flags dict_table_t::flags +@return tablespace flags (fil_space_t::flags) */ +UNIV_INLINE +ulint +dict_tf_to_fsp_flags(ulint table_flags) +{ + ulint fsp_flags; + ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL( + table_flags); + + ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0) + == (page_compression_level == 0)); + + 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; + + /* 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(); + + if (page_compression_level) { + fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION; + } + + ut_a(fsp_flags_is_valid(fsp_flags, false)); + + if (DICT_TF_HAS_DATA_DIR(table_flags)) { + fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; + } + + fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL; + + return(fsp_flags); +} + +/********************************************************************//** +Convert a 32 bit integer table flags to the 32bit integer that is written +to a SYS_TABLES.TYPE field. The following chart shows the translation of +the low order bit. Other bits are the same. +========================= Low order bit ========================== + | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC +dict_table_t::flags | 0 | 1 | 1 +SYS_TABLES.TYPE | 1 | 1 | 1 +================================================================== +@return ulint containing SYS_TABLES.TYPE */ +UNIV_INLINE +ulint +dict_tf_to_sys_tables_type( +/*=======================*/ + ulint flags) /*!< in: dict_table_t::flags */ +{ + ulint type; + + ut_a(dict_tf_is_valid(flags)); + + /* Adjust bit zero. It is always 1 in SYS_TABLES.TYPE */ + type = 1; + + /* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION, + PAGE_COMPRESSION_LEVEL are the same. */ + type |= flags & (DICT_TF_MASK_ZIP_SSIZE + | DICT_TF_MASK_ATOMIC_BLOBS + | DICT_TF_MASK_DATA_DIR + | DICT_TF_MASK_PAGE_COMPRESSION + | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL); + + 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, univ_page_size.logical(), true)); +} + +/** Get the table page size. +@param[in] table table +@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_table_page_size( + const dict_table_t* table) +{ + ut_ad(table != NULL); + + return(dict_tf_get_page_size(table->flags)); +} + +/*********************************************************************//** +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 */ +{ + ut_ad(mutex_own(&dict_sys->mutex)); + + dict_index_t* clust_index = dict_table_get_first_index(table); + + /* Loop through each index of the table and lock them */ + for (dict_index_t* index = dict_table_get_next_index(clust_index); + index != NULL; + index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); + } + + rw_lock_x_lock(dict_index_get_lock(clust_index)); +} + +/*********************************************************************//** +Returns true if the particular FTS index in the table is still syncing +in the background, false otherwise. +@param [in] table Table containing FTS index +@return True if sync of fts index is still going in the background */ +UNIV_INLINE +bool +dict_fts_index_syncing( + dict_table_t* table) +{ + dict_index_t* index; + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + if (index->index_fts_syncing) { + return(true); + } + } + 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, +including fields added by the dictionary system. +@return number of fields */ +UNIV_INLINE +ulint +dict_index_get_n_fields( +/*====================*/ + const dict_index_t* index) /*!< in: an internal + representation of index (in + the dictionary cache) */ +{ + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + return(index->n_fields); +} + +/********************************************************************//** +Gets the number of fields in the internal representation of an index +that uniquely determine the position of an index entry in the index, if +we do not take multiversioning into account: in the B-tree use the value +returned by dict_index_get_n_unique_in_tree. +@return number of fields */ +UNIV_INLINE +ulint +dict_index_get_n_unique( +/*====================*/ + const dict_index_t* index) /*!< in: an internal representation + of index (in the dictionary cache) */ +{ + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + ut_ad(index->cached); + return(index->n_uniq); +} + +/********************************************************************//** +Gets the number of fields in the internal representation of an index +which uniquely determine the position of an index entry in the index, if +we also take multiversioning into account. +@return number of fields */ +UNIV_INLINE +ulint +dict_index_get_n_unique_in_tree( +/*============================*/ + const dict_index_t* index) /*!< in: an internal representation + of index (in the dictionary cache) */ +{ + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + ut_ad(index->cached); + + if (dict_index_is_clust(index)) { + + return(dict_index_get_n_unique(index)); + } + + return(dict_index_get_n_fields(index)); +} + +/** +Gets the number of fields on nonleaf page level in the internal representation +of an index which uniquely determine the position of an index entry in the +index, if we also take multiversioning into account. Note, it doesn't +include page no field. +@param[in] index index +@return number of fields */ +UNIV_INLINE +ulint +dict_index_get_n_unique_in_tree_nonleaf( + const dict_index_t* index) +{ + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + ut_ad(index->cached); + + if (dict_index_is_spatial(index)) { + /* For spatial index, on non-leaf page, we have only + 2 fields(mbr+page_no). So, except page no field, + there's one field there. */ + return(DICT_INDEX_SPATIAL_NODEPTR_SIZE); + } else { + return(dict_index_get_n_unique_in_tree(index)); + } +} + +/********************************************************************//** +Gets the number of user-defined ordering fields in the index. In the internal +representation of clustered indexes we add the row id to the ordering fields +to make a clustered index unique, but this function returns the number of +fields the user defined in the index as ordering fields. +@return number of fields */ +UNIV_INLINE +ulint +dict_index_get_n_ordering_defined_by_user( +/*======================================*/ + const dict_index_t* index) /*!< in: an internal representation + of index (in the dictionary cache) */ +{ + return(index->n_user_defined_cols); +} + +#ifdef UNIV_DEBUG +/********************************************************************//** +Gets the nth field of an index. +@return pointer to field object */ +UNIV_INLINE +dict_field_t* +dict_index_get_nth_field( +/*=====================*/ + const dict_index_t* index, /*!< in: index */ + ulint pos) /*!< in: position of field */ +{ + ut_ad(pos < index->n_def); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + return((dict_field_t*) (index->fields) + pos); +} +#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 */ +UNIV_INLINE +const dict_col_t* +dict_field_get_col( +/*===============*/ + const dict_field_t* field) /*!< in: index field */ +{ + return(field->col); +} + +/********************************************************************//** +Gets pointer to the nth column in an index. +@return column */ +UNIV_INLINE +const dict_col_t* +dict_index_get_nth_col( +/*===================*/ + const dict_index_t* index, /*!< in: index */ + ulint pos) /*!< in: position of the field */ +{ + return(dict_field_get_col(dict_index_get_nth_field(index, pos))); +} + +/********************************************************************//** +Gets the column number the nth field in an index. +@return column number */ +UNIV_INLINE +ulint +dict_index_get_nth_col_no( +/*======================*/ + const dict_index_t* index, /*!< in: index */ + ulint pos) /*!< in: position of the field */ +{ + return(dict_col_get_no(dict_index_get_nth_col(index, pos))); +} + +/********************************************************************//** +Looks for column n in an index. +@return position in internal representation of the index; +ULINT_UNDEFINED if not contained */ +UNIV_INLINE +ulint +dict_index_get_nth_col_pos( +/*=======================*/ + const dict_index_t* index, /*!< in: index */ + ulint n, /*!< in: column number */ + ulint* prefix_col_pos) /*!< out: col num if prefix */ +{ + return(dict_index_get_nth_col_or_prefix_pos(index, n, false, false, + prefix_col_pos)); +} + +/********************************************************************//** +Returns the minimum data size of an index record. +@return minimum data size in bytes */ +UNIV_INLINE +ulint +dict_index_get_min_size( +/*====================*/ + const dict_index_t* index) /*!< in: index */ +{ + ulint n = dict_index_get_n_fields(index); + ulint size = 0; + + while (n--) { + size += dict_col_get_min_size(dict_index_get_nth_col(index, + n)); + } + + return(size); +} + +/*********************************************************************//** +Gets the space id of the root of the index tree. +@return space id */ +UNIV_INLINE +ulint +dict_index_get_space( +/*=================*/ + const dict_index_t* index) /*!< in: index */ +{ + ut_ad(index); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + return(index->space); +} + +/*********************************************************************//** +Sets the space id of the root of the index tree. */ +UNIV_INLINE +void +dict_index_set_space( +/*=================*/ + dict_index_t* index, /*!< in/out: index */ + ulint space) /*!< in: space id */ +{ + ut_ad(index); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + index->space = unsigned(space); +} + +/*********************************************************************//** +Gets the page number of the root of the index tree. +@return page number */ +UNIV_INLINE +ulint +dict_index_get_page( +/*================*/ + const dict_index_t* index) /*!< in: index */ +{ + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + return(index->page); +} + +/*********************************************************************//** +Gets the read-write lock of the index tree. +@return read-write lock */ +UNIV_INLINE +rw_lock_t* +dict_index_get_lock( +/*================*/ + const dict_index_t* index) /*!< in: index */ +{ + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + return(&(index->lock)); +} + +/********************************************************************//** +Returns free space reserved for future updates of records. This is +relevant only in the case of many consecutive inserts, as updates +which make the records bigger might fragment the index. +@return number of free bytes on page, reserved for updates */ +UNIV_INLINE +ulint +dict_index_get_space_reserve(void) +/*==============================*/ +{ + return(UNIV_PAGE_SIZE / 16); +} + +/********************************************************************//** +Gets the status of online index creation. +@return the status */ +UNIV_INLINE +enum online_index_status +dict_index_get_online_status( +/*=========================*/ + const dict_index_t* index) /*!< in: secondary index */ +{ + enum online_index_status status; + + status = (enum online_index_status) index->online_status; + + /* Without the index->lock protection, the online + status can change from ONLINE_INDEX_CREATION to + ONLINE_INDEX_COMPLETE (or ONLINE_INDEX_ABORTED) in + row_log_apply() once log application is done. So to make + sure the status is ONLINE_INDEX_CREATION or ONLINE_INDEX_COMPLETE + you should always do the recheck after acquiring index->lock */ + +#ifdef UNIV_DEBUG + switch (status) { + case ONLINE_INDEX_COMPLETE: + case ONLINE_INDEX_CREATION: + case ONLINE_INDEX_ABORTED: + case ONLINE_INDEX_ABORTED_DROPPED: + return(status); + } + ut_error; +#endif /* UNIV_DEBUG */ + return(status); +} + +/********************************************************************//** +Sets the status of online index creation. */ +UNIV_INLINE +void +dict_index_set_online_status( +/*=========================*/ + dict_index_t* index, /*!< in/out: index */ + enum online_index_status status) /*!< in: status */ +{ + ut_ad(!(index->type & DICT_FTS)); + ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X)); + +#ifdef UNIV_DEBUG + switch (dict_index_get_online_status(index)) { + case ONLINE_INDEX_COMPLETE: + case ONLINE_INDEX_CREATION: + break; + case ONLINE_INDEX_ABORTED: + ut_ad(status == ONLINE_INDEX_ABORTED_DROPPED); + break; + case ONLINE_INDEX_ABORTED_DROPPED: + ut_error; + } +#endif /* UNIV_DEBUG */ + + index->online_status = status; + ut_ad(dict_index_get_online_status(index) == status); +} + +/********************************************************************//** +Determines if a secondary index is being or has been created online, +or if the table is being rebuilt online, allowing concurrent modifications +to the table. +@retval true if the index is being or has been built online, or +if this is a clustered index and the table is being or has been rebuilt online +@retval false if the index has been created or the table has been +rebuilt completely */ +UNIV_INLINE +bool +dict_index_is_online_ddl( +/*=====================*/ + const dict_index_t* index) /*!< in: index */ +{ +#ifdef UNIV_DEBUG + if (dict_index_is_clust(index)) { + switch (dict_index_get_online_status(index)) { + case ONLINE_INDEX_CREATION: + return(true); + case ONLINE_INDEX_COMPLETE: + return(false); + case ONLINE_INDEX_ABORTED: + case ONLINE_INDEX_ABORTED_DROPPED: + break; + } + ut_ad(0); + return(false); + } +#endif /* UNIV_DEBUG */ + + return(UNIV_UNLIKELY(dict_index_get_online_status(index) + != ONLINE_INDEX_COMPLETE)); +} + +/**********************************************************************//** +Check whether a column exists in an FTS index. +@return ULINT_UNDEFINED if no match else the offset within the vector */ +UNIV_INLINE +ulint +dict_table_is_fts_column( +/*=====================*/ + ib_vector_t* indexes,/*!< in: vector containing only FTS indexes */ + ulint col_no, /*!< in: col number to search for */ + bool is_virtual) /*!< in: whether it is a virtual column */ + +{ + ulint i; + + for (i = 0; i < ib_vector_size(indexes); ++i) { + dict_index_t* index; + + index = (dict_index_t*) ib_vector_getp(indexes, i); + + if (dict_index_contains_col_or_prefix( + index, col_no, is_virtual)) { + + return(i); + } + } + + return(ULINT_UNDEFINED); +} + +/**********************************************************************//** +Determine bytes of column prefix to be stored in the undo log. Please +note if the table format is UNIV_FORMAT_A (< UNIV_FORMAT_B), no prefix +needs to be stored in the undo log. +@return bytes of column prefix to be stored in the undo log */ +UNIV_INLINE +ulint +dict_max_field_len_store_undo( +/*==========================*/ + dict_table_t* table, /*!< in: table */ + const dict_col_t* col) /*!< in: column which index prefix + is based on */ +{ + ulint prefix_len = 0; + + if (dict_table_get_format(table) >= UNIV_FORMAT_B) + { + prefix_len = col->max_prefix + ? col->max_prefix + : DICT_MAX_FIELD_LEN_BY_FORMAT(table); + } + + return(prefix_len); +} + +/** Determine maximum bytes of a virtual column need to be stored +in the undo log. +@param[in] table dict_table_t for the table +@param[in] col_no virtual column number +@return maximum bytes of virtual column to be stored in the undo log */ +UNIV_INLINE +ulint +dict_max_v_field_len_store_undo( + dict_table_t* table, + ulint col_no) +{ + const dict_col_t* col + = &dict_table_get_nth_v_col(table, col_no)->m_col; + ulint max_log_len; + + /* This calculation conforms to the non-virtual column + maximum log length calculation: + 1) for UNIV_FORMAT_A, upto REC_ANTELOPE_MAX_INDEX_COL_LEN + for UNIV_FORMAT_B, upto col->max_prefix or + 2) REC_VERSION_56_MAX_INDEX_COL_LEN, whichever is less */ + if (dict_table_get_format(table) >= UNIV_FORMAT_B) { + if (DATA_BIG_COL(col) && col->max_prefix > 0) { + max_log_len = col->max_prefix; + } else { + max_log_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table); + } + } else { + max_log_len = REC_ANTELOPE_MAX_INDEX_COL_LEN; + } + + 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 */ +UNIV_INLINE +ulint +dict_table_is_corrupted( +/*====================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + return(table->corrupted); +} + +/********************************************************************//** +Check if the tablespace for the table has been discarded. +@return true if the tablespace has been discarded. */ +UNIV_INLINE +bool +dict_table_is_discarded( +/*====================*/ + const dict_table_t* table) /*!< in: table to check */ +{ + return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_DISCARDED)); +} + +/** Check if the table is found is a file_per_table tablespace. +This test does not use table flags2 since some REDUNDANT tables in the +system tablespace may have garbage in the MIX_LEN field where flags2 is +stored. These garbage MIX_LEN fields were written before v3.23.52. +A patch was added to v3.23.52 which initializes the MIX_LEN field to 0. +Since file-per-table tablespaces were added in 4.1, any SYS_TABLES +record with a non-zero space ID will have a reliable MIX_LEN field. +However, this test does not use flags2 from SYS_TABLES.MIX_LEN. Instead, +assume that if the tablespace is not a predefined system tablespace, + then it must be file-per-table. +Also, during ALTER TABLE, the DICT_TF2_USE_FILE_PER_TABLE flag may not be +set on one of the file-per-table tablespaces. +This test cannot be done on a table in the process of being created +because the space_id will be zero until the tablespace is created. +@param[in] table An existing open table to check +@return true if this table was created as a file-per-table tablespace. */ +UNIV_INLINE +bool +dict_table_is_file_per_table( + const dict_table_t* table) /*!< in: table to check */ +{ + return !is_system_tablespace(table->space); +} + +/** Acquire the table handle. */ +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); +} + +/** Release the table handle. +@return whether the last handle was released */ +inline +bool +dict_table_t::release() +{ + int32 n = my_atomic_add32_explicit( + &n_ref_count, -1, MY_MEMORY_ORDER_RELAXED); + ut_ad(n > 0); + return n == 1; +} + +/** Encode the number of columns and number of virtual columns in a +4 bytes value. We could do this because the number of columns in +InnoDB is limited to 1017 +@param[in] n_col number of non-virtual column +@param[in] n_v_col number of virtual column +@return encoded value */ +UNIV_INLINE +ulint +dict_table_encode_n_col( + ulint n_col, + ulint n_v_col) +{ + return(n_col + (n_v_col<<16)); +} + +/** decode number of virtual and non-virtual columns in one 4 bytes value. +@param[in] encoded encoded value +@param[in,out] n_col number of non-virtual column +@param[in,out] n_v_col number of virtual column */ +UNIV_INLINE +void +dict_table_decode_n_col( + ulint encoded, + ulint* n_col, + ulint* n_v_col) +{ + + ulint num = encoded & ~DICT_N_COLS_COMPACT; + *n_v_col = num >> 16; + *n_col = num & 0xFFFF; +} + +/** Free the virtual column template +@param[in,out] vc_templ virtual column template */ +void +dict_free_vc_templ( + dict_vcol_templ_t* vc_templ) +{ + UT_DELETE_ARRAY(vc_templ->default_rec); + vc_templ->default_rec = NULL; + + if (vc_templ->vtempl != NULL) { + ut_ad(vc_templ->n_v_col > 0); + for (ulint i = 0; i < vc_templ->n_col + + vc_templ->n_v_col; i++) { + if (vc_templ->vtempl[i] != NULL) { + ut_free(vc_templ->vtempl[i]); + } + } + ut_free(vc_templ->vtempl); + vc_templ->vtempl = NULL; + } +} + +/** Check whether the table have virtual index. +@param[in] table InnoDB table +@return true if the table have virtual index, false otherwise. */ +UNIV_INLINE +bool +dict_table_have_virtual_index( + dict_table_t* table) +{ + for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(table); + col_no++) { + const dict_v_col_t* col + = dict_table_get_nth_v_col(table, col_no); + + if (col->m_col.ord_part) { + return(true); + } + } + + return(false); +} diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 5fc0e3ebe15..95afa7c2cc9 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2042,6 +2042,6 @@ inline void dict_stats_empty_defrag_stats(dict_index_t* index) index->stat_defrag_n_page_split = 0; } -#include "dict0mem.ic" +#include "dict0mem.inl" #endif /* dict0mem_h */ diff --git a/storage/innobase/include/dict0mem.ic b/storage/innobase/include/dict0mem.ic deleted file mode 100644 index d63f15ef7f3..00000000000 --- a/storage/innobase/include/dict0mem.ic +++ /dev/null @@ -1,78 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 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/dict0mem.ic -Data dictionary memory object creation - -Created 1/8/1996 Heikki Tuuri -***********************************************************************/ - -#include "data0type.h" -#include "dict0mem.h" -#include "fil0fil.h" - -/**********************************************************************//** -This function poplulates a dict_index_t index memory structure with -supplied information. */ -UNIV_INLINE -void -dict_mem_fill_index_struct( -/*=======================*/ - dict_index_t* index, /*!< out: index to be filled */ - mem_heap_t* heap, /*!< in: memory heap */ - const char* table_name, /*!< in: table name */ - const char* index_name, /*!< in: index name */ - ulint space, /*!< in: space where the index tree is - placed, ignored if the index is of - the clustered type */ - ulint type, /*!< in: DICT_UNIQUE, - DICT_CLUSTERED, ... ORed */ - ulint n_fields) /*!< in: number of fields */ -{ - - if (heap) { - index->heap = heap; - index->name = mem_heap_strdup(heap, index_name); - index->fields = (dict_field_t*) mem_heap_alloc( - heap, 1 + n_fields * sizeof(dict_field_t)); - } else { - index->name = index_name; - index->heap = NULL; - index->fields = NULL; - } - - /* Assign a ulint to a 4-bit-mapped field. - Only the low-order 4 bits are assigned. */ - index->type = unsigned(type); - index->space = (unsigned int) space; - index->page = FIL_NULL; - index->merge_threshold = DICT_INDEX_MERGE_THRESHOLD_DEFAULT; - index->table_name = table_name; - index->n_fields = (unsigned int) n_fields; - /* The '1 +' above prevents allocation - of an empty mem block */ - index->nulls_equal = false; -#ifdef BTR_CUR_HASH_ADAPT -#ifdef MYSQL_INDEX_DISABLE_AHI - index->disable_ahi = false; -#endif -#endif /* BTR_CUR_HASH_ADAPT */ - ut_d(index->magic_n = DICT_INDEX_MAGIC_N); -} diff --git a/storage/innobase/include/dict0mem.inl b/storage/innobase/include/dict0mem.inl new file mode 100644 index 00000000000..d63f15ef7f3 --- /dev/null +++ b/storage/innobase/include/dict0mem.inl @@ -0,0 +1,78 @@ +/***************************************************************************** + +Copyright (c) 1996, 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/dict0mem.ic +Data dictionary memory object creation + +Created 1/8/1996 Heikki Tuuri +***********************************************************************/ + +#include "data0type.h" +#include "dict0mem.h" +#include "fil0fil.h" + +/**********************************************************************//** +This function poplulates a dict_index_t index memory structure with +supplied information. */ +UNIV_INLINE +void +dict_mem_fill_index_struct( +/*=======================*/ + dict_index_t* index, /*!< out: index to be filled */ + mem_heap_t* heap, /*!< in: memory heap */ + const char* table_name, /*!< in: table name */ + const char* index_name, /*!< in: index name */ + ulint space, /*!< in: space where the index tree is + placed, ignored if the index is of + the clustered type */ + ulint type, /*!< in: DICT_UNIQUE, + DICT_CLUSTERED, ... ORed */ + ulint n_fields) /*!< in: number of fields */ +{ + + if (heap) { + index->heap = heap; + index->name = mem_heap_strdup(heap, index_name); + index->fields = (dict_field_t*) mem_heap_alloc( + heap, 1 + n_fields * sizeof(dict_field_t)); + } else { + index->name = index_name; + index->heap = NULL; + index->fields = NULL; + } + + /* Assign a ulint to a 4-bit-mapped field. + Only the low-order 4 bits are assigned. */ + index->type = unsigned(type); + index->space = (unsigned int) space; + index->page = FIL_NULL; + index->merge_threshold = DICT_INDEX_MERGE_THRESHOLD_DEFAULT; + index->table_name = table_name; + index->n_fields = (unsigned int) n_fields; + /* The '1 +' above prevents allocation + of an empty mem block */ + index->nulls_equal = false; +#ifdef BTR_CUR_HASH_ADAPT +#ifdef MYSQL_INDEX_DISABLE_AHI + index->disable_ahi = false; +#endif +#endif /* BTR_CUR_HASH_ADAPT */ + ut_d(index->magic_n = DICT_INDEX_MAGIC_N); +} diff --git a/storage/innobase/include/dict0pagecompress.h b/storage/innobase/include/dict0pagecompress.h index dfa6f2a244d..f1272dc447d 100644 --- a/storage/innobase/include/dict0pagecompress.h +++ b/storage/innobase/include/dict0pagecompress.h @@ -56,6 +56,6 @@ dict_table_page_compression_level( const dict_table_t* table) /*!< in: table */ __attribute__((const)); -#include "dict0pagecompress.ic" +#include "dict0pagecompress.inl" #endif diff --git a/storage/innobase/include/dict0pagecompress.ic b/storage/innobase/include/dict0pagecompress.ic deleted file mode 100644 index c959f9cada2..00000000000 --- a/storage/innobase/include/dict0pagecompress.ic +++ /dev/null @@ -1,81 +0,0 @@ -/***************************************************************************** - -Copyright (C) 2013, 2017, MariaDB Corporation. 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 St, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/******************************************************************//** -@file include/dict0pagecompress.ic -Inline implementation for helper functions for extracting/storing -page compression and atomic writes information to dictionary. - -Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com -***********************************************************************/ - -/********************************************************************//** -Extract the page compression level from dict_table_t::flags. -These flags are in memory, so assert that they are valid. -@return page compression level, or 0 if not compressed */ -UNIV_INLINE -ulint -dict_tf_get_page_compression_level( -/*===============================*/ - ulint flags) /*!< in: flags */ -{ - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags); - - ut_ad(page_compression_level <= 9); - - return(page_compression_level); -} - -/********************************************************************//** -Check whether the table uses the page compression page format. -@return page compression level, or 0 if not compressed */ -UNIV_INLINE -ulint -dict_table_page_compression_level( -/*==============================*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table); - ut_ad(dict_tf_get_page_compression(table->flags)); - - return(dict_tf_get_page_compression_level(table->flags)); -} - -/********************************************************************//** -Check whether the table uses the page compression page format. -@return true if page compressed, false if not */ -UNIV_INLINE -ibool -dict_tf_get_page_compression( -/*=========================*/ - ulint flags) /*!< in: flags */ -{ - return(DICT_TF_GET_PAGE_COMPRESSION(flags)); -} - -/********************************************************************//** -Check whether the table uses the page compression page format. -@return true if page compressed, false if not */ -UNIV_INLINE -ibool -dict_table_is_page_compressed( -/*==========================*/ - const dict_table_t* table) /*!< in: table */ -{ - return (dict_tf_get_page_compression(table->flags)); -} diff --git a/storage/innobase/include/dict0pagecompress.inl b/storage/innobase/include/dict0pagecompress.inl new file mode 100644 index 00000000000..c959f9cada2 --- /dev/null +++ b/storage/innobase/include/dict0pagecompress.inl @@ -0,0 +1,81 @@ +/***************************************************************************** + +Copyright (C) 2013, 2017, MariaDB Corporation. 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 St, Fifth Floor, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/******************************************************************//** +@file include/dict0pagecompress.ic +Inline implementation for helper functions for extracting/storing +page compression and atomic writes information to dictionary. + +Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com +***********************************************************************/ + +/********************************************************************//** +Extract the page compression level from dict_table_t::flags. +These flags are in memory, so assert that they are valid. +@return page compression level, or 0 if not compressed */ +UNIV_INLINE +ulint +dict_tf_get_page_compression_level( +/*===============================*/ + ulint flags) /*!< in: flags */ +{ + ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags); + + ut_ad(page_compression_level <= 9); + + return(page_compression_level); +} + +/********************************************************************//** +Check whether the table uses the page compression page format. +@return page compression level, or 0 if not compressed */ +UNIV_INLINE +ulint +dict_table_page_compression_level( +/*==============================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table); + ut_ad(dict_tf_get_page_compression(table->flags)); + + return(dict_tf_get_page_compression_level(table->flags)); +} + +/********************************************************************//** +Check whether the table uses the page compression page format. +@return true if page compressed, false if not */ +UNIV_INLINE +ibool +dict_tf_get_page_compression( +/*=========================*/ + ulint flags) /*!< in: flags */ +{ + return(DICT_TF_GET_PAGE_COMPRESSION(flags)); +} + +/********************************************************************//** +Check whether the table uses the page compression page format. +@return true if page compressed, false if not */ +UNIV_INLINE +ibool +dict_table_is_page_compressed( +/*==========================*/ + const dict_table_t* table) /*!< in: table */ +{ + return (dict_tf_get_page_compression(table->flags)); +} diff --git a/storage/innobase/include/dict0priv.h b/storage/innobase/include/dict0priv.h index e56848d1954..bcdd614b02d 100644 --- a/storage/innobase/include/dict0priv.h +++ b/storage/innobase/include/dict0priv.h @@ -57,6 +57,6 @@ dict_table_open_on_id_low( when loading the table */ ibool open_only_if_in_cache); -#include "dict0priv.ic" +#include "dict0priv.inl" #endif /* dict0priv.h */ diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic deleted file mode 100644 index 7b584c7e1cb..00000000000 --- a/storage/innobase/include/dict0priv.ic +++ /dev/null @@ -1,126 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2010, 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/dict0priv.ic -Data dictionary system private include file - -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 -function. -@return table, NULL if not found */ -UNIV_INLINE -dict_table_t* -dict_table_get_low( -/*===============*/ - const char* table_name) /*!< in: table name */ -{ - dict_table_t* table; - - ut_ad(table_name); - ut_ad(mutex_own(&dict_sys->mutex)); - - table = dict_table_check_if_in_cache_low(table_name); - - if (table && table->corrupted) { - ib::error error; - error << "Table " << table->name << "is corrupted"; - if (srv_load_corrupted) { - error << ", but innodb_force_load_corrupted is set"; - } else { - return(NULL); - } - } - - if (table == NULL) { - table = dict_load_table(table_name, DICT_ERR_IGNORE_NONE); - } - - ut_ad(!table || table->cached); - - return(table); -} - -/**********************************************************************//** -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 -dict_table_t* -dict_table_check_if_in_cache_low( -/*=============================*/ - const char* table_name) /*!< in: table name */ -{ - dict_table_t* table; - ulint table_fold; - - DBUG_ENTER("dict_table_check_if_in_cache_low"); - DBUG_PRINT("dict_table_check_if_in_cache_low", - ("table: '%s'", table_name)); - - ut_ad(table_name); - 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, - dict_table_t*, table, ut_ad(table->cached), - !strcmp(table->name.m_name, table_name)); - DBUG_RETURN(table); -} diff --git a/storage/innobase/include/dict0priv.inl b/storage/innobase/include/dict0priv.inl new file mode 100644 index 00000000000..7b584c7e1cb --- /dev/null +++ b/storage/innobase/include/dict0priv.inl @@ -0,0 +1,126 @@ +/***************************************************************************** + +Copyright (c) 2010, 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/dict0priv.ic +Data dictionary system private include file + +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 +function. +@return table, NULL if not found */ +UNIV_INLINE +dict_table_t* +dict_table_get_low( +/*===============*/ + const char* table_name) /*!< in: table name */ +{ + dict_table_t* table; + + ut_ad(table_name); + ut_ad(mutex_own(&dict_sys->mutex)); + + table = dict_table_check_if_in_cache_low(table_name); + + if (table && table->corrupted) { + ib::error error; + error << "Table " << table->name << "is corrupted"; + if (srv_load_corrupted) { + error << ", but innodb_force_load_corrupted is set"; + } else { + return(NULL); + } + } + + if (table == NULL) { + table = dict_load_table(table_name, DICT_ERR_IGNORE_NONE); + } + + ut_ad(!table || table->cached); + + return(table); +} + +/**********************************************************************//** +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 +dict_table_t* +dict_table_check_if_in_cache_low( +/*=============================*/ + const char* table_name) /*!< in: table name */ +{ + dict_table_t* table; + ulint table_fold; + + DBUG_ENTER("dict_table_check_if_in_cache_low"); + DBUG_PRINT("dict_table_check_if_in_cache_low", + ("table: '%s'", table_name)); + + ut_ad(table_name); + 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, + 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 00ac6eb4745..639c4043f02 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -221,7 +221,7 @@ dberr_t dict_stats_report_error(dict_table_t* table, bool defragment = false) MY_ATTRIBUTE((nonnull, warn_unused_result)); -#include "dict0stats.ic" +#include "dict0stats.inl" #ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS void test_dict_stats_all(); diff --git a/storage/innobase/include/dict0stats.ic b/storage/innobase/include/dict0stats.ic deleted file mode 100644 index c467ee1f3ac..00000000000 --- a/storage/innobase/include/dict0stats.ic +++ /dev/null @@ -1,221 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. -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 -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/dict0stats.ic -Code used for calculating and manipulating table statistics. - -Created Jan 23, 2012 Vasil Dimov -*******************************************************/ - -#include "dict0dict.h" -#include "srv0srv.h" - -/*********************************************************************//** -Set the persistent statistics flag for a given table. This is set only -in the in-memory table object and is not saved on disk. It will be read -from the .frm file upon first open from MySQL after a server restart. */ -UNIV_INLINE -void -dict_stats_set_persistent( -/*======================*/ - dict_table_t* table, /*!< in/out: table */ - ibool ps_on, /*!< in: persistent stats explicitly enabled */ - ibool ps_off) /*!< in: persistent stats explicitly disabled */ -{ - /* Not allowed to have both flags set, but a CREATE or ALTER - statement that contains "STATS_PERSISTENT=0 STATS_PERSISTENT=1" would - end up having both set. In this case we clear the OFF flag. */ - if (ps_on && ps_off) { - ps_off = FALSE; - } - - ib_uint32_t stat_persistent = 0; - - if (ps_on) { - stat_persistent |= DICT_STATS_PERSISTENT_ON; - } - - if (ps_off) { - stat_persistent |= DICT_STATS_PERSISTENT_OFF; - } - - /* we rely on this assignment to be atomic */ - table->stat_persistent = stat_persistent; -} - -/** @return whether persistent statistics is enabled for a given table */ -UNIV_INLINE -bool -dict_stats_is_persistent_enabled(const dict_table_t* table) -{ - /* Because of the nature of this check (non-locking) it is possible - that a table becomes: - * PS-disabled immediately after this function has returned TRUE or - * PS-enabled immediately after this function has returned FALSE. - This means that it is possible that we do: - + dict_stats_update(DICT_STATS_RECALC_PERSISTENT) on a table that has - just been PS-disabled or - + 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_sys->mutex like the - other ::stat_ members which would be too big performance penalty, - especially when this function is called from - dict_stats_update_if_needed(). */ - - /* we rely on this read to be atomic */ - ib_uint32_t stat_persistent = table->stat_persistent; - - if (stat_persistent & DICT_STATS_PERSISTENT_ON) { - ut_ad(!(stat_persistent & DICT_STATS_PERSISTENT_OFF)); - return(true); - } else if (stat_persistent & DICT_STATS_PERSISTENT_OFF) { - return(false); - } else { - return(srv_stats_persistent); - } -} - -/*********************************************************************//** -Set the auto recalc flag for a given table (only honored for a persistent -stats enabled table). The flag is set only in the in-memory table object -and is not saved in InnoDB files. It will be read from the .frm file upon -first open from MySQL after a server restart. */ -UNIV_INLINE -void -dict_stats_auto_recalc_set( -/*=======================*/ - dict_table_t* table, /*!< in/out: table */ - ibool auto_recalc_on, /*!< in: explicitly enabled */ - ibool auto_recalc_off) /*!< in: explicitly disabled */ -{ - ut_ad(!auto_recalc_on || !auto_recalc_off); - - ib_uint32_t stats_auto_recalc = 0; - - if (auto_recalc_on) { - stats_auto_recalc |= DICT_STATS_AUTO_RECALC_ON; - } - - if (auto_recalc_off) { - stats_auto_recalc |= DICT_STATS_AUTO_RECALC_OFF; - } - - /* we rely on this assignment to be atomic */ - table->stats_auto_recalc = stats_auto_recalc; -} - -/** @return whether auto recalc is enabled for a given table*/ -UNIV_INLINE -bool -dict_stats_auto_recalc_is_enabled(const dict_table_t* table) -{ - /* we rely on this read to be atomic */ - ib_uint32_t stats_auto_recalc = table->stats_auto_recalc; - - if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_ON) { - ut_ad(!(stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF)); - return(true); - } else if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF) { - return(false); - } else { - return(srv_stats_auto_recalc); - } -} - -/*********************************************************************//** -Initialize table's stats for the first time when opening a table. */ -UNIV_INLINE -void -dict_stats_init( -/*============*/ - dict_table_t* table) /*!< in/out: table */ -{ - ut_ad(!mutex_own(&dict_sys->mutex)); - - if (table->stat_initialized) { - return; - } - - dict_stats_upd_option_t opt; - - if (dict_stats_is_persistent_enabled(table)) { - opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY; - } else { - opt = DICT_STATS_RECALC_TRANSIENT; - } - - dict_stats_update(table, opt); -} - -/*********************************************************************//** -Deinitialize table's stats after the last close of the table. This is -used to detect "FLUSH TABLE" and refresh the stats upon next open. */ -UNIV_INLINE -void -dict_stats_deinit( -/*==============*/ - dict_table_t* table) /*!< in/out: table */ -{ - ut_ad(mutex_own(&dict_sys->mutex)); - - ut_a(table->get_ref_count() == 0); - - if (!table->stat_initialized) { - return; - } - - table->stat_initialized = FALSE; - -#ifdef HAVE_valgrind_or_MSAN - MEM_UNDEFINED(&table->stat_n_rows, sizeof table->stat_n_rows); - MEM_UNDEFINED(&table->stat_clustered_index_size, - sizeof table->stat_clustered_index_size); - MEM_UNDEFINED(&table->stat_sum_of_other_index_sizes, - sizeof table->stat_sum_of_other_index_sizes); - MEM_UNDEFINED(&table->stat_modified_counter, - sizeof table->stat_modified_counter); - - dict_index_t* index; - - for (index = dict_table_get_first_index(table); - index != NULL; - index = dict_table_get_next_index(index)) { - MEM_UNDEFINED( - index->stat_n_diff_key_vals, - index->n_uniq - * sizeof(index->stat_n_diff_key_vals[0])); - MEM_UNDEFINED( - index->stat_n_sample_sizes, - index->n_uniq - * sizeof(index->stat_n_sample_sizes[0])); - MEM_UNDEFINED( - index->stat_n_non_null_key_vals, - index->n_uniq - * sizeof(index->stat_n_non_null_key_vals[0])); - MEM_UNDEFINED( - &index->stat_index_size, - sizeof(index->stat_index_size)); - MEM_UNDEFINED( - &index->stat_n_leaf_pages, - sizeof(index->stat_n_leaf_pages)); - } -#endif /* HAVE_valgrind_or_MSAN */ -} diff --git a/storage/innobase/include/dict0stats.inl b/storage/innobase/include/dict0stats.inl new file mode 100644 index 00000000000..c467ee1f3ac --- /dev/null +++ b/storage/innobase/include/dict0stats.inl @@ -0,0 +1,221 @@ +/***************************************************************************** + +Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. +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 +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/dict0stats.ic +Code used for calculating and manipulating table statistics. + +Created Jan 23, 2012 Vasil Dimov +*******************************************************/ + +#include "dict0dict.h" +#include "srv0srv.h" + +/*********************************************************************//** +Set the persistent statistics flag for a given table. This is set only +in the in-memory table object and is not saved on disk. It will be read +from the .frm file upon first open from MySQL after a server restart. */ +UNIV_INLINE +void +dict_stats_set_persistent( +/*======================*/ + dict_table_t* table, /*!< in/out: table */ + ibool ps_on, /*!< in: persistent stats explicitly enabled */ + ibool ps_off) /*!< in: persistent stats explicitly disabled */ +{ + /* Not allowed to have both flags set, but a CREATE or ALTER + statement that contains "STATS_PERSISTENT=0 STATS_PERSISTENT=1" would + end up having both set. In this case we clear the OFF flag. */ + if (ps_on && ps_off) { + ps_off = FALSE; + } + + ib_uint32_t stat_persistent = 0; + + if (ps_on) { + stat_persistent |= DICT_STATS_PERSISTENT_ON; + } + + if (ps_off) { + stat_persistent |= DICT_STATS_PERSISTENT_OFF; + } + + /* we rely on this assignment to be atomic */ + table->stat_persistent = stat_persistent; +} + +/** @return whether persistent statistics is enabled for a given table */ +UNIV_INLINE +bool +dict_stats_is_persistent_enabled(const dict_table_t* table) +{ + /* Because of the nature of this check (non-locking) it is possible + that a table becomes: + * PS-disabled immediately after this function has returned TRUE or + * PS-enabled immediately after this function has returned FALSE. + This means that it is possible that we do: + + dict_stats_update(DICT_STATS_RECALC_PERSISTENT) on a table that has + just been PS-disabled or + + 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_sys->mutex like the + other ::stat_ members which would be too big performance penalty, + especially when this function is called from + dict_stats_update_if_needed(). */ + + /* we rely on this read to be atomic */ + ib_uint32_t stat_persistent = table->stat_persistent; + + if (stat_persistent & DICT_STATS_PERSISTENT_ON) { + ut_ad(!(stat_persistent & DICT_STATS_PERSISTENT_OFF)); + return(true); + } else if (stat_persistent & DICT_STATS_PERSISTENT_OFF) { + return(false); + } else { + return(srv_stats_persistent); + } +} + +/*********************************************************************//** +Set the auto recalc flag for a given table (only honored for a persistent +stats enabled table). The flag is set only in the in-memory table object +and is not saved in InnoDB files. It will be read from the .frm file upon +first open from MySQL after a server restart. */ +UNIV_INLINE +void +dict_stats_auto_recalc_set( +/*=======================*/ + dict_table_t* table, /*!< in/out: table */ + ibool auto_recalc_on, /*!< in: explicitly enabled */ + ibool auto_recalc_off) /*!< in: explicitly disabled */ +{ + ut_ad(!auto_recalc_on || !auto_recalc_off); + + ib_uint32_t stats_auto_recalc = 0; + + if (auto_recalc_on) { + stats_auto_recalc |= DICT_STATS_AUTO_RECALC_ON; + } + + if (auto_recalc_off) { + stats_auto_recalc |= DICT_STATS_AUTO_RECALC_OFF; + } + + /* we rely on this assignment to be atomic */ + table->stats_auto_recalc = stats_auto_recalc; +} + +/** @return whether auto recalc is enabled for a given table*/ +UNIV_INLINE +bool +dict_stats_auto_recalc_is_enabled(const dict_table_t* table) +{ + /* we rely on this read to be atomic */ + ib_uint32_t stats_auto_recalc = table->stats_auto_recalc; + + if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_ON) { + ut_ad(!(stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF)); + return(true); + } else if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF) { + return(false); + } else { + return(srv_stats_auto_recalc); + } +} + +/*********************************************************************//** +Initialize table's stats for the first time when opening a table. */ +UNIV_INLINE +void +dict_stats_init( +/*============*/ + dict_table_t* table) /*!< in/out: table */ +{ + ut_ad(!mutex_own(&dict_sys->mutex)); + + if (table->stat_initialized) { + return; + } + + dict_stats_upd_option_t opt; + + if (dict_stats_is_persistent_enabled(table)) { + opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY; + } else { + opt = DICT_STATS_RECALC_TRANSIENT; + } + + dict_stats_update(table, opt); +} + +/*********************************************************************//** +Deinitialize table's stats after the last close of the table. This is +used to detect "FLUSH TABLE" and refresh the stats upon next open. */ +UNIV_INLINE +void +dict_stats_deinit( +/*==============*/ + dict_table_t* table) /*!< in/out: table */ +{ + ut_ad(mutex_own(&dict_sys->mutex)); + + ut_a(table->get_ref_count() == 0); + + if (!table->stat_initialized) { + return; + } + + table->stat_initialized = FALSE; + +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&table->stat_n_rows, sizeof table->stat_n_rows); + MEM_UNDEFINED(&table->stat_clustered_index_size, + sizeof table->stat_clustered_index_size); + MEM_UNDEFINED(&table->stat_sum_of_other_index_sizes, + sizeof table->stat_sum_of_other_index_sizes); + MEM_UNDEFINED(&table->stat_modified_counter, + sizeof table->stat_modified_counter); + + dict_index_t* index; + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + MEM_UNDEFINED( + index->stat_n_diff_key_vals, + index->n_uniq + * sizeof(index->stat_n_diff_key_vals[0])); + MEM_UNDEFINED( + index->stat_n_sample_sizes, + index->n_uniq + * sizeof(index->stat_n_sample_sizes[0])); + MEM_UNDEFINED( + index->stat_n_non_null_key_vals, + index->n_uniq + * sizeof(index->stat_n_non_null_key_vals[0])); + MEM_UNDEFINED( + &index->stat_index_size, + sizeof(index->stat_index_size)); + MEM_UNDEFINED( + &index->stat_n_leaf_pages, + sizeof(index->stat_n_leaf_pages)); + } +#endif /* HAVE_valgrind_or_MSAN */ +} diff --git a/storage/innobase/include/eval0eval.h b/storage/innobase/include/eval0eval.h index ebd40924a49..a3ea046250b 100644 --- a/storage/innobase/include/eval0eval.h +++ b/storage/innobase/include/eval0eval.h @@ -104,6 +104,6 @@ eval_cmp( func_node_t* cmp_node); /*!< in: comparison node */ -#include "eval0eval.ic" +#include "eval0eval.inl" #endif diff --git a/storage/innobase/include/eval0eval.ic b/storage/innobase/include/eval0eval.ic deleted file mode 100644 index ae0887408b0..00000000000 --- a/storage/innobase/include/eval0eval.ic +++ /dev/null @@ -1,253 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1997, 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/eval0eval.ic -SQL evaluator: evaluates simple data structures, like expressions, in -a query graph - -Created 12/29/1997 Heikki Tuuri -*******************************************************/ - -#include "que0que.h" -#include "rem0cmp.h" -#include "pars0grm.h" - -/*****************************************************************//** -Evaluates a function node. */ -void -eval_func( -/*======*/ - func_node_t* func_node); /*!< in: function node */ -/*****************************************************************//** -Allocate a buffer from global dynamic memory for a value of a que_node. -NOTE that this memory must be explicitly freed when the query graph is -freed. If the node already has allocated buffer, that buffer is freed -here. NOTE that this is the only function where dynamic memory should be -allocated for a query node val field. -@return pointer to allocated buffer */ -byte* -eval_node_alloc_val_buf( -/*====================*/ - que_node_t* node, /*!< in: query graph node; sets the val field - data field to point to the new buffer, and - len field equal to size */ - ulint size); /*!< in: buffer size */ - - -/*****************************************************************//** -Allocates a new buffer if needed. -@return pointer to buffer */ -UNIV_INLINE -byte* -eval_node_ensure_val_buf( -/*=====================*/ - que_node_t* node, /*!< in: query graph node; sets the val field - data field to point to the new buffer, and - len field equal to size */ - ulint size) /*!< in: buffer size */ -{ - dfield_t* dfield; - byte* data; - - dfield = que_node_get_val(node); - dfield_set_len(dfield, size); - - data = static_cast(dfield_get_data(dfield)); - - if (!data || que_node_get_val_buf_size(node) < size) { - - data = eval_node_alloc_val_buf(node, size); - } - - return(data); -} - -/*****************************************************************//** -Evaluates a symbol table symbol. */ -UNIV_INLINE -void -eval_sym( -/*=====*/ - sym_node_t* sym_node) /*!< in: symbol table node */ -{ - - ut_ad(que_node_get_type(sym_node) == QUE_NODE_SYMBOL); - - if (sym_node->indirection) { - /* The symbol table node is an alias for a variable or a - column */ - - dfield_copy_data(que_node_get_val(sym_node), - que_node_get_val(sym_node->indirection)); - } -} - -/*****************************************************************//** -Evaluates an expression. */ -UNIV_INLINE -void -eval_exp( -/*=====*/ - que_node_t* exp_node) /*!< in: expression */ -{ - if (que_node_get_type(exp_node) == QUE_NODE_SYMBOL) { - - eval_sym((sym_node_t*) exp_node); - - return; - } - - eval_func(static_cast(exp_node)); -} - -/*****************************************************************//** -Sets an integer value as the value of an expression node. */ -UNIV_INLINE -void -eval_node_set_int_val( -/*==================*/ - que_node_t* node, /*!< in: expression node */ - lint val) /*!< in: value to set */ -{ - dfield_t* dfield; - byte* data; - - dfield = que_node_get_val(node); - - data = static_cast(dfield_get_data(dfield)); - - if (data == NULL) { - data = eval_node_alloc_val_buf(node, 4); - } - - ut_ad(dfield_get_len(dfield) == 4); - - mach_write_to_4(data, (ulint) val); -} - -/*****************************************************************//** -Gets an integer non-SQL null value from an expression node. -@return integer value */ -UNIV_INLINE -lint -eval_node_get_int_val( -/*==================*/ - que_node_t* node) /*!< in: expression node */ -{ - const byte* ptr; - dfield_t* dfield; - - dfield = que_node_get_val(node); - ptr = static_cast(dfield_get_data(dfield)); - - ut_ad(dfield_get_len(dfield) == 4); - - return((int) mach_read_from_4(ptr)); -} - -/*****************************************************************//** -Gets a iboolean value from a query node. -@return iboolean value */ -UNIV_INLINE -ibool -eval_node_get_ibool_val( -/*====================*/ - que_node_t* node) /*!< in: query graph node */ -{ - dfield_t* dfield; - byte* data; - - dfield = que_node_get_val(node); - - data = static_cast(dfield_get_data(dfield)); - - ut_ad(data != NULL); - - return(mach_read_from_1(data)); -} - -/*****************************************************************//** -Sets a iboolean value as the value of a function node. */ -UNIV_INLINE -void -eval_node_set_ibool_val( -/*====================*/ - func_node_t* func_node, /*!< in: function node */ - ibool val) /*!< in: value to set */ -{ - dfield_t* dfield; - byte* data; - - dfield = que_node_get_val(func_node); - - data = static_cast(dfield_get_data(dfield)); - - if (data == NULL) { - /* Allocate 1 byte to hold the value */ - - data = eval_node_alloc_val_buf(func_node, 1); - } - - ut_ad(dfield_get_len(dfield) == 1); - - mach_write_to_1(data, val); -} - -/*****************************************************************//** -Copies a binary string value as the value of a query graph node. Allocates a -new buffer if necessary. */ -UNIV_INLINE -void -eval_node_copy_and_alloc_val( -/*=========================*/ - que_node_t* node, /*!< in: query graph node */ - const byte* str, /*!< in: binary string */ - ulint len) /*!< in: string length or UNIV_SQL_NULL */ -{ - byte* data; - - if (len == UNIV_SQL_NULL) { - dfield_set_len(que_node_get_val(node), len); - - return; - } - - data = eval_node_ensure_val_buf(node, len); - - ut_memcpy(data, str, len); -} - -/*****************************************************************//** -Copies a query node value to another node. */ -UNIV_INLINE -void -eval_node_copy_val( -/*===============*/ - que_node_t* node1, /*!< in: node to copy to */ - que_node_t* node2) /*!< in: node to copy from */ -{ - dfield_t* dfield2; - - dfield2 = que_node_get_val(node2); - - eval_node_copy_and_alloc_val( - node1, - static_cast(dfield_get_data(dfield2)), - dfield_get_len(dfield2)); -} diff --git a/storage/innobase/include/eval0eval.inl b/storage/innobase/include/eval0eval.inl new file mode 100644 index 00000000000..ae0887408b0 --- /dev/null +++ b/storage/innobase/include/eval0eval.inl @@ -0,0 +1,253 @@ +/***************************************************************************** + +Copyright (c) 1997, 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/eval0eval.ic +SQL evaluator: evaluates simple data structures, like expressions, in +a query graph + +Created 12/29/1997 Heikki Tuuri +*******************************************************/ + +#include "que0que.h" +#include "rem0cmp.h" +#include "pars0grm.h" + +/*****************************************************************//** +Evaluates a function node. */ +void +eval_func( +/*======*/ + func_node_t* func_node); /*!< in: function node */ +/*****************************************************************//** +Allocate a buffer from global dynamic memory for a value of a que_node. +NOTE that this memory must be explicitly freed when the query graph is +freed. If the node already has allocated buffer, that buffer is freed +here. NOTE that this is the only function where dynamic memory should be +allocated for a query node val field. +@return pointer to allocated buffer */ +byte* +eval_node_alloc_val_buf( +/*====================*/ + que_node_t* node, /*!< in: query graph node; sets the val field + data field to point to the new buffer, and + len field equal to size */ + ulint size); /*!< in: buffer size */ + + +/*****************************************************************//** +Allocates a new buffer if needed. +@return pointer to buffer */ +UNIV_INLINE +byte* +eval_node_ensure_val_buf( +/*=====================*/ + que_node_t* node, /*!< in: query graph node; sets the val field + data field to point to the new buffer, and + len field equal to size */ + ulint size) /*!< in: buffer size */ +{ + dfield_t* dfield; + byte* data; + + dfield = que_node_get_val(node); + dfield_set_len(dfield, size); + + data = static_cast(dfield_get_data(dfield)); + + if (!data || que_node_get_val_buf_size(node) < size) { + + data = eval_node_alloc_val_buf(node, size); + } + + return(data); +} + +/*****************************************************************//** +Evaluates a symbol table symbol. */ +UNIV_INLINE +void +eval_sym( +/*=====*/ + sym_node_t* sym_node) /*!< in: symbol table node */ +{ + + ut_ad(que_node_get_type(sym_node) == QUE_NODE_SYMBOL); + + if (sym_node->indirection) { + /* The symbol table node is an alias for a variable or a + column */ + + dfield_copy_data(que_node_get_val(sym_node), + que_node_get_val(sym_node->indirection)); + } +} + +/*****************************************************************//** +Evaluates an expression. */ +UNIV_INLINE +void +eval_exp( +/*=====*/ + que_node_t* exp_node) /*!< in: expression */ +{ + if (que_node_get_type(exp_node) == QUE_NODE_SYMBOL) { + + eval_sym((sym_node_t*) exp_node); + + return; + } + + eval_func(static_cast(exp_node)); +} + +/*****************************************************************//** +Sets an integer value as the value of an expression node. */ +UNIV_INLINE +void +eval_node_set_int_val( +/*==================*/ + que_node_t* node, /*!< in: expression node */ + lint val) /*!< in: value to set */ +{ + dfield_t* dfield; + byte* data; + + dfield = que_node_get_val(node); + + data = static_cast(dfield_get_data(dfield)); + + if (data == NULL) { + data = eval_node_alloc_val_buf(node, 4); + } + + ut_ad(dfield_get_len(dfield) == 4); + + mach_write_to_4(data, (ulint) val); +} + +/*****************************************************************//** +Gets an integer non-SQL null value from an expression node. +@return integer value */ +UNIV_INLINE +lint +eval_node_get_int_val( +/*==================*/ + que_node_t* node) /*!< in: expression node */ +{ + const byte* ptr; + dfield_t* dfield; + + dfield = que_node_get_val(node); + ptr = static_cast(dfield_get_data(dfield)); + + ut_ad(dfield_get_len(dfield) == 4); + + return((int) mach_read_from_4(ptr)); +} + +/*****************************************************************//** +Gets a iboolean value from a query node. +@return iboolean value */ +UNIV_INLINE +ibool +eval_node_get_ibool_val( +/*====================*/ + que_node_t* node) /*!< in: query graph node */ +{ + dfield_t* dfield; + byte* data; + + dfield = que_node_get_val(node); + + data = static_cast(dfield_get_data(dfield)); + + ut_ad(data != NULL); + + return(mach_read_from_1(data)); +} + +/*****************************************************************//** +Sets a iboolean value as the value of a function node. */ +UNIV_INLINE +void +eval_node_set_ibool_val( +/*====================*/ + func_node_t* func_node, /*!< in: function node */ + ibool val) /*!< in: value to set */ +{ + dfield_t* dfield; + byte* data; + + dfield = que_node_get_val(func_node); + + data = static_cast(dfield_get_data(dfield)); + + if (data == NULL) { + /* Allocate 1 byte to hold the value */ + + data = eval_node_alloc_val_buf(func_node, 1); + } + + ut_ad(dfield_get_len(dfield) == 1); + + mach_write_to_1(data, val); +} + +/*****************************************************************//** +Copies a binary string value as the value of a query graph node. Allocates a +new buffer if necessary. */ +UNIV_INLINE +void +eval_node_copy_and_alloc_val( +/*=========================*/ + que_node_t* node, /*!< in: query graph node */ + const byte* str, /*!< in: binary string */ + ulint len) /*!< in: string length or UNIV_SQL_NULL */ +{ + byte* data; + + if (len == UNIV_SQL_NULL) { + dfield_set_len(que_node_get_val(node), len); + + return; + } + + data = eval_node_ensure_val_buf(node, len); + + ut_memcpy(data, str, len); +} + +/*****************************************************************//** +Copies a query node value to another node. */ +UNIV_INLINE +void +eval_node_copy_val( +/*===============*/ + que_node_t* node1, /*!< in: node to copy to */ + que_node_t* node2) /*!< in: node to copy from */ +{ + dfield_t* dfield2; + + dfield2 = que_node_get_val(node2); + + eval_node_copy_and_alloc_val( + node1, + static_cast(dfield_get_data(dfield2)), + dfield_get_len(dfield2)); +} diff --git a/storage/innobase/include/eval0proc.h b/storage/innobase/include/eval0proc.h index 71700bb5933..a93140bf053 100644 --- a/storage/innobase/include/eval0proc.h +++ b/storage/innobase/include/eval0proc.h @@ -89,6 +89,6 @@ return_step( /*========*/ que_thr_t* thr); /*!< in: query thread */ -#include "eval0proc.ic" +#include "eval0proc.inl" #endif diff --git a/storage/innobase/include/eval0proc.ic b/storage/innobase/include/eval0proc.ic deleted file mode 100644 index b0c5f75b94e..00000000000 --- a/storage/innobase/include/eval0proc.ic +++ /dev/null @@ -1,88 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1998, 2013, 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/eval0proc.ic -Executes SQL stored procedures and their control structures - -Created 1/20/1998 Heikki Tuuri -*******************************************************/ - -#include "pars0pars.h" -#include "que0que.h" -#include "eval0eval.h" - -/**********************************************************************//** -Performs an execution step of a procedure node. -@return query thread to run next or NULL */ -UNIV_INLINE -que_thr_t* -proc_step( -/*======*/ - que_thr_t* thr) /*!< in: query thread */ -{ - proc_node_t* node; - - ut_ad(thr); - - node = static_cast(thr->run_node); - ut_ad(que_node_get_type(node) == QUE_NODE_PROC); - - if (thr->prev_node == que_node_get_parent(node)) { - /* Start execution from the first statement in the statement - list */ - - thr->run_node = node->stat_list; - } else { - /* Move to the next statement */ - ut_ad(que_node_get_next(thr->prev_node) == NULL); - - thr->run_node = NULL; - } - - if (thr->run_node == NULL) { - thr->run_node = que_node_get_parent(node); - } - - return(thr); -} - -/**********************************************************************//** -Performs an execution step of a procedure call node. -@return query thread to run next or NULL */ -UNIV_INLINE -que_thr_t* -proc_eval_step( -/*===========*/ - que_thr_t* thr) /*!< in: query thread */ -{ - func_node_t* node; - - ut_ad(thr); - - node = static_cast(thr->run_node); - ut_ad(que_node_get_type(node) == QUE_NODE_FUNC); - - /* Evaluate the procedure */ - - eval_exp(node); - - thr->run_node = que_node_get_parent(node); - - return(thr); -} diff --git a/storage/innobase/include/eval0proc.inl b/storage/innobase/include/eval0proc.inl new file mode 100644 index 00000000000..b0c5f75b94e --- /dev/null +++ b/storage/innobase/include/eval0proc.inl @@ -0,0 +1,88 @@ +/***************************************************************************** + +Copyright (c) 1998, 2013, 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/eval0proc.ic +Executes SQL stored procedures and their control structures + +Created 1/20/1998 Heikki Tuuri +*******************************************************/ + +#include "pars0pars.h" +#include "que0que.h" +#include "eval0eval.h" + +/**********************************************************************//** +Performs an execution step of a procedure node. +@return query thread to run next or NULL */ +UNIV_INLINE +que_thr_t* +proc_step( +/*======*/ + que_thr_t* thr) /*!< in: query thread */ +{ + proc_node_t* node; + + ut_ad(thr); + + node = static_cast(thr->run_node); + ut_ad(que_node_get_type(node) == QUE_NODE_PROC); + + if (thr->prev_node == que_node_get_parent(node)) { + /* Start execution from the first statement in the statement + list */ + + thr->run_node = node->stat_list; + } else { + /* Move to the next statement */ + ut_ad(que_node_get_next(thr->prev_node) == NULL); + + thr->run_node = NULL; + } + + if (thr->run_node == NULL) { + thr->run_node = que_node_get_parent(node); + } + + return(thr); +} + +/**********************************************************************//** +Performs an execution step of a procedure call node. +@return query thread to run next or NULL */ +UNIV_INLINE +que_thr_t* +proc_eval_step( +/*===========*/ + que_thr_t* thr) /*!< in: query thread */ +{ + func_node_t* node; + + ut_ad(thr); + + node = static_cast(thr->run_node); + ut_ad(que_node_get_type(node) == QUE_NODE_FUNC); + + /* Evaluate the procedure */ + + eval_exp(node); + + thr->run_node = que_node_get_parent(node); + + return(thr); +} diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index 42b38c395d8..c2ceadf8d0a 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -479,7 +479,7 @@ fil_space_get_scrub_status( const fil_space_t* space, fil_space_scrub_status_t* status); -#include "fil0crypt.ic" +#include "fil0crypt.inl" #endif /* !UNIV_INNOCHECKSUM */ /** diff --git a/storage/innobase/include/fil0crypt.ic b/storage/innobase/include/fil0crypt.ic deleted file mode 100644 index cc59b394368..00000000000 --- a/storage/innobase/include/fil0crypt.ic +++ /dev/null @@ -1,81 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2015, 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/fil0crypt.ic -The low-level file system encryption support functions - -Created 04/01/2015 Jan Lindström -*******************************************************/ - -/*******************************************************************//** -Find out whether the page is page encrypted -@return true if page is page encrypted, false if not */ -UNIV_INLINE -bool -fil_page_is_encrypted( -/*==================*/ - const byte *buf) /*!< in: page */ -{ - return(mach_read_from_4(buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) != 0); -} - -/*******************************************************************//** -Get current encryption mode from crypt_data. -@return string representation */ -UNIV_INLINE -const char * -fil_crypt_get_mode( -/*===============*/ - const fil_space_crypt_t* crypt_data) -{ - switch (crypt_data->encryption) { - case FIL_ENCRYPTION_DEFAULT: - return("Default tablespace encryption mode"); - case FIL_ENCRYPTION_ON: - return("Tablespace encrypted"); - case FIL_ENCRYPTION_OFF: - return("Tablespace not encrypted"); - } - - ut_error; - return ("NULL"); -} - -/*******************************************************************//** -Get current encryption type from crypt_data. -@return string representation */ -UNIV_INLINE -const char * -fil_crypt_get_type( - const fil_space_crypt_t* crypt_data) -{ - ut_ad(crypt_data != NULL); - switch (crypt_data->type) { - case CRYPT_SCHEME_UNENCRYPTED: - return("scheme unencrypted"); - break; - case CRYPT_SCHEME_1: - return("scheme encrypted"); - break; - default: - ut_error; - } - - return ("NULL"); -} diff --git a/storage/innobase/include/fil0crypt.inl b/storage/innobase/include/fil0crypt.inl new file mode 100644 index 00000000000..cc59b394368 --- /dev/null +++ b/storage/innobase/include/fil0crypt.inl @@ -0,0 +1,81 @@ +/***************************************************************************** + +Copyright (c) 2015, 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/fil0crypt.ic +The low-level file system encryption support functions + +Created 04/01/2015 Jan Lindström +*******************************************************/ + +/*******************************************************************//** +Find out whether the page is page encrypted +@return true if page is page encrypted, false if not */ +UNIV_INLINE +bool +fil_page_is_encrypted( +/*==================*/ + const byte *buf) /*!< in: page */ +{ + return(mach_read_from_4(buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) != 0); +} + +/*******************************************************************//** +Get current encryption mode from crypt_data. +@return string representation */ +UNIV_INLINE +const char * +fil_crypt_get_mode( +/*===============*/ + const fil_space_crypt_t* crypt_data) +{ + switch (crypt_data->encryption) { + case FIL_ENCRYPTION_DEFAULT: + return("Default tablespace encryption mode"); + case FIL_ENCRYPTION_ON: + return("Tablespace encrypted"); + case FIL_ENCRYPTION_OFF: + return("Tablespace not encrypted"); + } + + ut_error; + return ("NULL"); +} + +/*******************************************************************//** +Get current encryption type from crypt_data. +@return string representation */ +UNIV_INLINE +const char * +fil_crypt_get_type( + const fil_space_crypt_t* crypt_data) +{ + ut_ad(crypt_data != NULL); + switch (crypt_data->type) { + case CRYPT_SCHEME_UNENCRYPTED: + return("scheme unencrypted"); + break; + case CRYPT_SCHEME_1: + return("scheme encrypted"); + break; + default: + ut_error; + } + + return ("NULL"); +} diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 7ce89f3be60..a1edc1ca741 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1469,7 +1469,7 @@ UNIV_INTERN ulint fil_space_get_block_size(const fil_space_t* space, unsigned offset); -#include "fil0fil.ic" +#include "fil0fil.inl" #endif /* UNIV_INNOCHECKSUM */ #endif /* fil0fil_h */ diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic deleted file mode 100644 index 1d1aaab61f5..00000000000 --- a/storage/innobase/include/fil0fil.ic +++ /dev/null @@ -1,128 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2015, 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/fil0fil.ic -The low-level file system support functions - -Created 31/03/2015 Jan Lindström -*******************************************************/ - -#ifndef fil0fil_ic -#define fil0fil_ic - -/*******************************************************************//** -Return page type name */ -UNIV_INLINE -const char* -fil_get_page_type_name( -/*===================*/ - ulint page_type) /*!< in: FIL_PAGE_TYPE */ -{ - switch(page_type) { - case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: - return "PAGE_COMPRESSED_ENRYPTED"; - case FIL_PAGE_PAGE_COMPRESSED: - return "PAGE_COMPRESSED"; - case FIL_PAGE_INDEX: - return "INDEX"; - case FIL_PAGE_RTREE: - return "RTREE"; - case FIL_PAGE_UNDO_LOG: - return "UNDO LOG"; - case FIL_PAGE_INODE: - return "INODE"; - case FIL_PAGE_IBUF_FREE_LIST: - return "IBUF_FREE_LIST"; - case FIL_PAGE_TYPE_ALLOCATED: - return "ALLOCATED"; - case FIL_PAGE_IBUF_BITMAP: - return "IBUF_BITMAP"; - case FIL_PAGE_TYPE_SYS: - return "SYS"; - case FIL_PAGE_TYPE_TRX_SYS: - return "TRX_SYS"; - case FIL_PAGE_TYPE_FSP_HDR: - return "FSP_HDR"; - case FIL_PAGE_TYPE_XDES: - return "XDES"; - case FIL_PAGE_TYPE_BLOB: - return "BLOB"; - case FIL_PAGE_TYPE_ZBLOB: - return "ZBLOB"; - case FIL_PAGE_TYPE_ZBLOB2: - return "ZBLOB2"; - case FIL_PAGE_TYPE_UNKNOWN: - return "OLD UNKOWN PAGE TYPE"; - default: - return "PAGE TYPE CORRUPTED"; - } -} - -/****************************************************************//** -Validate page type. -@return true if valid, false if not */ -UNIV_INLINE -bool -fil_page_type_validate( - const byte* page) /*!< in: page */ -{ -#ifdef UNIV_DEBUG - ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE); - - /* Validate page type */ - if (!((page_type == FIL_PAGE_PAGE_COMPRESSED || - page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED || - page_type == FIL_PAGE_INDEX || - page_type == FIL_PAGE_RTREE || - page_type == FIL_PAGE_UNDO_LOG || - page_type == FIL_PAGE_INODE || - page_type == FIL_PAGE_IBUF_FREE_LIST || - page_type == FIL_PAGE_TYPE_ALLOCATED || - page_type == FIL_PAGE_IBUF_BITMAP || - page_type == FIL_PAGE_TYPE_SYS || - page_type == FIL_PAGE_TYPE_TRX_SYS || - page_type == FIL_PAGE_TYPE_FSP_HDR || - page_type == FIL_PAGE_TYPE_XDES || - page_type == FIL_PAGE_TYPE_BLOB || - page_type == FIL_PAGE_TYPE_ZBLOB || - 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 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(); - - /* Dump out the page info */ - ib::fatal() << "Page " << space << ":" << offset - << " name " << (rspace ? rspace->name : "???") - << " page_type " << page_type - << " key_version " - << mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_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 /* fil0fil_ic */ diff --git a/storage/innobase/include/fil0fil.inl b/storage/innobase/include/fil0fil.inl new file mode 100644 index 00000000000..1d1aaab61f5 --- /dev/null +++ b/storage/innobase/include/fil0fil.inl @@ -0,0 +1,128 @@ +/***************************************************************************** + +Copyright (c) 2015, 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/fil0fil.ic +The low-level file system support functions + +Created 31/03/2015 Jan Lindström +*******************************************************/ + +#ifndef fil0fil_ic +#define fil0fil_ic + +/*******************************************************************//** +Return page type name */ +UNIV_INLINE +const char* +fil_get_page_type_name( +/*===================*/ + ulint page_type) /*!< in: FIL_PAGE_TYPE */ +{ + switch(page_type) { + case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: + return "PAGE_COMPRESSED_ENRYPTED"; + case FIL_PAGE_PAGE_COMPRESSED: + return "PAGE_COMPRESSED"; + case FIL_PAGE_INDEX: + return "INDEX"; + case FIL_PAGE_RTREE: + return "RTREE"; + case FIL_PAGE_UNDO_LOG: + return "UNDO LOG"; + case FIL_PAGE_INODE: + return "INODE"; + case FIL_PAGE_IBUF_FREE_LIST: + return "IBUF_FREE_LIST"; + case FIL_PAGE_TYPE_ALLOCATED: + return "ALLOCATED"; + case FIL_PAGE_IBUF_BITMAP: + return "IBUF_BITMAP"; + case FIL_PAGE_TYPE_SYS: + return "SYS"; + case FIL_PAGE_TYPE_TRX_SYS: + return "TRX_SYS"; + case FIL_PAGE_TYPE_FSP_HDR: + return "FSP_HDR"; + case FIL_PAGE_TYPE_XDES: + return "XDES"; + case FIL_PAGE_TYPE_BLOB: + return "BLOB"; + case FIL_PAGE_TYPE_ZBLOB: + return "ZBLOB"; + case FIL_PAGE_TYPE_ZBLOB2: + return "ZBLOB2"; + case FIL_PAGE_TYPE_UNKNOWN: + return "OLD UNKOWN PAGE TYPE"; + default: + return "PAGE TYPE CORRUPTED"; + } +} + +/****************************************************************//** +Validate page type. +@return true if valid, false if not */ +UNIV_INLINE +bool +fil_page_type_validate( + const byte* page) /*!< in: page */ +{ +#ifdef UNIV_DEBUG + ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE); + + /* Validate page type */ + if (!((page_type == FIL_PAGE_PAGE_COMPRESSED || + page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED || + page_type == FIL_PAGE_INDEX || + page_type == FIL_PAGE_RTREE || + page_type == FIL_PAGE_UNDO_LOG || + page_type == FIL_PAGE_INODE || + page_type == FIL_PAGE_IBUF_FREE_LIST || + page_type == FIL_PAGE_TYPE_ALLOCATED || + page_type == FIL_PAGE_IBUF_BITMAP || + page_type == FIL_PAGE_TYPE_SYS || + page_type == FIL_PAGE_TYPE_TRX_SYS || + page_type == FIL_PAGE_TYPE_FSP_HDR || + page_type == FIL_PAGE_TYPE_XDES || + page_type == FIL_PAGE_TYPE_BLOB || + page_type == FIL_PAGE_TYPE_ZBLOB || + 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 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(); + + /* Dump out the page info */ + ib::fatal() << "Page " << space << ":" << offset + << " name " << (rspace ? rspace->name : "???") + << " page_type " << page_type + << " key_version " + << mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_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 /* fil0fil_ic */ diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index a50be6f8998..dc441142c23 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -861,6 +861,6 @@ xdes_calc_descriptor_page( #endif /* UNIV_INNOCHECKSUM */ -#include "fsp0fsp.ic" +#include "fsp0fsp.inl" #endif diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic deleted file mode 100644 index d0f7fba4047..00000000000 --- a/storage/innobase/include/fsp0fsp.ic +++ /dev/null @@ -1,124 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 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/fsp0fsp.ic -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 */ -UNIV_INLINE -ibool -xdes_get_bit( -/*=========*/ - const xdes_t* descr, /*!< in: descriptor */ - ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */ - ulint offset) /*!< in: page offset within extent: - 0 ... FSP_EXTENT_SIZE - 1 */ -{ - ut_ad(offset < FSP_EXTENT_SIZE); - ut_ad(bit == XDES_FREE_BIT || bit == XDES_CLEAN_BIT); - - ulint index = bit + XDES_BITS_PER_PAGE * offset; - - 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) -{ -#ifndef DOXYGEN /* Doxygen gets confused by these */ -# if UNIV_PAGE_SIZE_MAX <= XDES_ARR_OFFSET \ - + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX) \ - * XDES_SIZE_MAX -# error -# endif -# if UNIV_ZIP_SIZE_MIN <= XDES_ARR_OFFSET \ - + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE_MIN) \ - * XDES_SIZE_MIN -# error -# endif -#endif /* !DOXYGEN */ - - ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET - + (UNIV_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())); -} -#endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/fsp0fsp.inl b/storage/innobase/include/fsp0fsp.inl new file mode 100644 index 00000000000..d0f7fba4047 --- /dev/null +++ b/storage/innobase/include/fsp0fsp.inl @@ -0,0 +1,124 @@ +/***************************************************************************** + +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 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/fsp0fsp.ic +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 */ +UNIV_INLINE +ibool +xdes_get_bit( +/*=========*/ + const xdes_t* descr, /*!< in: descriptor */ + ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */ + ulint offset) /*!< in: page offset within extent: + 0 ... FSP_EXTENT_SIZE - 1 */ +{ + ut_ad(offset < FSP_EXTENT_SIZE); + ut_ad(bit == XDES_FREE_BIT || bit == XDES_CLEAN_BIT); + + ulint index = bit + XDES_BITS_PER_PAGE * offset; + + 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) +{ +#ifndef DOXYGEN /* Doxygen gets confused by these */ +# if UNIV_PAGE_SIZE_MAX <= XDES_ARR_OFFSET \ + + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX) \ + * XDES_SIZE_MAX +# error +# endif +# if UNIV_ZIP_SIZE_MIN <= XDES_ARR_OFFSET \ + + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE_MIN) \ + * XDES_SIZE_MIN +# error +# endif +#endif /* !DOXYGEN */ + + ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET + + (UNIV_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())); +} +#endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/fsp0pagecompress.h b/storage/innobase/include/fsp0pagecompress.h index fc0b907dfa7..f16b7d29bc0 100644 --- a/storage/innobase/include/fsp0pagecompress.h +++ b/storage/innobase/include/fsp0pagecompress.h @@ -59,6 +59,6 @@ fsp_flags_get_page_compression_level( /*=================================*/ ulint flags); /*!< in: tablespace flags */ -#include "fsp0pagecompress.ic" +#include "fsp0pagecompress.inl" #endif diff --git a/storage/innobase/include/fsp0pagecompress.ic b/storage/innobase/include/fsp0pagecompress.ic deleted file mode 100644 index 590a609c309..00000000000 --- a/storage/innobase/include/fsp0pagecompress.ic +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************** - -Copyright (C) 2013, 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 St, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/******************************************************************//** -@file include/fsp0pagecompress.ic -Implementation for helper functions for extracting/storing page -compression and atomic writes information to file space. - -Created 11/12/2013 Jan Lindström jan.lindstrom@mariadb.com - -***********************************************************************/ - -/********************************************************************//** -Determine the tablespace is page compression level from dict_table_t::flags. -@return page compression level or 0 if not compressed*/ -UNIV_INLINE -ulint -fsp_flags_get_page_compression_level( -/*=================================*/ - ulint flags) /*!< in: tablespace flags */ -{ - return(FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags)); -} - - -/*******************************************************************//** -Find out wheather the page is page compressed -@return true if page is page compressed, false if not */ -UNIV_INLINE -bool -fil_page_is_compressed( -/*===================*/ - const byte* buf) /*!< in: page */ -{ - return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED); -} - -/*******************************************************************//** -Find out wheather the page is page compressed -@return true if page is page compressed, false if not */ -UNIV_INLINE -bool -fil_page_is_compressed_encrypted( -/*=============================*/ - const byte* buf) /*!< in: page */ -{ - return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED); -} diff --git a/storage/innobase/include/fsp0pagecompress.inl b/storage/innobase/include/fsp0pagecompress.inl new file mode 100644 index 00000000000..590a609c309 --- /dev/null +++ b/storage/innobase/include/fsp0pagecompress.inl @@ -0,0 +1,63 @@ +/***************************************************************************** + +Copyright (C) 2013, 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 St, Fifth Floor, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/******************************************************************//** +@file include/fsp0pagecompress.ic +Implementation for helper functions for extracting/storing page +compression and atomic writes information to file space. + +Created 11/12/2013 Jan Lindström jan.lindstrom@mariadb.com + +***********************************************************************/ + +/********************************************************************//** +Determine the tablespace is page compression level from dict_table_t::flags. +@return page compression level or 0 if not compressed*/ +UNIV_INLINE +ulint +fsp_flags_get_page_compression_level( +/*=================================*/ + ulint flags) /*!< in: tablespace flags */ +{ + return(FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags)); +} + + +/*******************************************************************//** +Find out wheather the page is page compressed +@return true if page is page compressed, false if not */ +UNIV_INLINE +bool +fil_page_is_compressed( +/*===================*/ + const byte* buf) /*!< in: page */ +{ + return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED); +} + +/*******************************************************************//** +Find out wheather the page is page compressed +@return true if page is page compressed, false if not */ +UNIV_INLINE +bool +fil_page_is_compressed_encrypted( +/*=============================*/ + const byte* buf) /*!< in: page */ +{ + return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED); +} diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h index 2b7f31dfe54..56955d0cf98 100644 --- a/storage/innobase/include/fts0priv.h +++ b/storage/innobase/include/fts0priv.h @@ -512,6 +512,6 @@ fts_config_create_index_param_name( const dict_index_t* index) /*!< in: index for config */ MY_ATTRIBUTE((nonnull, malloc, warn_unused_result)); -#include "fts0priv.ic" +#include "fts0priv.inl" #endif /* INNOBASE_FTS0PRIV_H */ diff --git a/storage/innobase/include/fts0priv.ic b/storage/innobase/include/fts0priv.ic deleted file mode 100644 index da14cfcb013..00000000000 --- a/storage/innobase/include/fts0priv.ic +++ /dev/null @@ -1,121 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2011, 2016, 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/fts0priv.ic -Full text search internal header file - -Created 2011/11/12 Sunny Bains -***********************************************************************/ - -/******************************************************************//** -Write the table id to the given buffer (including final NUL). Buffer must be -at least FTS_AUX_MIN_TABLE_ID_LENGTH bytes long. -@return number of bytes written */ -UNIV_INLINE -int -fts_write_object_id( -/*================*/ - ib_id_t id, /* in: a table/index id */ - char* str) /* in: buffer to write the id to */ -{ - -#ifdef _WIN32 - - DBUG_EXECUTE_IF("innodb_test_wrong_non_windows_fts_aux_table_name", - return(sprintf(str, UINT64PFx, id));); - - /* Use this to construct old(5.6.14 and 5.7.3) windows - ambiguous aux table names */ - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - return(sprintf(str, "%016llu", (ulonglong) id));); - -#else /* _WIN32 */ - - /* Use this to construct old(5.6.14 and 5.7.3) windows - ambiguous aux table names */ - DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name", - return(sprintf(str, "%016llu", (ulonglong) id));); - - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - return(sprintf(str, "%016llx", (ulonglong) id));); - -#endif /* _WIN32 */ - - return(sprintf(str, "%016llx", (ulonglong) id)); -} - -/******************************************************************//** -Read the table id from the string generated by fts_write_object_id(). -@return TRUE if parse successful */ -UNIV_INLINE -ibool -fts_read_object_id( -/*===============*/ - ib_id_t* id, /* out: an id */ - const char* str) /* in: buffer to read from */ -{ - /* NOTE: this func doesn't care about whether current table - is set with HEX_NAME, the user of the id read here will check - if the id is HEX or DEC and do the right thing with it. */ - return(sscanf(str, UINT64PFx, id) == 1); -} - -/******************************************************************//** -Compare two fts_trx_table_t instances. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_table_cmp( -/*==============*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const dict_table_t* table1 - = (*static_cast(p1))->table; - - const dict_table_t* table2 - = (*static_cast(p2))->table; - - return((table1->id > table2->id) - ? 1 - : (table1->id == table2->id) - ? 0 - : -1); -} - -/******************************************************************//** -Compare a table id with a fts_trx_table_t table id. -@return < 0 if n1 < n2, 0 if n1 == n2,> 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_table_id_cmp( -/*=================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const uintmax_t* table_id = static_cast(p1); - const dict_table_t* table2 - = (*static_cast(p2))->table; - - return((*table_id > table2->id) - ? 1 - : (*table_id == table2->id) - ? 0 - : -1); -} diff --git a/storage/innobase/include/fts0priv.inl b/storage/innobase/include/fts0priv.inl new file mode 100644 index 00000000000..da14cfcb013 --- /dev/null +++ b/storage/innobase/include/fts0priv.inl @@ -0,0 +1,121 @@ +/***************************************************************************** + +Copyright (c) 2011, 2016, 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/fts0priv.ic +Full text search internal header file + +Created 2011/11/12 Sunny Bains +***********************************************************************/ + +/******************************************************************//** +Write the table id to the given buffer (including final NUL). Buffer must be +at least FTS_AUX_MIN_TABLE_ID_LENGTH bytes long. +@return number of bytes written */ +UNIV_INLINE +int +fts_write_object_id( +/*================*/ + ib_id_t id, /* in: a table/index id */ + char* str) /* in: buffer to write the id to */ +{ + +#ifdef _WIN32 + + DBUG_EXECUTE_IF("innodb_test_wrong_non_windows_fts_aux_table_name", + return(sprintf(str, UINT64PFx, id));); + + /* Use this to construct old(5.6.14 and 5.7.3) windows + ambiguous aux table names */ + DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", + return(sprintf(str, "%016llu", (ulonglong) id));); + +#else /* _WIN32 */ + + /* Use this to construct old(5.6.14 and 5.7.3) windows + ambiguous aux table names */ + DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name", + return(sprintf(str, "%016llu", (ulonglong) id));); + + DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", + return(sprintf(str, "%016llx", (ulonglong) id));); + +#endif /* _WIN32 */ + + return(sprintf(str, "%016llx", (ulonglong) id)); +} + +/******************************************************************//** +Read the table id from the string generated by fts_write_object_id(). +@return TRUE if parse successful */ +UNIV_INLINE +ibool +fts_read_object_id( +/*===============*/ + ib_id_t* id, /* out: an id */ + const char* str) /* in: buffer to read from */ +{ + /* NOTE: this func doesn't care about whether current table + is set with HEX_NAME, the user of the id read here will check + if the id is HEX or DEC and do the right thing with it. */ + return(sscanf(str, UINT64PFx, id) == 1); +} + +/******************************************************************//** +Compare two fts_trx_table_t instances. +@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ +UNIV_INLINE +int +fts_trx_table_cmp( +/*==============*/ + const void* p1, /*!< in: id1 */ + const void* p2) /*!< in: id2 */ +{ + const dict_table_t* table1 + = (*static_cast(p1))->table; + + const dict_table_t* table2 + = (*static_cast(p2))->table; + + return((table1->id > table2->id) + ? 1 + : (table1->id == table2->id) + ? 0 + : -1); +} + +/******************************************************************//** +Compare a table id with a fts_trx_table_t table id. +@return < 0 if n1 < n2, 0 if n1 == n2,> 0 if n1 > n2 */ +UNIV_INLINE +int +fts_trx_table_id_cmp( +/*=================*/ + const void* p1, /*!< in: id1 */ + const void* p2) /*!< in: id2 */ +{ + const uintmax_t* table_id = static_cast(p1); + const dict_table_t* table2 + = (*static_cast(p2))->table; + + return((*table_id > table2->id) + ? 1 + : (*table_id == table2->id) + ? 0 + : -1); +} diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h index d49bc7c0254..2cddf152d04 100644 --- a/storage/innobase/include/fts0types.h +++ b/storage/innobase/include/fts0types.h @@ -351,6 +351,6 @@ fts_select_index( const byte* str, ulint len); -#include "fts0types.ic" +#include "fts0types.inl" #endif /* INNOBASE_FTS0TYPES_H */ diff --git a/storage/innobase/include/fts0types.ic b/storage/innobase/include/fts0types.ic deleted file mode 100644 index cf5cf35c48e..00000000000 --- a/storage/innobase/include/fts0types.ic +++ /dev/null @@ -1,232 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2007, 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/fts0types.ic -Full text search types. - -Created 2007-03-27 Sunny Bains -*******************************************************/ - -#ifndef INNOBASE_FTS0TYPES_IC -#define INNOBASE_FTS0TYPES_IC - -/******************************************************************//** -Duplicate a string. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -void -fts_string_dup( -/*===========*/ - fts_string_t* dst, /*!< in: dup to here */ - const fts_string_t* src, /*!< in: src string */ - mem_heap_t* heap) /*!< in: heap to use */ -{ - dst->f_str = (byte*)mem_heap_alloc(heap, src->f_len + 1); - memcpy(dst->f_str, src->f_str, src->f_len); - - dst->f_len = src->f_len; - dst->f_str[src->f_len] = 0; - dst->f_n_char = src->f_n_char; -} - -/******************************************************************//** -Compare two fts_trx_row_t doc_ids. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_row_doc_id_cmp( -/*===================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const fts_trx_row_t* tr1 = (const fts_trx_row_t*) p1; - const fts_trx_row_t* tr2 = (const fts_trx_row_t*) p2; - - return((int)(tr1->doc_id - tr2->doc_id)); -} - -/******************************************************************//** -Compare two fts_ranking_t doc_ids. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_ranking_doc_id_cmp( -/*===================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const fts_ranking_t* rk1 = (const fts_ranking_t*) p1; - const fts_ranking_t* rk2 = (const fts_ranking_t*) p2; - - return((int)(rk1->doc_id - rk2->doc_id)); -} - -/******************************************************************//** -Compare two doc_ids. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int fts_doc_id_cmp( -/*==================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const doc_id_t* up1 = static_cast(p1); - const doc_id_t* up2 = static_cast(p2); - - return static_cast(*up1 - *up2); -} - -/******************************************************************//** -Get the first character's code position for FTS index partition */ -extern -ulint -innobase_strnxfrm( -/*==============*/ - const CHARSET_INFO* cs, /*!< in: Character set */ - const uchar* p2, /*!< in: string */ - const ulint len2); /*!< in: string length */ - -/** Check if fts index charset is cjk -@param[in] cs charset -@retval true if the charset is cjk -@retval false if not. */ -inline bool fts_is_charset_cjk(const CHARSET_INFO* cs) -{ - switch (cs->number) { - case 24: /* my_charset_gb2312_chinese_ci */ - case 28: /* my_charset_gbk_chinese_ci */ - case 1: /* my_charset_big5_chinese_ci */ - case 12: /* my_charset_ujis_japanese_ci */ - case 13: /* my_charset_sjis_japanese_ci */ - case 95: /* my_charset_cp932_japanese_ci */ - case 97: /* my_charset_eucjpms_japanese_ci */ - case 19: /* my_charset_euckr_korean_ci */ - return true; - default: - return false; - } -} - -/** Select the FTS auxiliary index for the given character by range. -@param[in] cs charset -@param[in] str string -@param[in] len string length -@retval the index to use for the string */ -UNIV_INLINE -ulint -fts_select_index_by_range( - const CHARSET_INFO* cs, - const byte* str, - ulint len) -{ - ulint selected = 0; - ulint value = innobase_strnxfrm(cs, str, len); - - while (fts_index_selector[selected].value != 0) { - - if (fts_index_selector[selected].value == value) { - - return(selected); - - } else if (fts_index_selector[selected].value > value) { - - return(selected > 0 ? selected - 1 : 0); - } - - ++selected; - } - - ut_ad(selected > 1); - - return(selected - 1); -} - -/** Select the FTS auxiliary index for the given character by hash. -@param[in] cs charset -@param[in] str string -@param[in] len string length -@retval the index to use for the string */ -UNIV_INLINE -ulint -fts_select_index_by_hash( - const CHARSET_INFO* cs, - const byte* str, - ulint len) -{ - int char_len; - ulong nr1 = 1; - ulong nr2 = 4; - - ut_ad(!(str == NULL && len > 0)); - - if (str == NULL || len == 0) { - return 0; - } - - /* Get the first char */ - /* JAN: TODO: MySQL 5.7 had - char_len = my_mbcharlen_ptr(cs, reinterpret_cast(str), - reinterpret_cast(str + len)); - */ - char_len = cs->cset->charlen(cs, str, str+len); - - ut_ad(static_cast(char_len) <= len); - - /* Get collation hash code */ - cs->coll->hash_sort(cs, str, char_len, &nr1, &nr2); - - return(nr1 % FTS_NUM_AUX_INDEX); -} - -/** Select the FTS auxiliary index for the given character. -@param[in] cs charset -@param[in] str string -@param[in] len string length in bytes -@retval the index to use for the string */ -UNIV_INLINE -ulint -fts_select_index( - const CHARSET_INFO* cs, - const byte* str, - ulint len) -{ - ulint selected; - - if (fts_is_charset_cjk(cs)) { - selected = fts_select_index_by_hash(cs, str, len); - } else { - selected = fts_select_index_by_range(cs, str, len); - } - - return(selected); -} - -/******************************************************************//** -Return the selected FTS aux index suffix. */ -UNIV_INLINE -const char* -fts_get_suffix( -/*===========*/ - ulint selected) /*!< in: selected index */ -{ - return(fts_index_selector[selected].suffix); -} - -#endif /* INNOBASE_FTS0TYPES_IC */ diff --git a/storage/innobase/include/fts0types.inl b/storage/innobase/include/fts0types.inl new file mode 100644 index 00000000000..cf5cf35c48e --- /dev/null +++ b/storage/innobase/include/fts0types.inl @@ -0,0 +1,232 @@ +/***************************************************************************** + +Copyright (c) 2007, 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/fts0types.ic +Full text search types. + +Created 2007-03-27 Sunny Bains +*******************************************************/ + +#ifndef INNOBASE_FTS0TYPES_IC +#define INNOBASE_FTS0TYPES_IC + +/******************************************************************//** +Duplicate a string. +@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ +UNIV_INLINE +void +fts_string_dup( +/*===========*/ + fts_string_t* dst, /*!< in: dup to here */ + const fts_string_t* src, /*!< in: src string */ + mem_heap_t* heap) /*!< in: heap to use */ +{ + dst->f_str = (byte*)mem_heap_alloc(heap, src->f_len + 1); + memcpy(dst->f_str, src->f_str, src->f_len); + + dst->f_len = src->f_len; + dst->f_str[src->f_len] = 0; + dst->f_n_char = src->f_n_char; +} + +/******************************************************************//** +Compare two fts_trx_row_t doc_ids. +@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ +UNIV_INLINE +int +fts_trx_row_doc_id_cmp( +/*===================*/ + const void* p1, /*!< in: id1 */ + const void* p2) /*!< in: id2 */ +{ + const fts_trx_row_t* tr1 = (const fts_trx_row_t*) p1; + const fts_trx_row_t* tr2 = (const fts_trx_row_t*) p2; + + return((int)(tr1->doc_id - tr2->doc_id)); +} + +/******************************************************************//** +Compare two fts_ranking_t doc_ids. +@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ +UNIV_INLINE +int +fts_ranking_doc_id_cmp( +/*===================*/ + const void* p1, /*!< in: id1 */ + const void* p2) /*!< in: id2 */ +{ + const fts_ranking_t* rk1 = (const fts_ranking_t*) p1; + const fts_ranking_t* rk2 = (const fts_ranking_t*) p2; + + return((int)(rk1->doc_id - rk2->doc_id)); +} + +/******************************************************************//** +Compare two doc_ids. +@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ +UNIV_INLINE +int fts_doc_id_cmp( +/*==================*/ + const void* p1, /*!< in: id1 */ + const void* p2) /*!< in: id2 */ +{ + const doc_id_t* up1 = static_cast(p1); + const doc_id_t* up2 = static_cast(p2); + + return static_cast(*up1 - *up2); +} + +/******************************************************************//** +Get the first character's code position for FTS index partition */ +extern +ulint +innobase_strnxfrm( +/*==============*/ + const CHARSET_INFO* cs, /*!< in: Character set */ + const uchar* p2, /*!< in: string */ + const ulint len2); /*!< in: string length */ + +/** Check if fts index charset is cjk +@param[in] cs charset +@retval true if the charset is cjk +@retval false if not. */ +inline bool fts_is_charset_cjk(const CHARSET_INFO* cs) +{ + switch (cs->number) { + case 24: /* my_charset_gb2312_chinese_ci */ + case 28: /* my_charset_gbk_chinese_ci */ + case 1: /* my_charset_big5_chinese_ci */ + case 12: /* my_charset_ujis_japanese_ci */ + case 13: /* my_charset_sjis_japanese_ci */ + case 95: /* my_charset_cp932_japanese_ci */ + case 97: /* my_charset_eucjpms_japanese_ci */ + case 19: /* my_charset_euckr_korean_ci */ + return true; + default: + return false; + } +} + +/** Select the FTS auxiliary index for the given character by range. +@param[in] cs charset +@param[in] str string +@param[in] len string length +@retval the index to use for the string */ +UNIV_INLINE +ulint +fts_select_index_by_range( + const CHARSET_INFO* cs, + const byte* str, + ulint len) +{ + ulint selected = 0; + ulint value = innobase_strnxfrm(cs, str, len); + + while (fts_index_selector[selected].value != 0) { + + if (fts_index_selector[selected].value == value) { + + return(selected); + + } else if (fts_index_selector[selected].value > value) { + + return(selected > 0 ? selected - 1 : 0); + } + + ++selected; + } + + ut_ad(selected > 1); + + return(selected - 1); +} + +/** Select the FTS auxiliary index for the given character by hash. +@param[in] cs charset +@param[in] str string +@param[in] len string length +@retval the index to use for the string */ +UNIV_INLINE +ulint +fts_select_index_by_hash( + const CHARSET_INFO* cs, + const byte* str, + ulint len) +{ + int char_len; + ulong nr1 = 1; + ulong nr2 = 4; + + ut_ad(!(str == NULL && len > 0)); + + if (str == NULL || len == 0) { + return 0; + } + + /* Get the first char */ + /* JAN: TODO: MySQL 5.7 had + char_len = my_mbcharlen_ptr(cs, reinterpret_cast(str), + reinterpret_cast(str + len)); + */ + char_len = cs->cset->charlen(cs, str, str+len); + + ut_ad(static_cast(char_len) <= len); + + /* Get collation hash code */ + cs->coll->hash_sort(cs, str, char_len, &nr1, &nr2); + + return(nr1 % FTS_NUM_AUX_INDEX); +} + +/** Select the FTS auxiliary index for the given character. +@param[in] cs charset +@param[in] str string +@param[in] len string length in bytes +@retval the index to use for the string */ +UNIV_INLINE +ulint +fts_select_index( + const CHARSET_INFO* cs, + const byte* str, + ulint len) +{ + ulint selected; + + if (fts_is_charset_cjk(cs)) { + selected = fts_select_index_by_hash(cs, str, len); + } else { + selected = fts_select_index_by_range(cs, str, len); + } + + return(selected); +} + +/******************************************************************//** +Return the selected FTS aux index suffix. */ +UNIV_INLINE +const char* +fts_get_suffix( +/*===========*/ + ulint selected) /*!< in: selected index */ +{ + return(fts_index_selector[selected].suffix); +} + +#endif /* INNOBASE_FTS0TYPES_IC */ diff --git a/storage/innobase/include/fut0fut.h b/storage/innobase/include/fut0fut.h index 3c3f118bd68..8f00eb74470 100644 --- a/storage/innobase/include/fut0fut.h +++ b/storage/innobase/include/fut0fut.h @@ -50,6 +50,6 @@ fut_get_ptr( buf_block_t** ptr_block = NULL) MY_ATTRIBUTE((warn_unused_result)); -#include "fut0fut.ic" +#include "fut0fut.inl" #endif /* fut0fut_h */ diff --git a/storage/innobase/include/fut0fut.ic b/storage/innobase/include/fut0fut.ic deleted file mode 100644 index bba84d0d80e..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 < UNIV_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/fut0fut.inl b/storage/innobase/include/fut0fut.inl new file mode 100644 index 00000000000..bba84d0d80e --- /dev/null +++ b/storage/innobase/include/fut0fut.inl @@ -0,0 +1,68 @@ +/***************************************************************************** + +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 < UNIV_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..9ffc4f8955d 100644 --- a/storage/innobase/include/fut0lst.h +++ b/storage/innobase/include/fut0lst.h @@ -149,7 +149,7 @@ flst_validate( const flst_base_node_t* base, /*!< in: pointer to base node of list */ mtr_t* mtr1); /*!< in: mtr */ -#include "fut0lst.ic" +#include "fut0lst.inl" #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/fut0lst.ic b/storage/innobase/include/fut0lst.ic deleted file mode 100644 index fae7fa078bf..00000000000 --- a/storage/innobase/include/fut0lst.ic +++ /dev/null @@ -1,169 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 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/fut0lst.ic -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 -void -flst_write_addr( -/*============*/ - fil_faddr_t* faddr, /*!< in: pointer to file faddress */ - fil_addr_t addr, /*!< in: file address */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - ut_ad(faddr && mtr); - ut_ad(mtr_memo_contains_page_flagged(mtr, faddr, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA); - ut_a(ut_align_offset(faddr, UNIV_PAGE_SIZE) >= FIL_PAGE_DATA); - - mlog_write_ulint(faddr + FIL_ADDR_PAGE, addr.page, MLOG_4BYTES, mtr); - mlog_write_ulint(faddr + FIL_ADDR_BYTE, addr.boffset, - MLOG_2BYTES, mtr); -} - -/********************************************************************//** -Reads a file address. -@return file address */ -UNIV_INLINE -fil_addr_t -flst_read_addr( -/*===========*/ - const fil_faddr_t* faddr, /*!< in: pointer to file faddress */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - fil_addr_t 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); - ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA); - ut_a(ut_align_offset(faddr, UNIV_PAGE_SIZE) >= FIL_PAGE_DATA); - return(addr); -} - -/********************************************************************//** -Initializes a list base node. */ -UNIV_INLINE -void -flst_init( -/*======*/ - flst_base_node_t* base, /*!< in: pointer to base node */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - ut_ad(mtr_memo_contains_page_flagged(mtr, base, - 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); -} - -/** Get the length of a list. -@param[in] base base node -@return length */ -UNIV_INLINE -ulint -flst_get_len( - const flst_base_node_t* base) -{ - return(mach_read_from_4(base + FLST_LEN)); -} - -/********************************************************************//** -Gets list first node address. -@return file address */ -UNIV_INLINE -fil_addr_t -flst_get_first( -/*===========*/ - const flst_base_node_t* base, /*!< in: pointer to base node */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - return(flst_read_addr(base + FLST_FIRST, mtr)); -} - -/********************************************************************//** -Gets list last node address. -@return file address */ -UNIV_INLINE -fil_addr_t -flst_get_last( -/*==========*/ - const flst_base_node_t* base, /*!< in: pointer to base node */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - return(flst_read_addr(base + FLST_LAST, mtr)); -} - -/********************************************************************//** -Gets list next node address. -@return file address */ -UNIV_INLINE -fil_addr_t -flst_get_next_addr( -/*===============*/ - const flst_node_t* node, /*!< in: pointer to node */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - return(flst_read_addr(node + FLST_NEXT, mtr)); -} - -/********************************************************************//** -Gets list prev node address. -@return file address */ -UNIV_INLINE -fil_addr_t -flst_get_prev_addr( -/*===============*/ - const flst_node_t* node, /*!< in: pointer to node */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - return(flst_read_addr(node + FLST_PREV, mtr)); -} diff --git a/storage/innobase/include/fut0lst.inl b/storage/innobase/include/fut0lst.inl new file mode 100644 index 00000000000..fae7fa078bf --- /dev/null +++ b/storage/innobase/include/fut0lst.inl @@ -0,0 +1,169 @@ +/***************************************************************************** + +Copyright (c) 1995, 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/fut0lst.ic +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 +void +flst_write_addr( +/*============*/ + fil_faddr_t* faddr, /*!< in: pointer to file faddress */ + fil_addr_t addr, /*!< in: file address */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + ut_ad(faddr && mtr); + ut_ad(mtr_memo_contains_page_flagged(mtr, faddr, + MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_SX_FIX)); + ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA); + ut_a(ut_align_offset(faddr, UNIV_PAGE_SIZE) >= FIL_PAGE_DATA); + + mlog_write_ulint(faddr + FIL_ADDR_PAGE, addr.page, MLOG_4BYTES, mtr); + mlog_write_ulint(faddr + FIL_ADDR_BYTE, addr.boffset, + MLOG_2BYTES, mtr); +} + +/********************************************************************//** +Reads a file address. +@return file address */ +UNIV_INLINE +fil_addr_t +flst_read_addr( +/*===========*/ + const fil_faddr_t* faddr, /*!< in: pointer to file faddress */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + fil_addr_t 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); + ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA); + ut_a(ut_align_offset(faddr, UNIV_PAGE_SIZE) >= FIL_PAGE_DATA); + return(addr); +} + +/********************************************************************//** +Initializes a list base node. */ +UNIV_INLINE +void +flst_init( +/*======*/ + flst_base_node_t* base, /*!< in: pointer to base node */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + ut_ad(mtr_memo_contains_page_flagged(mtr, base, + 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); +} + +/** Get the length of a list. +@param[in] base base node +@return length */ +UNIV_INLINE +ulint +flst_get_len( + const flst_base_node_t* base) +{ + return(mach_read_from_4(base + FLST_LEN)); +} + +/********************************************************************//** +Gets list first node address. +@return file address */ +UNIV_INLINE +fil_addr_t +flst_get_first( +/*===========*/ + const flst_base_node_t* base, /*!< in: pointer to base node */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + return(flst_read_addr(base + FLST_FIRST, mtr)); +} + +/********************************************************************//** +Gets list last node address. +@return file address */ +UNIV_INLINE +fil_addr_t +flst_get_last( +/*==========*/ + const flst_base_node_t* base, /*!< in: pointer to base node */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + return(flst_read_addr(base + FLST_LAST, mtr)); +} + +/********************************************************************//** +Gets list next node address. +@return file address */ +UNIV_INLINE +fil_addr_t +flst_get_next_addr( +/*===============*/ + const flst_node_t* node, /*!< in: pointer to node */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + return(flst_read_addr(node + FLST_NEXT, mtr)); +} + +/********************************************************************//** +Gets list prev node address. +@return file address */ +UNIV_INLINE +fil_addr_t +flst_get_prev_addr( +/*===============*/ + const flst_node_t* node, /*!< in: pointer to node */ + mtr_t* mtr) /*!< in: mini-transaction handle */ +{ + return(flst_read_addr(node + FLST_PREV, mtr)); +} diff --git a/storage/innobase/include/gis0rtree.h b/storage/innobase/include/gis0rtree.h index 5e812d10451..db70d80f21a 100644 --- a/storage/innobase/include/gis0rtree.h +++ b/storage/innobase/include/gis0rtree.h @@ -517,5 +517,5 @@ rtr_estimate_n_rows_in_range( const dtuple_t* tuple, page_cur_mode_t mode); -#include "gis0rtree.ic" +#include "gis0rtree.inl" #endif /*!< gis0rtree.h */ diff --git a/storage/innobase/include/gis0rtree.ic b/storage/innobase/include/gis0rtree.ic deleted file mode 100644 index 696aa1e2f5f..00000000000 --- a/storage/innobase/include/gis0rtree.ic +++ /dev/null @@ -1,266 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2014, Oracle and/or its affiliates. All Rights Reserved. -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 -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 gis0rtree.h -R-tree Inline code - -Created 2013/03/27 Jimmy Yang and Allen Lai -***********************************************************************/ - -/**************************************************************//** -Sets the child node mbr in a node pointer. */ -UNIV_INLINE -void -rtr_page_cal_mbr( -/*=============*/ - const dict_index_t* index, /*!< in: index */ - const buf_block_t* block, /*!< in: buffer block */ - rtr_mbr_t* rtr_mbr,/*!< out: MBR encapsulates the page */ - mem_heap_t* heap) /*!< in: heap for the memory - allocation */ -{ - page_t* page; - rec_t* rec; - byte* field; - ulint len; - rec_offs* offsets = NULL; - double bmin, bmax; - double* amin; - double* amax; - ulint inc = 0; - double* mbr; - - rtr_mbr->xmin = DBL_MAX; - rtr_mbr->ymin = DBL_MAX; - rtr_mbr->xmax = -DBL_MAX; - rtr_mbr->ymax = -DBL_MAX; - - mbr = reinterpret_cast(rtr_mbr); - - page = buf_block_get_frame(block); - - rec = page_rec_get_next(page_get_infimum_rec(page)); - offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), - ULINT_UNDEFINED, &heap); - - do { - /* The mbr address is in the first field. */ - field = rec_get_nth_field(rec, offsets, 0, &len); - - ut_ad(len == DATA_MBR_LEN); - inc = 0; - for (unsigned i = 0; i < SPDIMS; i++) { - bmin = mach_double_read(field + inc); - bmax = mach_double_read(field + inc + sizeof(double)); - - amin = mbr + i * SPDIMS; - amax = mbr + i * SPDIMS + 1; - - if (*amin > bmin) - *amin = bmin; - if (*amax < bmax) - *amax = bmax; - - inc += 2 * sizeof(double); - } - - rec = page_rec_get_next(rec); - - if (rec == NULL) { - break; - } - } while (!page_rec_is_supremum(rec)); -} - -/**************************************************************//** -push a nonleaf index node to the search path */ -UNIV_INLINE -void -rtr_non_leaf_stack_push( -/*====================*/ - rtr_node_path_t* path, /*!< in/out: search path */ - ulint pageno, /*!< in: pageno to insert */ - node_seq_t seq_no, /*!< in: Node sequence num */ - ulint level, /*!< in: index page level */ - ulint child_no, /*!< in: child page no */ - btr_pcur_t* cursor, /*!< in: position cursor */ - double mbr_inc) /*!< in: MBR needs to be - enlarged */ -{ - node_visit_t insert_val; - - insert_val.page_no = pageno; - insert_val.seq_no = seq_no; - insert_val.level = level; - insert_val.child_no = child_no; - insert_val.cursor = cursor; - insert_val.mbr_inc = mbr_inc; - - path->push_back(insert_val); - -#ifdef RTR_SEARCH_DIAGNOSTIC - fprintf(stderr, "INNODB_RTR: Push page %d, level %d, seq %d" - " to search stack \n", - static_cast(pageno), static_cast(level), - static_cast(seq_no)); -#endif /* RTR_SEARCH_DIAGNOSTIC */ -} - -/*****************************************************************//** -Allocates a new Split Sequence Number. -@return new SSN id */ -UNIV_INLINE -node_seq_t -rtr_get_new_ssn_id( -/*===============*/ - dict_index_t* index) /*!< in/out: the index struct */ -{ - node_seq_t ssn= my_atomic_add32_explicit(&index->rtr_ssn, 1, - MY_MEMORY_ORDER_RELAXED); - return ssn + 1; -} -/*****************************************************************//** -Get the current Split Sequence Number. -@return current SSN id */ -UNIV_INLINE -node_seq_t -rtr_get_current_ssn_id( -/*===================*/ - dict_index_t* index) /*!< in: index struct */ -{ - return my_atomic_load32_explicit(&index->rtr_ssn, MY_MEMORY_ORDER_RELAXED); -} - -/*********************************************************************//** -Sets pointer to the data and length in a field. */ -UNIV_INLINE -void -rtr_write_mbr( -/*==========*/ - byte* data, /*!< out: data */ - const rtr_mbr_t* mbr) /*!< in: data */ -{ - const double* my_mbr = reinterpret_cast(mbr); - - for (unsigned i = 0; i < SPDIMS * 2; i++) { - mach_double_write(data + i * sizeof(double), my_mbr[i]); - } -} - -/*********************************************************************//** -Sets pointer to the data and length in a field. */ -UNIV_INLINE -void -rtr_read_mbr( -/*==========*/ - const byte* data, /*!< in: data */ - rtr_mbr_t* mbr) /*!< out: MBR */ -{ - for (unsigned i = 0; i < SPDIMS * 2; i++) { - (reinterpret_cast(mbr))[i] = mach_double_read( - data - + i * sizeof(double)); - } -} - -/*********************************************************//** -Returns the R-Tree node stored in the parent search path -@return pointer to R-Tree cursor component in the parent path, -NULL if parent path is empty or index is larger than num of items contained */ -UNIV_INLINE -node_visit_t* -rtr_get_parent_node( -/*================*/ - btr_cur_t* btr_cur, /*!< in: persistent cursor */ - ulint level, /*!< in: index level of buffer page */ - ulint is_insert) /*!< in: whether it is insert */ -{ - ulint num; - ulint tree_height = btr_cur->tree_height; - node_visit_t* found_node = NULL; - - if (level >= tree_height) { - return(NULL); - } - - mutex_enter(&btr_cur->rtr_info->rtr_path_mutex); - - num = btr_cur->rtr_info->parent_path->size(); - - if (!num) { - mutex_exit(&btr_cur->rtr_info->rtr_path_mutex); - return(NULL); - } - - if (is_insert) { - ulint idx = tree_height - level - 1; - ut_ad(idx < num); - - found_node = &(*btr_cur->rtr_info->parent_path)[idx]; - } else { - node_visit_t* node; - - while (num > 0) { - node = &(*btr_cur->rtr_info->parent_path)[num - 1]; - - if (node->level == level) { - found_node = node; - break; - } - num--; - } - } - - mutex_exit(&btr_cur->rtr_info->rtr_path_mutex); - - return(found_node); -} - -/*********************************************************//** -Returns the R-Tree cursor stored in the parent search path -@return pointer to R-Tree cursor component */ -UNIV_INLINE -btr_pcur_t* -rtr_get_parent_cursor( -/*==================*/ - btr_cur_t* btr_cur, /*!< in: persistent cursor */ - ulint level, /*!< in: index level of buffer page */ - ulint is_insert) /*!< in: whether insert operation */ -{ - node_visit_t* found_node = rtr_get_parent_node( - btr_cur, level, is_insert); - - return((found_node) ? found_node->cursor : NULL); -} - -/********************************************************************//** -Reinitialize a R-Tree search info in btr_cur_t */ -UNIV_INLINE -void -rtr_info_reinit_in_cursor( -/************************/ - btr_cur_t* cursor, /*!< in/out: tree cursor */ - dict_index_t* index, /*!< in: index struct */ - bool need_prdt) /*!< in: Whether predicate lock is - needed */ -{ - rtr_clean_rtr_info(cursor->rtr_info, false); - rtr_init_rtr_info(cursor->rtr_info, need_prdt, cursor, index, true); -} diff --git a/storage/innobase/include/gis0rtree.inl b/storage/innobase/include/gis0rtree.inl new file mode 100644 index 00000000000..696aa1e2f5f --- /dev/null +++ b/storage/innobase/include/gis0rtree.inl @@ -0,0 +1,266 @@ +/***************************************************************************** + +Copyright (c) 2014, Oracle and/or its affiliates. All Rights Reserved. +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 +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 gis0rtree.h +R-tree Inline code + +Created 2013/03/27 Jimmy Yang and Allen Lai +***********************************************************************/ + +/**************************************************************//** +Sets the child node mbr in a node pointer. */ +UNIV_INLINE +void +rtr_page_cal_mbr( +/*=============*/ + const dict_index_t* index, /*!< in: index */ + const buf_block_t* block, /*!< in: buffer block */ + rtr_mbr_t* rtr_mbr,/*!< out: MBR encapsulates the page */ + mem_heap_t* heap) /*!< in: heap for the memory + allocation */ +{ + page_t* page; + rec_t* rec; + byte* field; + ulint len; + rec_offs* offsets = NULL; + double bmin, bmax; + double* amin; + double* amax; + ulint inc = 0; + double* mbr; + + rtr_mbr->xmin = DBL_MAX; + rtr_mbr->ymin = DBL_MAX; + rtr_mbr->xmax = -DBL_MAX; + rtr_mbr->ymax = -DBL_MAX; + + mbr = reinterpret_cast(rtr_mbr); + + page = buf_block_get_frame(block); + + rec = page_rec_get_next(page_get_infimum_rec(page)); + offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), + ULINT_UNDEFINED, &heap); + + do { + /* The mbr address is in the first field. */ + field = rec_get_nth_field(rec, offsets, 0, &len); + + ut_ad(len == DATA_MBR_LEN); + inc = 0; + for (unsigned i = 0; i < SPDIMS; i++) { + bmin = mach_double_read(field + inc); + bmax = mach_double_read(field + inc + sizeof(double)); + + amin = mbr + i * SPDIMS; + amax = mbr + i * SPDIMS + 1; + + if (*amin > bmin) + *amin = bmin; + if (*amax < bmax) + *amax = bmax; + + inc += 2 * sizeof(double); + } + + rec = page_rec_get_next(rec); + + if (rec == NULL) { + break; + } + } while (!page_rec_is_supremum(rec)); +} + +/**************************************************************//** +push a nonleaf index node to the search path */ +UNIV_INLINE +void +rtr_non_leaf_stack_push( +/*====================*/ + rtr_node_path_t* path, /*!< in/out: search path */ + ulint pageno, /*!< in: pageno to insert */ + node_seq_t seq_no, /*!< in: Node sequence num */ + ulint level, /*!< in: index page level */ + ulint child_no, /*!< in: child page no */ + btr_pcur_t* cursor, /*!< in: position cursor */ + double mbr_inc) /*!< in: MBR needs to be + enlarged */ +{ + node_visit_t insert_val; + + insert_val.page_no = pageno; + insert_val.seq_no = seq_no; + insert_val.level = level; + insert_val.child_no = child_no; + insert_val.cursor = cursor; + insert_val.mbr_inc = mbr_inc; + + path->push_back(insert_val); + +#ifdef RTR_SEARCH_DIAGNOSTIC + fprintf(stderr, "INNODB_RTR: Push page %d, level %d, seq %d" + " to search stack \n", + static_cast(pageno), static_cast(level), + static_cast(seq_no)); +#endif /* RTR_SEARCH_DIAGNOSTIC */ +} + +/*****************************************************************//** +Allocates a new Split Sequence Number. +@return new SSN id */ +UNIV_INLINE +node_seq_t +rtr_get_new_ssn_id( +/*===============*/ + dict_index_t* index) /*!< in/out: the index struct */ +{ + node_seq_t ssn= my_atomic_add32_explicit(&index->rtr_ssn, 1, + MY_MEMORY_ORDER_RELAXED); + return ssn + 1; +} +/*****************************************************************//** +Get the current Split Sequence Number. +@return current SSN id */ +UNIV_INLINE +node_seq_t +rtr_get_current_ssn_id( +/*===================*/ + dict_index_t* index) /*!< in: index struct */ +{ + return my_atomic_load32_explicit(&index->rtr_ssn, MY_MEMORY_ORDER_RELAXED); +} + +/*********************************************************************//** +Sets pointer to the data and length in a field. */ +UNIV_INLINE +void +rtr_write_mbr( +/*==========*/ + byte* data, /*!< out: data */ + const rtr_mbr_t* mbr) /*!< in: data */ +{ + const double* my_mbr = reinterpret_cast(mbr); + + for (unsigned i = 0; i < SPDIMS * 2; i++) { + mach_double_write(data + i * sizeof(double), my_mbr[i]); + } +} + +/*********************************************************************//** +Sets pointer to the data and length in a field. */ +UNIV_INLINE +void +rtr_read_mbr( +/*==========*/ + const byte* data, /*!< in: data */ + rtr_mbr_t* mbr) /*!< out: MBR */ +{ + for (unsigned i = 0; i < SPDIMS * 2; i++) { + (reinterpret_cast(mbr))[i] = mach_double_read( + data + + i * sizeof(double)); + } +} + +/*********************************************************//** +Returns the R-Tree node stored in the parent search path +@return pointer to R-Tree cursor component in the parent path, +NULL if parent path is empty or index is larger than num of items contained */ +UNIV_INLINE +node_visit_t* +rtr_get_parent_node( +/*================*/ + btr_cur_t* btr_cur, /*!< in: persistent cursor */ + ulint level, /*!< in: index level of buffer page */ + ulint is_insert) /*!< in: whether it is insert */ +{ + ulint num; + ulint tree_height = btr_cur->tree_height; + node_visit_t* found_node = NULL; + + if (level >= tree_height) { + return(NULL); + } + + mutex_enter(&btr_cur->rtr_info->rtr_path_mutex); + + num = btr_cur->rtr_info->parent_path->size(); + + if (!num) { + mutex_exit(&btr_cur->rtr_info->rtr_path_mutex); + return(NULL); + } + + if (is_insert) { + ulint idx = tree_height - level - 1; + ut_ad(idx < num); + + found_node = &(*btr_cur->rtr_info->parent_path)[idx]; + } else { + node_visit_t* node; + + while (num > 0) { + node = &(*btr_cur->rtr_info->parent_path)[num - 1]; + + if (node->level == level) { + found_node = node; + break; + } + num--; + } + } + + mutex_exit(&btr_cur->rtr_info->rtr_path_mutex); + + return(found_node); +} + +/*********************************************************//** +Returns the R-Tree cursor stored in the parent search path +@return pointer to R-Tree cursor component */ +UNIV_INLINE +btr_pcur_t* +rtr_get_parent_cursor( +/*==================*/ + btr_cur_t* btr_cur, /*!< in: persistent cursor */ + ulint level, /*!< in: index level of buffer page */ + ulint is_insert) /*!< in: whether insert operation */ +{ + node_visit_t* found_node = rtr_get_parent_node( + btr_cur, level, is_insert); + + return((found_node) ? found_node->cursor : NULL); +} + +/********************************************************************//** +Reinitialize a R-Tree search info in btr_cur_t */ +UNIV_INLINE +void +rtr_info_reinit_in_cursor( +/************************/ + btr_cur_t* cursor, /*!< in/out: tree cursor */ + dict_index_t* index, /*!< in: index struct */ + bool need_prdt) /*!< in: Whether predicate lock is + needed */ +{ + rtr_clean_rtr_info(cursor->rtr_info, false); + rtr_init_rtr_info(cursor->rtr_info, need_prdt, cursor, index, true); +} diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h index 1944309c8ec..b4a28e44e04 100644 --- a/storage/innobase/include/ha0ha.h +++ b/storage/innobase/include/ha0ha.h @@ -236,6 +236,6 @@ hash_assert_can_search( #define hash_assert_can_search(t, f) #endif /* UNIV_DEBUG */ -#include "ha0ha.ic" +#include "ha0ha.inl" #endif diff --git a/storage/innobase/include/ha0ha.ic b/storage/innobase/include/ha0ha.ic deleted file mode 100644 index 0612ef1bb25..00000000000 --- a/storage/innobase/include/ha0ha.ic +++ /dev/null @@ -1,242 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 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/ha0ha.ic -The hash table with external chains - -Created 8/18/1994 Heikki Tuuri -*************************************************************************/ - -#ifdef BTR_CUR_HASH_ADAPT -#include "ut0rnd.h" -#include "mem0mem.h" -#include "btr0types.h" - -/******************************************************************//** -Gets a hash node data. -@return pointer to the data */ -UNIV_INLINE -const rec_t* -ha_node_get_data( -/*=============*/ - const ha_node_t* node) /*!< in: hash chain node */ -{ - return(node->data); -} - -/******************************************************************//** -Sets hash node data. */ -UNIV_INLINE -void -ha_node_set_data_func( -/*==================*/ - ha_node_t* node, /*!< in: hash chain node */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - buf_block_t* block, /*!< in: buffer block containing the data */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - const rec_t* data) /*!< in: pointer to the data */ -{ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - node->block = block; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - node->data = data; -} - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/** Sets hash node data. -@param n in: hash chain node -@param b in: buffer block containing the data -@param d in: pointer to the data */ -# define ha_node_set_data(n,b,d) ha_node_set_data_func(n,b,d) -#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -/** Sets hash node data. -@param n in: hash chain node -@param b in: buffer block containing the data -@param d in: pointer to the data */ -# define ha_node_set_data(n,b,d) ha_node_set_data_func(n,d) -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - -/******************************************************************//** -Gets the next node in a hash chain. -@return next node, NULL if none */ -UNIV_INLINE -ha_node_t* -ha_chain_get_next( -/*==============*/ - const ha_node_t* node) /*!< in: hash chain node */ -{ - return(node->next); -} - -/******************************************************************//** -Gets the first node in a hash chain. -@return first node, NULL if none */ -UNIV_INLINE -ha_node_t* -ha_chain_get_first( -/*===============*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold value determining the chain */ -{ - return((ha_node_t*) - hash_get_nth_cell(table, hash_calc_hash(fold, table))->node); -} - -#ifdef UNIV_DEBUG -/********************************************************************//** -Assert that the synchronization object in a hash operation involving -possible change in the hash table is held. -Note that in case of mutexes we assert that mutex is owned while in case -of rw-locks we assert that it is held in exclusive mode. */ -UNIV_INLINE -void -hash_assert_can_modify( -/*===================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold value */ -{ - if (table->type == HASH_TABLE_SYNC_MUTEX) { - ut_ad(mutex_own(hash_get_mutex(table, fold))); - } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { -# ifdef UNIV_DEBUG - rw_lock_t* lock = hash_get_lock(table, fold); - ut_ad(rw_lock_own(lock, RW_LOCK_X)); -# endif - } else { - ut_ad(table->type == HASH_TABLE_SYNC_NONE); - } -} - -/********************************************************************//** -Assert that the synchronization object in a hash search operation is held. -Note that in case of mutexes we assert that mutex is owned while in case -of rw-locks we assert that it is held either in x-mode or s-mode. */ -UNIV_INLINE -void -hash_assert_can_search( -/*===================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold value */ -{ - if (table->type == HASH_TABLE_SYNC_MUTEX) { - ut_ad(mutex_own(hash_get_mutex(table, fold))); - } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { - ut_ad(rw_lock_own_flagged(hash_get_lock(table, fold), - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - } else { - ut_ad(table->type == HASH_TABLE_SYNC_NONE); - } -} -#endif /* UNIV_DEBUG */ - -/*************************************************************//** -Looks for an element in a hash table. -@return pointer to the data of the first hash table node in chain -having the fold number, NULL if not found */ -UNIV_INLINE -const rec_t* -ha_search_and_get_data( -/*===================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: folded value of the searched data */ -{ - hash_assert_can_search(table, fold); - ut_ad(btr_search_enabled); - - for (const ha_node_t* node = ha_chain_get_first(table, fold); - node != NULL; - node = ha_chain_get_next(node)) { - - if (node->fold == fold) { - - return(node->data); - } - } - - return(NULL); -} - -/*********************************************************//** -Looks for an element when we know the pointer to the data. -@return pointer to the hash table node, NULL if not found in the table */ -UNIV_INLINE -ha_node_t* -ha_search_with_data( -/*================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data) /*!< in: pointer to the data */ -{ - ha_node_t* node; - - hash_assert_can_search(table, fold); - - ut_ad(btr_search_enabled); - - node = ha_chain_get_first(table, fold); - - while (node) { - if (node->data == data) { - - return(node); - } - - node = ha_chain_get_next(node); - } - - return(NULL); -} - -/***********************************************************//** -Deletes a hash node. */ -void -ha_delete_hash_node( -/*================*/ - hash_table_t* table, /*!< in: hash table */ - ha_node_t* del_node); /*!< in: node to be deleted */ - -/*********************************************************//** -Looks for an element when we know the pointer to the data, and deletes -it from the hash table, if found. -@return TRUE if found */ -UNIV_INLINE -ibool -ha_search_and_delete_if_found( -/*==========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data) /*!< in: pointer to the data */ -{ - ha_node_t* node; - - hash_assert_can_modify(table, fold); - ut_ad(btr_search_enabled); - - node = ha_search_with_data(table, fold, data); - - if (node) { - ha_delete_hash_node(table, node); - - return(TRUE); - } - - return(FALSE); -} -#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/ha0ha.inl b/storage/innobase/include/ha0ha.inl new file mode 100644 index 00000000000..0612ef1bb25 --- /dev/null +++ b/storage/innobase/include/ha0ha.inl @@ -0,0 +1,242 @@ +/***************************************************************************** + +Copyright (c) 1994, 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/ha0ha.ic +The hash table with external chains + +Created 8/18/1994 Heikki Tuuri +*************************************************************************/ + +#ifdef BTR_CUR_HASH_ADAPT +#include "ut0rnd.h" +#include "mem0mem.h" +#include "btr0types.h" + +/******************************************************************//** +Gets a hash node data. +@return pointer to the data */ +UNIV_INLINE +const rec_t* +ha_node_get_data( +/*=============*/ + const ha_node_t* node) /*!< in: hash chain node */ +{ + return(node->data); +} + +/******************************************************************//** +Sets hash node data. */ +UNIV_INLINE +void +ha_node_set_data_func( +/*==================*/ + ha_node_t* node, /*!< in: hash chain node */ +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + buf_block_t* block, /*!< in: buffer block containing the data */ +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + const rec_t* data) /*!< in: pointer to the data */ +{ +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + node->block = block; +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + node->data = data; +} + +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +/** Sets hash node data. +@param n in: hash chain node +@param b in: buffer block containing the data +@param d in: pointer to the data */ +# define ha_node_set_data(n,b,d) ha_node_set_data_func(n,b,d) +#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +/** Sets hash node data. +@param n in: hash chain node +@param b in: buffer block containing the data +@param d in: pointer to the data */ +# define ha_node_set_data(n,b,d) ha_node_set_data_func(n,d) +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + +/******************************************************************//** +Gets the next node in a hash chain. +@return next node, NULL if none */ +UNIV_INLINE +ha_node_t* +ha_chain_get_next( +/*==============*/ + const ha_node_t* node) /*!< in: hash chain node */ +{ + return(node->next); +} + +/******************************************************************//** +Gets the first node in a hash chain. +@return first node, NULL if none */ +UNIV_INLINE +ha_node_t* +ha_chain_get_first( +/*===============*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold value determining the chain */ +{ + return((ha_node_t*) + hash_get_nth_cell(table, hash_calc_hash(fold, table))->node); +} + +#ifdef UNIV_DEBUG +/********************************************************************//** +Assert that the synchronization object in a hash operation involving +possible change in the hash table is held. +Note that in case of mutexes we assert that mutex is owned while in case +of rw-locks we assert that it is held in exclusive mode. */ +UNIV_INLINE +void +hash_assert_can_modify( +/*===================*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold value */ +{ + if (table->type == HASH_TABLE_SYNC_MUTEX) { + ut_ad(mutex_own(hash_get_mutex(table, fold))); + } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { +# ifdef UNIV_DEBUG + rw_lock_t* lock = hash_get_lock(table, fold); + ut_ad(rw_lock_own(lock, RW_LOCK_X)); +# endif + } else { + ut_ad(table->type == HASH_TABLE_SYNC_NONE); + } +} + +/********************************************************************//** +Assert that the synchronization object in a hash search operation is held. +Note that in case of mutexes we assert that mutex is owned while in case +of rw-locks we assert that it is held either in x-mode or s-mode. */ +UNIV_INLINE +void +hash_assert_can_search( +/*===================*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold value */ +{ + if (table->type == HASH_TABLE_SYNC_MUTEX) { + ut_ad(mutex_own(hash_get_mutex(table, fold))); + } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { + ut_ad(rw_lock_own_flagged(hash_get_lock(table, fold), + RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); + } else { + ut_ad(table->type == HASH_TABLE_SYNC_NONE); + } +} +#endif /* UNIV_DEBUG */ + +/*************************************************************//** +Looks for an element in a hash table. +@return pointer to the data of the first hash table node in chain +having the fold number, NULL if not found */ +UNIV_INLINE +const rec_t* +ha_search_and_get_data( +/*===================*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: folded value of the searched data */ +{ + hash_assert_can_search(table, fold); + ut_ad(btr_search_enabled); + + for (const ha_node_t* node = ha_chain_get_first(table, fold); + node != NULL; + node = ha_chain_get_next(node)) { + + if (node->fold == fold) { + + return(node->data); + } + } + + return(NULL); +} + +/*********************************************************//** +Looks for an element when we know the pointer to the data. +@return pointer to the hash table node, NULL if not found in the table */ +UNIV_INLINE +ha_node_t* +ha_search_with_data( +/*================*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold, /*!< in: folded value of the searched data */ + const rec_t* data) /*!< in: pointer to the data */ +{ + ha_node_t* node; + + hash_assert_can_search(table, fold); + + ut_ad(btr_search_enabled); + + node = ha_chain_get_first(table, fold); + + while (node) { + if (node->data == data) { + + return(node); + } + + node = ha_chain_get_next(node); + } + + return(NULL); +} + +/***********************************************************//** +Deletes a hash node. */ +void +ha_delete_hash_node( +/*================*/ + hash_table_t* table, /*!< in: hash table */ + ha_node_t* del_node); /*!< in: node to be deleted */ + +/*********************************************************//** +Looks for an element when we know the pointer to the data, and deletes +it from the hash table, if found. +@return TRUE if found */ +UNIV_INLINE +ibool +ha_search_and_delete_if_found( +/*==========================*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold, /*!< in: folded value of the searched data */ + const rec_t* data) /*!< in: pointer to the data */ +{ + ha_node_t* node; + + hash_assert_can_modify(table, fold); + ut_ad(btr_search_enabled); + + node = ha_search_with_data(table, fold, data); + + if (node) { + ha_delete_hash_node(table, node); + + return(TRUE); + } + + return(FALSE); +} +#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/ha0storage.h b/storage/innobase/include/ha0storage.h index db23ddc66ed..fdf50a2ee4a 100644 --- a/storage/innobase/include/ha0storage.h +++ b/storage/innobase/include/ha0storage.h @@ -132,6 +132,6 @@ ha_storage_get_size( /*================*/ const ha_storage_t* storage); /*!< in: hash storage */ -#include "ha0storage.ic" +#include "ha0storage.inl" #endif /* ha0storage_h */ diff --git a/storage/innobase/include/ha0storage.ic b/storage/innobase/include/ha0storage.ic deleted file mode 100644 index 8cc487faf47..00000000000 --- a/storage/innobase/include/ha0storage.ic +++ /dev/null @@ -1,144 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2007, 2013, 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/ha0storage.ic -Hash storage. -Provides a data structure that stores chunks of data in -its own storage, avoiding duplicates. - -Created September 24, 2007 Vasil Dimov -*******************************************************/ - -#include "hash0hash.h" -#include "mem0mem.h" - -/** Hash storage for strings */ -struct ha_storage_t { - mem_heap_t* heap; /*!< memory heap from which memory is - allocated */ - hash_table_t* hash; /*!< hash table used to avoid - duplicates */ -}; - -/** Objects of this type are stored in ha_storage_t */ -struct ha_storage_node_t { - ulint data_len;/*!< length of the data */ - const void* data; /*!< pointer to data */ - ha_storage_node_t* next; /*!< next node in hash chain */ -}; - -/*******************************************************************//** -Creates a hash storage. If any of the parameters is 0, then a default -value is used. -@return own: hash storage */ -UNIV_INLINE -ha_storage_t* -ha_storage_create( -/*==============*/ - ulint initial_heap_bytes, /*!< in: initial heap's size */ - ulint initial_hash_cells) /*!< in: initial number of cells - in the hash table */ -{ - ha_storage_t* storage; - mem_heap_t* heap; - - if (initial_heap_bytes == 0) { - - initial_heap_bytes = HA_STORAGE_DEFAULT_HEAP_BYTES; - } - - if (initial_hash_cells == 0) { - - initial_hash_cells = HA_STORAGE_DEFAULT_HASH_CELLS; - } - - /* we put "storage" within "storage->heap" */ - - heap = mem_heap_create(sizeof(ha_storage_t) - + initial_heap_bytes); - - storage = (ha_storage_t*) mem_heap_alloc(heap, - sizeof(ha_storage_t)); - - storage->heap = heap; - storage->hash = hash_create(initial_hash_cells); - - return(storage); -} - -/*******************************************************************//** -Empties a hash storage, freeing memory occupied by data chunks. -This invalidates any pointers previously returned by ha_storage_put(). -The hash storage is not invalidated itself and can be used again. */ -UNIV_INLINE -void -ha_storage_empty( -/*=============*/ - ha_storage_t** storage) /*!< in/out: hash storage */ -{ - ha_storage_t temp_storage; - - temp_storage.heap = (*storage)->heap; - temp_storage.hash = (*storage)->hash; - - hash_table_clear(temp_storage.hash); - mem_heap_empty(temp_storage.heap); - - *storage = (ha_storage_t*) mem_heap_alloc(temp_storage.heap, - sizeof(ha_storage_t)); - - (*storage)->heap = temp_storage.heap; - (*storage)->hash = temp_storage.hash; -} - -/*******************************************************************//** -Frees a hash storage and everything it contains, it cannot be used after -this call. -This invalidates any pointers previously returned by ha_storage_put(). */ -UNIV_INLINE -void -ha_storage_free( -/*============*/ - ha_storage_t* storage) /*!< in, own: hash storage */ -{ - /* order is important because the pointer storage->hash is - within the heap */ - hash_table_free(storage->hash); - mem_heap_free(storage->heap); -} - -/*******************************************************************//** -Gets the size of the memory used by a storage. -@return bytes used */ -UNIV_INLINE -ulint -ha_storage_get_size( -/*================*/ - const ha_storage_t* storage) /*!< in: hash storage */ -{ - ulint ret; - - ret = mem_heap_get_size(storage->heap); - - /* this assumes hash->heap and hash->heaps are NULL */ - ret += sizeof(hash_table_t); - ret += sizeof(hash_cell_t) * hash_get_n_cells(storage->hash); - - return(ret); -} diff --git a/storage/innobase/include/ha0storage.inl b/storage/innobase/include/ha0storage.inl new file mode 100644 index 00000000000..8cc487faf47 --- /dev/null +++ b/storage/innobase/include/ha0storage.inl @@ -0,0 +1,144 @@ +/***************************************************************************** + +Copyright (c) 2007, 2013, 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/ha0storage.ic +Hash storage. +Provides a data structure that stores chunks of data in +its own storage, avoiding duplicates. + +Created September 24, 2007 Vasil Dimov +*******************************************************/ + +#include "hash0hash.h" +#include "mem0mem.h" + +/** Hash storage for strings */ +struct ha_storage_t { + mem_heap_t* heap; /*!< memory heap from which memory is + allocated */ + hash_table_t* hash; /*!< hash table used to avoid + duplicates */ +}; + +/** Objects of this type are stored in ha_storage_t */ +struct ha_storage_node_t { + ulint data_len;/*!< length of the data */ + const void* data; /*!< pointer to data */ + ha_storage_node_t* next; /*!< next node in hash chain */ +}; + +/*******************************************************************//** +Creates a hash storage. If any of the parameters is 0, then a default +value is used. +@return own: hash storage */ +UNIV_INLINE +ha_storage_t* +ha_storage_create( +/*==============*/ + ulint initial_heap_bytes, /*!< in: initial heap's size */ + ulint initial_hash_cells) /*!< in: initial number of cells + in the hash table */ +{ + ha_storage_t* storage; + mem_heap_t* heap; + + if (initial_heap_bytes == 0) { + + initial_heap_bytes = HA_STORAGE_DEFAULT_HEAP_BYTES; + } + + if (initial_hash_cells == 0) { + + initial_hash_cells = HA_STORAGE_DEFAULT_HASH_CELLS; + } + + /* we put "storage" within "storage->heap" */ + + heap = mem_heap_create(sizeof(ha_storage_t) + + initial_heap_bytes); + + storage = (ha_storage_t*) mem_heap_alloc(heap, + sizeof(ha_storage_t)); + + storage->heap = heap; + storage->hash = hash_create(initial_hash_cells); + + return(storage); +} + +/*******************************************************************//** +Empties a hash storage, freeing memory occupied by data chunks. +This invalidates any pointers previously returned by ha_storage_put(). +The hash storage is not invalidated itself and can be used again. */ +UNIV_INLINE +void +ha_storage_empty( +/*=============*/ + ha_storage_t** storage) /*!< in/out: hash storage */ +{ + ha_storage_t temp_storage; + + temp_storage.heap = (*storage)->heap; + temp_storage.hash = (*storage)->hash; + + hash_table_clear(temp_storage.hash); + mem_heap_empty(temp_storage.heap); + + *storage = (ha_storage_t*) mem_heap_alloc(temp_storage.heap, + sizeof(ha_storage_t)); + + (*storage)->heap = temp_storage.heap; + (*storage)->hash = temp_storage.hash; +} + +/*******************************************************************//** +Frees a hash storage and everything it contains, it cannot be used after +this call. +This invalidates any pointers previously returned by ha_storage_put(). */ +UNIV_INLINE +void +ha_storage_free( +/*============*/ + ha_storage_t* storage) /*!< in, own: hash storage */ +{ + /* order is important because the pointer storage->hash is + within the heap */ + hash_table_free(storage->hash); + mem_heap_free(storage->heap); +} + +/*******************************************************************//** +Gets the size of the memory used by a storage. +@return bytes used */ +UNIV_INLINE +ulint +ha_storage_get_size( +/*================*/ + const ha_storage_t* storage) /*!< in: hash storage */ +{ + ulint ret; + + ret = mem_heap_get_size(storage->heap); + + /* this assumes hash->heap and hash->heaps are NULL */ + ret += sizeof(hash_table_t); + ret += sizeof(hash_cell_t) * hash_get_n_cells(storage->hash); + + return(ret); +} diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 4f55b051d80..e2565c62169 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -520,6 +520,6 @@ struct hash_table_t { #endif /* UNIV_DEBUG */ }; -#include "hash0hash.ic" +#include "hash0hash.inl" #endif diff --git a/storage/innobase/include/hash0hash.ic b/storage/innobase/include/hash0hash.ic deleted file mode 100644 index d6dd104572f..00000000000 --- a/storage/innobase/include/hash0hash.ic +++ /dev/null @@ -1,277 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1997, 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/hash0hash.ic -The simple hash table utility - -Created 5/20/1997 Heikki Tuuri -*******************************************************/ - -#include "ut0rnd.h" - -/************************************************************//** -Gets the nth cell in a hash table. -@return pointer to cell */ -UNIV_INLINE -hash_cell_t* -hash_get_nth_cell( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint n) /*!< in: cell index */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(n < table->n_cells); - - return(table->array + n); -} - -/*************************************************************//** -Clears a hash table so that all the cells become empty. */ -UNIV_INLINE -void -hash_table_clear( -/*=============*/ - hash_table_t* table) /*!< in/out: hash table */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - memset(table->array, 0x0, - table->n_cells * sizeof(*table->array)); -} - -/*************************************************************//** -Returns the number of cells in a hash table. -@return number of cells */ -UNIV_INLINE -ulint -hash_get_n_cells( -/*=============*/ - hash_table_t* table) /*!< in: table */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - return(table->n_cells); -} - -/**************************************************************//** -Calculates the hash value from a folded value. -@return hashed value */ -UNIV_INLINE -ulint -hash_calc_hash( -/*===========*/ - ulint fold, /*!< in: folded value */ - hash_table_t* table) /*!< in: hash table */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - return(ut_hash_ulint(fold, table->n_cells)); -} - -/************************************************************//** -Gets the sync object index for a fold value in a hash table. -@return index */ -UNIV_INLINE -ulint -hash_get_sync_obj_index( -/*====================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type != HASH_TABLE_SYNC_NONE); - ut_ad(ut_is_2pow(table->n_sync_obj)); - return(ut_2pow_remainder(hash_calc_hash(fold, table), - table->n_sync_obj)); -} - -/************************************************************//** -Gets the nth heap in a hash table. -@return mem heap */ -UNIV_INLINE -mem_heap_t* -hash_get_nth_heap( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i) /*!< in: index of the heap */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type != HASH_TABLE_SYNC_NONE); - ut_ad(i < table->n_sync_obj); - - return(table->heaps[i]); -} - -/************************************************************//** -Gets the heap for a fold value in a hash table. -@return mem heap */ -UNIV_INLINE -mem_heap_t* -hash_get_heap( -/*==========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ulint i; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - if (table->heap) { - return(table->heap); - } - - i = hash_get_sync_obj_index(table, fold); - - return(hash_get_nth_heap(table, i)); -} - -/************************************************************//** -Gets the nth mutex in a hash table. -@return mutex */ -UNIV_INLINE -ib_mutex_t* -hash_get_nth_mutex( -/*===============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i) /*!< in: index of the mutex */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); - ut_ad(i < table->n_sync_obj); - - return(table->sync_obj.mutexes + i); -} - -/************************************************************//** -Gets the mutex for a fold value in a hash table. -@return mutex */ -UNIV_INLINE -ib_mutex_t* -hash_get_mutex( -/*===========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ulint i; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - i = hash_get_sync_obj_index(table, fold); - - return(hash_get_nth_mutex(table, i)); -} - -/************************************************************//** -Gets the nth rw_lock in a hash table. -@return rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_get_nth_lock( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i) /*!< in: index of the rw_lock */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - ut_ad(i < table->n_sync_obj); - - return(table->sync_obj.rw_locks + i); -} - -/************************************************************//** -Gets the rw_lock for a fold value in a hash table. -@return rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_get_lock( -/*==========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ulint i; - - ut_ad(table); - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - i = hash_get_sync_obj_index(table, fold); - - return(hash_get_nth_lock(table, i)); -} - -/** If not appropriate rw_lock for a fold value in a hash table, -relock S-lock the another rw_lock until appropriate for a fold value. -@param[in] hash_lock latched rw_lock to be confirmed -@param[in] table hash table -@param[in] fold fold value -@return latched rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_lock_s_confirm( - rw_lock_t* hash_lock, - hash_table_t* table, - ulint fold) -{ - ut_ad(rw_lock_own(hash_lock, RW_LOCK_S)); - - rw_lock_t* hash_lock_tmp = hash_get_lock(table, fold); - - while (hash_lock_tmp != hash_lock) { - rw_lock_s_unlock(hash_lock); - hash_lock = hash_lock_tmp; - rw_lock_s_lock(hash_lock); - hash_lock_tmp = hash_get_lock(table, fold); - } - - return(hash_lock); -} - -/** If not appropriate rw_lock for a fold value in a hash table, -relock X-lock the another rw_lock until appropriate for a fold value. -@param[in] hash_lock latched rw_lock to be confirmed -@param[in] table hash table -@param[in] fold fold value -@return latched rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_lock_x_confirm( - rw_lock_t* hash_lock, - hash_table_t* table, - ulint fold) -{ - ut_ad(rw_lock_own(hash_lock, RW_LOCK_X)); - - rw_lock_t* hash_lock_tmp = hash_get_lock(table, fold); - - while (hash_lock_tmp != hash_lock) { - rw_lock_x_unlock(hash_lock); - hash_lock = hash_lock_tmp; - rw_lock_x_lock(hash_lock); - hash_lock_tmp = hash_get_lock(table, fold); - } - - return(hash_lock); -} diff --git a/storage/innobase/include/hash0hash.inl b/storage/innobase/include/hash0hash.inl new file mode 100644 index 00000000000..d6dd104572f --- /dev/null +++ b/storage/innobase/include/hash0hash.inl @@ -0,0 +1,277 @@ +/***************************************************************************** + +Copyright (c) 1997, 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/hash0hash.ic +The simple hash table utility + +Created 5/20/1997 Heikki Tuuri +*******************************************************/ + +#include "ut0rnd.h" + +/************************************************************//** +Gets the nth cell in a hash table. +@return pointer to cell */ +UNIV_INLINE +hash_cell_t* +hash_get_nth_cell( +/*==============*/ + hash_table_t* table, /*!< in: hash table */ + ulint n) /*!< in: cell index */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + ut_ad(n < table->n_cells); + + return(table->array + n); +} + +/*************************************************************//** +Clears a hash table so that all the cells become empty. */ +UNIV_INLINE +void +hash_table_clear( +/*=============*/ + hash_table_t* table) /*!< in/out: hash table */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + memset(table->array, 0x0, + table->n_cells * sizeof(*table->array)); +} + +/*************************************************************//** +Returns the number of cells in a hash table. +@return number of cells */ +UNIV_INLINE +ulint +hash_get_n_cells( +/*=============*/ + hash_table_t* table) /*!< in: table */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + return(table->n_cells); +} + +/**************************************************************//** +Calculates the hash value from a folded value. +@return hashed value */ +UNIV_INLINE +ulint +hash_calc_hash( +/*===========*/ + ulint fold, /*!< in: folded value */ + hash_table_t* table) /*!< in: hash table */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + return(ut_hash_ulint(fold, table->n_cells)); +} + +/************************************************************//** +Gets the sync object index for a fold value in a hash table. +@return index */ +UNIV_INLINE +ulint +hash_get_sync_obj_index( +/*====================*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + ut_ad(table->type != HASH_TABLE_SYNC_NONE); + ut_ad(ut_is_2pow(table->n_sync_obj)); + return(ut_2pow_remainder(hash_calc_hash(fold, table), + table->n_sync_obj)); +} + +/************************************************************//** +Gets the nth heap in a hash table. +@return mem heap */ +UNIV_INLINE +mem_heap_t* +hash_get_nth_heap( +/*==============*/ + hash_table_t* table, /*!< in: hash table */ + ulint i) /*!< in: index of the heap */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + ut_ad(table->type != HASH_TABLE_SYNC_NONE); + ut_ad(i < table->n_sync_obj); + + return(table->heaps[i]); +} + +/************************************************************//** +Gets the heap for a fold value in a hash table. +@return mem heap */ +UNIV_INLINE +mem_heap_t* +hash_get_heap( +/*==========*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + ulint i; + + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + + if (table->heap) { + return(table->heap); + } + + i = hash_get_sync_obj_index(table, fold); + + return(hash_get_nth_heap(table, i)); +} + +/************************************************************//** +Gets the nth mutex in a hash table. +@return mutex */ +UNIV_INLINE +ib_mutex_t* +hash_get_nth_mutex( +/*===============*/ + hash_table_t* table, /*!< in: hash table */ + ulint i) /*!< in: index of the mutex */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); + ut_ad(i < table->n_sync_obj); + + return(table->sync_obj.mutexes + i); +} + +/************************************************************//** +Gets the mutex for a fold value in a hash table. +@return mutex */ +UNIV_INLINE +ib_mutex_t* +hash_get_mutex( +/*===========*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + ulint i; + + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + + i = hash_get_sync_obj_index(table, fold); + + return(hash_get_nth_mutex(table, i)); +} + +/************************************************************//** +Gets the nth rw_lock in a hash table. +@return rw_lock */ +UNIV_INLINE +rw_lock_t* +hash_get_nth_lock( +/*==============*/ + hash_table_t* table, /*!< in: hash table */ + ulint i) /*!< in: index of the rw_lock */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + ut_ad(i < table->n_sync_obj); + + return(table->sync_obj.rw_locks + i); +} + +/************************************************************//** +Gets the rw_lock for a fold value in a hash table. +@return rw_lock */ +UNIV_INLINE +rw_lock_t* +hash_get_lock( +/*==========*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + ulint i; + + ut_ad(table); + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + + i = hash_get_sync_obj_index(table, fold); + + return(hash_get_nth_lock(table, i)); +} + +/** If not appropriate rw_lock for a fold value in a hash table, +relock S-lock the another rw_lock until appropriate for a fold value. +@param[in] hash_lock latched rw_lock to be confirmed +@param[in] table hash table +@param[in] fold fold value +@return latched rw_lock */ +UNIV_INLINE +rw_lock_t* +hash_lock_s_confirm( + rw_lock_t* hash_lock, + hash_table_t* table, + ulint fold) +{ + ut_ad(rw_lock_own(hash_lock, RW_LOCK_S)); + + rw_lock_t* hash_lock_tmp = hash_get_lock(table, fold); + + while (hash_lock_tmp != hash_lock) { + rw_lock_s_unlock(hash_lock); + hash_lock = hash_lock_tmp; + rw_lock_s_lock(hash_lock); + hash_lock_tmp = hash_get_lock(table, fold); + } + + return(hash_lock); +} + +/** If not appropriate rw_lock for a fold value in a hash table, +relock X-lock the another rw_lock until appropriate for a fold value. +@param[in] hash_lock latched rw_lock to be confirmed +@param[in] table hash table +@param[in] fold fold value +@return latched rw_lock */ +UNIV_INLINE +rw_lock_t* +hash_lock_x_confirm( + rw_lock_t* hash_lock, + hash_table_t* table, + ulint fold) +{ + ut_ad(rw_lock_own(hash_lock, RW_LOCK_X)); + + rw_lock_t* hash_lock_tmp = hash_get_lock(table, fold); + + while (hash_lock_tmp != hash_lock) { + rw_lock_x_unlock(hash_lock); + hash_lock = hash_lock_tmp; + rw_lock_x_lock(hash_lock); + hash_lock_tmp = hash_get_lock(table, fold); + } + + return(hash_lock); +} diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 1a5214085de..75b37250d97 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -443,6 +443,6 @@ for the file segment from which the pages for the ibuf tree are allocated */ /* The insert buffer tree itself is always located in space 0. */ #define IBUF_SPACE_ID static_cast(0) -#include "ibuf0ibuf.ic" +#include "ibuf0ibuf.inl" #endif diff --git a/storage/innobase/include/ibuf0ibuf.ic b/storage/innobase/include/ibuf0ibuf.ic deleted file mode 100644 index 1b19d5450b7..00000000000 --- a/storage/innobase/include/ibuf0ibuf.ic +++ /dev/null @@ -1,341 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1997, 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/ibuf0ibuf.ic -Insert buffer - -Created 7/19/1997 Heikki Tuuri -*******************************************************/ - -#include "page0page.h" -#include "page0zip.h" -#include "fsp0types.h" -#include "buf0lru.h" - -/** An index page must contain at least UNIV_PAGE_SIZE / -IBUF_PAGE_SIZE_PER_FREE_SPACE bytes of free space for ibuf to try to -buffer inserts to this page. If there is this much of free space, the -corresponding bits are set in the ibuf bitmap. */ -#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32 - -/***************************************************************//** -Starts an insert buffer mini-transaction. */ -UNIV_INLINE -void -ibuf_mtr_start( -/*===========*/ - mtr_t* mtr) /*!< out: mini-transaction */ -{ - mtr_start(mtr); - mtr->enter_ibuf(); -} -/***************************************************************//** -Commits an insert buffer mini-transaction. */ -UNIV_INLINE -void -ibuf_mtr_commit( -/*============*/ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - ut_ad(mtr->is_inside_ibuf()); - ut_d(mtr->exit_ibuf()); - - mtr_commit(mtr); -} - -/** Insert buffer struct */ -struct ibuf_t{ - ulint size; /*!< current size of the ibuf index - tree, in pages */ - ulint max_size; /*!< recommended maximum size of the - ibuf index tree, in pages */ - ulint seg_size; /*!< allocated pages of the file - segment containing ibuf header and - tree */ - bool empty; /*!< Protected by the page - latch of the root page of the - insert buffer tree - (FSP_IBUF_TREE_ROOT_PAGE_NO). true - if and only if the insert - buffer tree is empty. */ - ulint free_list_len; /*!< length of the free list */ - 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 operations of each type - merged to index pages */ - ulint n_discarded_ops[IBUF_OP_COUNT]; - /*!< number of operations of each type - discarded without merging due to the - tablespace being deleted or the - index being dropped */ -}; - -/************************************************************************//** -Sets the free bit of the page in the ibuf bitmap. This is done in a separate -mini-transaction, hence this operation does not restrict further work to only -ibuf bitmap operations, which would result if the latch to the bitmap page -were kept. */ -void -ibuf_set_free_bits_func( -/*====================*/ - buf_block_t* block, /*!< in: index page of a non-clustered index; - free bit is reset if page level is 0 */ -#ifdef UNIV_IBUF_DEBUG - ulint max_val,/*!< in: ULINT_UNDEFINED or a maximum - value which the bits must have before - setting; this is for debugging */ -#endif /* UNIV_IBUF_DEBUG */ - ulint val); /*!< in: value to set: < 4 */ -#ifdef UNIV_IBUF_DEBUG -# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,max,v) -#else /* UNIV_IBUF_DEBUG */ -# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,v) -#endif /* UNIV_IBUF_DEBUG */ - -/**********************************************************************//** -A basic partial test if an insert to the insert buffer could be possible and -recommended. */ -UNIV_INLINE -ibool -ibuf_should_try( -/*============*/ - dict_index_t* index, /*!< in: index where to insert */ - ulint ignore_sec_unique) /*!< in: if != 0, we should - ignore UNIQUE constraint on - a secondary index when we - decide */ -{ - return(ibuf_use != IBUF_USE_NONE - && ibuf->max_size != 0 - && !dict_index_is_clust(index) - && !dict_index_is_spatial(index) - && index->table->quiesce == QUIESCE_NONE - && (ignore_sec_unique || !dict_index_is_unique(index)) - && srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE); -} - -/******************************************************************//** -Returns TRUE if the current OS thread is performing an insert buffer -routine. - -For instance, a read-ahead of non-ibuf pages is forbidden by threads -that are executing an insert buffer routine. -@return TRUE if inside an insert buffer routine */ -UNIV_INLINE -ibool -ibuf_inside( -/*========*/ - const mtr_t* mtr) /*!< in: mini-transaction */ -{ - 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 -the page -@return value for ibuf bitmap bits */ -UNIV_INLINE -ulint -ibuf_index_page_calc_free_bits( - ulint page_size, - ulint max_ins_size) -{ - ulint n; - ut_ad(ut_is_2pow(page_size)); - ut_ad(page_size > IBUF_PAGE_SIZE_PER_FREE_SPACE); - - n = max_ins_size / (page_size / IBUF_PAGE_SIZE_PER_FREE_SPACE); - - if (n == 3) { - n = 2; - } - - if (n > 3) { - n = 3; - } - - 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 */ -UNIV_INLINE -ulint -ibuf_index_page_calc_free_zip( -/*==========================*/ - const buf_block_t* block) /*!< in: buffer block */ -{ - ulint max_ins_size; - const page_zip_des_t* page_zip; - lint zip_max_ins; - - ut_ad(block->page.size.is_compressed()); - - /* Consider the maximum insert size on the uncompressed page - without reorganizing the page. We must not assume anything - about the compression ratio. If zip_max_ins > max_ins_size and - there is 1/4 garbage on the page, recompression after the - reorganize could fail, in theory. So, let us guarantee that - merging a buffered insert to a compressed page will always - succeed without reorganizing or recompressing the page, just - by using the page modification log. */ - max_ins_size = page_get_max_insert_size( - buf_block_get_frame(block), 1); - - page_zip = buf_block_get_page_zip(block); - zip_max_ins = page_zip_max_ins_size(page_zip, - FALSE/* not clustered */); - - if (zip_max_ins < 0) { - return(0); - } else if (max_ins_size > (ulint) zip_max_ins) { - max_ins_size = (ulint) zip_max_ins; - } - - return(ibuf_index_page_calc_free_bits(block->page.size.physical(), - max_ins_size)); -} - -/*********************************************************************//** -Translates the free space on a page to a value in the ibuf bitmap. -@return value for ibuf bitmap bits */ -UNIV_INLINE -ulint -ibuf_index_page_calc_free( -/*======================*/ - const buf_block_t* block) /*!< in: buffer block */ -{ - if (!block->page.size.is_compressed()) { - 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)); - } else { - return(ibuf_index_page_calc_free_zip(block)); - } -} - -/************************************************************************//** -Updates the free bits of an uncompressed page in the ibuf bitmap if -there is not enough free on the page any more. This is done in a -separate mini-transaction, hence this operation does not restrict -further work to only ibuf bitmap operations, which would result if the -latch to the bitmap page were kept. NOTE: The free bits in the insert -buffer bitmap must never exceed the free space on a page. It is -unsafe to increment the bits in a separately committed -mini-transaction, because in crash recovery, the free bits could -momentarily be set too high. It is only safe to use this function for -decrementing the free bits. Should more free space become available, -we must not update the free bits here, because that would break crash -recovery. */ -UNIV_INLINE -void -ibuf_update_free_bits_if_full( -/*==========================*/ - buf_block_t* block, /*!< in: index page to which we have added new - records; the free bits are updated if the - index is non-clustered and non-unique and - the page level is 0, and the page becomes - fuller */ - ulint max_ins_size,/*!< in: value of maximum insert size with - reorganize before the latest operation - performed to the page */ - ulint increase)/*!< in: upper limit for the additional space - used in the latest operation, if known, or - ULINT_UNDEFINED */ -{ - ulint before; - ulint after; - - ut_ad(buf_block_get_page_zip(block) == NULL); - - before = ibuf_index_page_calc_free_bits( - block->page.size.physical(), max_ins_size); - - if (max_ins_size >= increase) { -#if ULINT32_UNDEFINED <= UNIV_PAGE_SIZE_MAX -# error "ULINT32_UNDEFINED <= UNIV_PAGE_SIZE_MAX" -#endif - after = ibuf_index_page_calc_free_bits( - block->page.size.physical(), max_ins_size - increase); -#ifdef UNIV_IBUF_DEBUG - ut_a(after <= ibuf_index_page_calc_free(block)); -#endif - } else { - after = ibuf_index_page_calc_free(block); - } - - if (after == 0) { - /* We move the page to the front of the buffer pool LRU list: - the purpose of this is to prevent those pages to which we - cannot make inserts using the insert buffer from slipping - out of the buffer pool */ - - buf_page_make_young(&block->page); - } - - if (before > after) { - ibuf_set_free_bits(block, after, before); - } -} diff --git a/storage/innobase/include/ibuf0ibuf.inl b/storage/innobase/include/ibuf0ibuf.inl new file mode 100644 index 00000000000..1b19d5450b7 --- /dev/null +++ b/storage/innobase/include/ibuf0ibuf.inl @@ -0,0 +1,341 @@ +/***************************************************************************** + +Copyright (c) 1997, 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/ibuf0ibuf.ic +Insert buffer + +Created 7/19/1997 Heikki Tuuri +*******************************************************/ + +#include "page0page.h" +#include "page0zip.h" +#include "fsp0types.h" +#include "buf0lru.h" + +/** An index page must contain at least UNIV_PAGE_SIZE / +IBUF_PAGE_SIZE_PER_FREE_SPACE bytes of free space for ibuf to try to +buffer inserts to this page. If there is this much of free space, the +corresponding bits are set in the ibuf bitmap. */ +#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32 + +/***************************************************************//** +Starts an insert buffer mini-transaction. */ +UNIV_INLINE +void +ibuf_mtr_start( +/*===========*/ + mtr_t* mtr) /*!< out: mini-transaction */ +{ + mtr_start(mtr); + mtr->enter_ibuf(); +} +/***************************************************************//** +Commits an insert buffer mini-transaction. */ +UNIV_INLINE +void +ibuf_mtr_commit( +/*============*/ + mtr_t* mtr) /*!< in/out: mini-transaction */ +{ + ut_ad(mtr->is_inside_ibuf()); + ut_d(mtr->exit_ibuf()); + + mtr_commit(mtr); +} + +/** Insert buffer struct */ +struct ibuf_t{ + ulint size; /*!< current size of the ibuf index + tree, in pages */ + ulint max_size; /*!< recommended maximum size of the + ibuf index tree, in pages */ + ulint seg_size; /*!< allocated pages of the file + segment containing ibuf header and + tree */ + bool empty; /*!< Protected by the page + latch of the root page of the + insert buffer tree + (FSP_IBUF_TREE_ROOT_PAGE_NO). true + if and only if the insert + buffer tree is empty. */ + ulint free_list_len; /*!< length of the free list */ + 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 operations of each type + merged to index pages */ + ulint n_discarded_ops[IBUF_OP_COUNT]; + /*!< number of operations of each type + discarded without merging due to the + tablespace being deleted or the + index being dropped */ +}; + +/************************************************************************//** +Sets the free bit of the page in the ibuf bitmap. This is done in a separate +mini-transaction, hence this operation does not restrict further work to only +ibuf bitmap operations, which would result if the latch to the bitmap page +were kept. */ +void +ibuf_set_free_bits_func( +/*====================*/ + buf_block_t* block, /*!< in: index page of a non-clustered index; + free bit is reset if page level is 0 */ +#ifdef UNIV_IBUF_DEBUG + ulint max_val,/*!< in: ULINT_UNDEFINED or a maximum + value which the bits must have before + setting; this is for debugging */ +#endif /* UNIV_IBUF_DEBUG */ + ulint val); /*!< in: value to set: < 4 */ +#ifdef UNIV_IBUF_DEBUG +# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,max,v) +#else /* UNIV_IBUF_DEBUG */ +# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,v) +#endif /* UNIV_IBUF_DEBUG */ + +/**********************************************************************//** +A basic partial test if an insert to the insert buffer could be possible and +recommended. */ +UNIV_INLINE +ibool +ibuf_should_try( +/*============*/ + dict_index_t* index, /*!< in: index where to insert */ + ulint ignore_sec_unique) /*!< in: if != 0, we should + ignore UNIQUE constraint on + a secondary index when we + decide */ +{ + return(ibuf_use != IBUF_USE_NONE + && ibuf->max_size != 0 + && !dict_index_is_clust(index) + && !dict_index_is_spatial(index) + && index->table->quiesce == QUIESCE_NONE + && (ignore_sec_unique || !dict_index_is_unique(index)) + && srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE); +} + +/******************************************************************//** +Returns TRUE if the current OS thread is performing an insert buffer +routine. + +For instance, a read-ahead of non-ibuf pages is forbidden by threads +that are executing an insert buffer routine. +@return TRUE if inside an insert buffer routine */ +UNIV_INLINE +ibool +ibuf_inside( +/*========*/ + const mtr_t* mtr) /*!< in: mini-transaction */ +{ + 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 +the page +@return value for ibuf bitmap bits */ +UNIV_INLINE +ulint +ibuf_index_page_calc_free_bits( + ulint page_size, + ulint max_ins_size) +{ + ulint n; + ut_ad(ut_is_2pow(page_size)); + ut_ad(page_size > IBUF_PAGE_SIZE_PER_FREE_SPACE); + + n = max_ins_size / (page_size / IBUF_PAGE_SIZE_PER_FREE_SPACE); + + if (n == 3) { + n = 2; + } + + if (n > 3) { + n = 3; + } + + 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 */ +UNIV_INLINE +ulint +ibuf_index_page_calc_free_zip( +/*==========================*/ + const buf_block_t* block) /*!< in: buffer block */ +{ + ulint max_ins_size; + const page_zip_des_t* page_zip; + lint zip_max_ins; + + ut_ad(block->page.size.is_compressed()); + + /* Consider the maximum insert size on the uncompressed page + without reorganizing the page. We must not assume anything + about the compression ratio. If zip_max_ins > max_ins_size and + there is 1/4 garbage on the page, recompression after the + reorganize could fail, in theory. So, let us guarantee that + merging a buffered insert to a compressed page will always + succeed without reorganizing or recompressing the page, just + by using the page modification log. */ + max_ins_size = page_get_max_insert_size( + buf_block_get_frame(block), 1); + + page_zip = buf_block_get_page_zip(block); + zip_max_ins = page_zip_max_ins_size(page_zip, + FALSE/* not clustered */); + + if (zip_max_ins < 0) { + return(0); + } else if (max_ins_size > (ulint) zip_max_ins) { + max_ins_size = (ulint) zip_max_ins; + } + + return(ibuf_index_page_calc_free_bits(block->page.size.physical(), + max_ins_size)); +} + +/*********************************************************************//** +Translates the free space on a page to a value in the ibuf bitmap. +@return value for ibuf bitmap bits */ +UNIV_INLINE +ulint +ibuf_index_page_calc_free( +/*======================*/ + const buf_block_t* block) /*!< in: buffer block */ +{ + if (!block->page.size.is_compressed()) { + 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)); + } else { + return(ibuf_index_page_calc_free_zip(block)); + } +} + +/************************************************************************//** +Updates the free bits of an uncompressed page in the ibuf bitmap if +there is not enough free on the page any more. This is done in a +separate mini-transaction, hence this operation does not restrict +further work to only ibuf bitmap operations, which would result if the +latch to the bitmap page were kept. NOTE: The free bits in the insert +buffer bitmap must never exceed the free space on a page. It is +unsafe to increment the bits in a separately committed +mini-transaction, because in crash recovery, the free bits could +momentarily be set too high. It is only safe to use this function for +decrementing the free bits. Should more free space become available, +we must not update the free bits here, because that would break crash +recovery. */ +UNIV_INLINE +void +ibuf_update_free_bits_if_full( +/*==========================*/ + buf_block_t* block, /*!< in: index page to which we have added new + records; the free bits are updated if the + index is non-clustered and non-unique and + the page level is 0, and the page becomes + fuller */ + ulint max_ins_size,/*!< in: value of maximum insert size with + reorganize before the latest operation + performed to the page */ + ulint increase)/*!< in: upper limit for the additional space + used in the latest operation, if known, or + ULINT_UNDEFINED */ +{ + ulint before; + ulint after; + + ut_ad(buf_block_get_page_zip(block) == NULL); + + before = ibuf_index_page_calc_free_bits( + block->page.size.physical(), max_ins_size); + + if (max_ins_size >= increase) { +#if ULINT32_UNDEFINED <= UNIV_PAGE_SIZE_MAX +# error "ULINT32_UNDEFINED <= UNIV_PAGE_SIZE_MAX" +#endif + after = ibuf_index_page_calc_free_bits( + block->page.size.physical(), max_ins_size - increase); +#ifdef UNIV_IBUF_DEBUG + ut_a(after <= ibuf_index_page_calc_free(block)); +#endif + } else { + after = ibuf_index_page_calc_free(block); + } + + if (after == 0) { + /* We move the page to the front of the buffer pool LRU list: + the purpose of this is to prevent those pages to which we + cannot make inserts using the insert buffer from slipping + out of the buffer pool */ + + buf_page_make_young(&block->page); + } + + if (before > after) { + ibuf_set_free_bits(block, after, before); + } +} diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index edde6bf516e..58ca9f52856 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -1048,6 +1048,6 @@ lock_get_info( #endif /* WITH_WSREP */ -#include "lock0lock.ic" +#include "lock0lock.inl" #endif diff --git a/storage/innobase/include/lock0lock.ic b/storage/innobase/include/lock0lock.ic deleted file mode 100644 index 0ed933cba78..00000000000 --- a/storage/innobase/include/lock0lock.ic +++ /dev/null @@ -1,134 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -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 -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/lock0lock.ic -The transaction lock system - -Created 5/7/1996 Heikki Tuuri -*******************************************************/ - -#include "dict0dict.h" -#include "buf0buf.h" -#include "page0page.h" - -/*********************************************************************//** -Calculates the fold value of a page file address: used in inserting or -searching for a lock in the hash table. -@return folded value */ -UNIV_INLINE -ulint -lock_rec_fold( -/*==========*/ - ulint space, /*!< in: space */ - ulint page_no)/*!< in: page number */ -{ - return(ut_fold_ulint_pair(space, page_no)); -} - -/*********************************************************************//** -Calculates the hash value of a page file address: used in inserting or -searching for a lock in the hash table. -@return hashed value */ -UNIV_INLINE -unsigned -lock_rec_hash( -/*==========*/ - ulint space, /*!< in: space */ - ulint page_no)/*!< in: page number */ -{ - return(unsigned(hash_calc_hash(lock_rec_fold(space, page_no), - lock_sys->rec_hash))); -} - -/*********************************************************************//** -Gets the heap_no of the smallest user record on a page. -@return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */ -UNIV_INLINE -ulint -lock_get_min_heap_no( -/*=================*/ - const buf_block_t* block) /*!< in: buffer block */ -{ - const page_t* page = block->frame; - - if (page_is_comp(page)) { - return(rec_get_heap_no_new( - page - + rec_get_next_offs(page + PAGE_NEW_INFIMUM, - TRUE))); - } else { - return(rec_get_heap_no_old( - page - + rec_get_next_offs(page + PAGE_OLD_INFIMUM, - FALSE))); - } -} - -/*************************************************************//** -Get the lock hash table */ -UNIV_INLINE -hash_table_t* -lock_hash_get( -/*==========*/ - ulint mode) /*!< in: lock mode */ -{ - if (mode & LOCK_PREDICATE) { - return(lock_sys->prdt_hash); - } else if (mode & LOCK_PRDT_PAGE) { - return(lock_sys->prdt_page_hash); - } else { - return(lock_sys->rec_hash); - } -} - -/*********************************************************************//** -Creates a new record lock and inserts it to the lock queue. Does NOT check -for deadlocks or lock compatibility! -@return created lock */ -UNIV_INLINE -lock_t* -lock_rec_create( -/*============*/ -#ifdef WITH_WSREP - lock_t* c_lock, /*!< conflicting lock */ - que_thr_t* thr, /*!< thread owning trx */ -#endif - ulint type_mode,/*!< in: lock mode and wait - flag, type is ignored and - replaced by LOCK_REC */ - const buf_block_t* block, /*!< in: buffer block containing - the record */ - ulint heap_no,/*!< in: heap number of the record */ - dict_index_t* index, /*!< in: index of record */ - trx_t* trx, /*!< in,out: transaction */ - bool caller_owns_trx_mutex) - /*!< in: TRUE if caller owns - trx mutex */ -{ - btr_assert_not_corrupted(block, index); - return lock_rec_create_low( -#ifdef WITH_WSREP - c_lock, thr, -#endif - type_mode, - block->page.id.space(), block->page.id.page_no(), - block->frame, heap_no, - index, trx, caller_owns_trx_mutex); -} diff --git a/storage/innobase/include/lock0lock.inl b/storage/innobase/include/lock0lock.inl new file mode 100644 index 00000000000..0ed933cba78 --- /dev/null +++ b/storage/innobase/include/lock0lock.inl @@ -0,0 +1,134 @@ +/***************************************************************************** + +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +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 +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/lock0lock.ic +The transaction lock system + +Created 5/7/1996 Heikki Tuuri +*******************************************************/ + +#include "dict0dict.h" +#include "buf0buf.h" +#include "page0page.h" + +/*********************************************************************//** +Calculates the fold value of a page file address: used in inserting or +searching for a lock in the hash table. +@return folded value */ +UNIV_INLINE +ulint +lock_rec_fold( +/*==========*/ + ulint space, /*!< in: space */ + ulint page_no)/*!< in: page number */ +{ + return(ut_fold_ulint_pair(space, page_no)); +} + +/*********************************************************************//** +Calculates the hash value of a page file address: used in inserting or +searching for a lock in the hash table. +@return hashed value */ +UNIV_INLINE +unsigned +lock_rec_hash( +/*==========*/ + ulint space, /*!< in: space */ + ulint page_no)/*!< in: page number */ +{ + return(unsigned(hash_calc_hash(lock_rec_fold(space, page_no), + lock_sys->rec_hash))); +} + +/*********************************************************************//** +Gets the heap_no of the smallest user record on a page. +@return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */ +UNIV_INLINE +ulint +lock_get_min_heap_no( +/*=================*/ + const buf_block_t* block) /*!< in: buffer block */ +{ + const page_t* page = block->frame; + + if (page_is_comp(page)) { + return(rec_get_heap_no_new( + page + + rec_get_next_offs(page + PAGE_NEW_INFIMUM, + TRUE))); + } else { + return(rec_get_heap_no_old( + page + + rec_get_next_offs(page + PAGE_OLD_INFIMUM, + FALSE))); + } +} + +/*************************************************************//** +Get the lock hash table */ +UNIV_INLINE +hash_table_t* +lock_hash_get( +/*==========*/ + ulint mode) /*!< in: lock mode */ +{ + if (mode & LOCK_PREDICATE) { + return(lock_sys->prdt_hash); + } else if (mode & LOCK_PRDT_PAGE) { + return(lock_sys->prdt_page_hash); + } else { + return(lock_sys->rec_hash); + } +} + +/*********************************************************************//** +Creates a new record lock and inserts it to the lock queue. Does NOT check +for deadlocks or lock compatibility! +@return created lock */ +UNIV_INLINE +lock_t* +lock_rec_create( +/*============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /*!< conflicting lock */ + que_thr_t* thr, /*!< thread owning trx */ +#endif + ulint type_mode,/*!< in: lock mode and wait + flag, type is ignored and + replaced by LOCK_REC */ + const buf_block_t* block, /*!< in: buffer block containing + the record */ + ulint heap_no,/*!< in: heap number of the record */ + dict_index_t* index, /*!< in: index of record */ + trx_t* trx, /*!< in,out: transaction */ + bool caller_owns_trx_mutex) + /*!< in: TRUE if caller owns + trx mutex */ +{ + btr_assert_not_corrupted(block, index); + return lock_rec_create_low( +#ifdef WITH_WSREP + c_lock, thr, +#endif + type_mode, + block->page.id.space(), block->page.id.page_no(), + block->frame, heap_no, + index, trx, caller_owns_trx_mutex); +} diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h index 1a950ac1cfa..b7dcbfa2b86 100644 --- a/storage/innobase/include/lock0priv.h +++ b/storage/innobase/include/lock0priv.h @@ -685,6 +685,6 @@ inline void lock_reset_lock_and_trx_wait(lock_t* lock) lock->type_mode &= ~LOCK_WAIT; } -#include "lock0priv.ic" +#include "lock0priv.inl" #endif /* lock0priv_h */ diff --git a/storage/innobase/include/lock0priv.ic b/storage/innobase/include/lock0priv.ic deleted file mode 100644 index 8bb145e41fc..00000000000 --- a/storage/innobase/include/lock0priv.ic +++ /dev/null @@ -1,421 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2007, 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 -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/lock0priv.ic -Lock module internal inline methods. - -Created July 16, 2007 Vasil Dimov -*******************************************************/ - -/* This file contains only methods which are used in -lock/lock0* files, other than lock/lock0lock.cc. -I.e. lock/lock0lock.cc contains more internal inline -methods but they are used only in that file. */ - -#ifndef LOCK_MODULE_IMPLEMENTATION -#error Do not include lock0priv.ic outside of the lock/ module -#endif - -#include "row0row.h" - -/*********************************************************************//** -Gets the type of a lock. -@return LOCK_TABLE or LOCK_REC */ -UNIV_INLINE -ulint -lock_get_type_low( -/*==============*/ - const lock_t* lock) /*!< in: lock */ -{ - ut_ad(lock); - - return(lock->type_mode & LOCK_TYPE_MASK); -} - -/*********************************************************************//** -Checks if some transaction has an implicit x-lock on a record in a clustered -index. -@return transaction id of the transaction which has the x-lock, or 0 */ -UNIV_INLINE -trx_id_t -lock_clust_rec_some_has_impl( -/*=========================*/ - const rec_t* rec, /*!< in: user record */ - const dict_index_t* index, /*!< in: clustered index */ - const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ -{ - ut_ad(dict_index_is_clust(index)); - ut_ad(page_rec_is_user_rec(rec)); - - return(row_get_rec_trx_id(rec, index, offsets)); -} - -/*********************************************************************//** -Gets the number of bits in a record lock bitmap. -@return number of bits */ -UNIV_INLINE -ulint -lock_rec_get_n_bits( -/*================*/ - const lock_t* lock) /*!< in: record lock */ -{ - return(lock->un_member.rec_lock.n_bits); -} - -/**********************************************************************//** -Sets the nth bit of a record lock to TRUE. */ -UNIV_INLINE -void -lock_rec_set_nth_bit( -/*=================*/ - lock_t* lock, /*!< in: record lock */ - ulint i) /*!< in: index of the bit */ -{ - ulint byte_index; - ulint bit_index; - - ut_ad(lock); - ut_ad(lock_get_type_low(lock) == LOCK_REC); - ut_ad(i < lock->un_member.rec_lock.n_bits); - - byte_index = i / 8; - bit_index = i % 8; - - ((byte*) &lock[1])[byte_index] |= 1 << bit_index; - - ++lock->trx->lock.n_rec_locks; -} - -/*********************************************************************//** -Gets the first or next record lock on a page. -@return next lock, NULL if none exists */ -UNIV_INLINE -lock_t* -lock_rec_get_next_on_page( -/*======================*/ - lock_t* lock) /*!< in: a record lock */ -{ - return((lock_t*) lock_rec_get_next_on_page_const(lock)); -} - -/*********************************************************************//** -Gets the first record lock on a page, where the page is identified by its -file address. -@return first lock, NULL if none exists */ -UNIV_INLINE -lock_t* -lock_rec_get_first_on_page_addr( -/*============================*/ - hash_table_t* lock_hash, /* Lock hash table */ - ulint space, /*!< in: space */ - ulint page_no) /*!< in: page number */ -{ - ut_ad(lock_mutex_own()); - - for (lock_t* lock = static_cast( - HASH_GET_FIRST(lock_hash, - lock_rec_hash(space, page_no))); - lock != NULL; - lock = static_cast(HASH_GET_NEXT(hash, lock))) { - - if (lock->un_member.rec_lock.space == space - && lock->un_member.rec_lock.page_no == page_no) { - - return(lock); - } - } - - return(NULL); -} - -/*********************************************************************//** -Gets the first record lock on a page, where the page is identified by a -pointer to it. -@return first lock, NULL if none exists */ -UNIV_INLINE -lock_t* -lock_rec_get_first_on_page( -/*=======================*/ - hash_table_t* lock_hash, /*!< in: lock hash table */ - const buf_block_t* block) /*!< in: buffer block */ -{ - ut_ad(lock_mutex_own()); - - ulint space = block->page.id.space(); - ulint page_no = block->page.id.page_no(); - ulint hash = buf_block_get_lock_hash_val(block); - - for (lock_t* lock = static_cast( - HASH_GET_FIRST(lock_hash, hash)); - lock != NULL; - lock = static_cast(HASH_GET_NEXT(hash, lock))) { - - if (lock->un_member.rec_lock.space == space - && lock->un_member.rec_lock.page_no == page_no) { - - return(lock); - } - } - - return(NULL); -} - -/*********************************************************************//** -Gets the next explicit lock request on a record. -@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */ -UNIV_INLINE -lock_t* -lock_rec_get_next( -/*==============*/ - ulint heap_no,/*!< in: heap number of the record */ - lock_t* lock) /*!< in: lock */ -{ - ut_ad(lock_mutex_own()); - - do { - ut_ad(lock_get_type_low(lock) == LOCK_REC); - lock = lock_rec_get_next_on_page(lock); - } while (lock && !lock_rec_get_nth_bit(lock, heap_no)); - - return(lock); -} - -/*********************************************************************//** -Gets the next explicit lock request on a record. -@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */ -UNIV_INLINE -const lock_t* -lock_rec_get_next_const( -/*====================*/ - ulint heap_no,/*!< in: heap number of the record */ - const lock_t* lock) /*!< in: lock */ -{ - return(lock_rec_get_next(heap_no, (lock_t*) lock)); -} - -/*********************************************************************//** -Gets the first explicit lock request on a record. -@return first lock, NULL if none exists */ -UNIV_INLINE -lock_t* -lock_rec_get_first( -/*===============*/ - hash_table_t* hash, /*!< in: hash chain the lock on */ - const buf_block_t* block, /*!< in: block containing the record */ - ulint heap_no)/*!< in: heap number of the record */ -{ - ut_ad(lock_mutex_own()); - - for (lock_t* lock = lock_rec_get_first_on_page(hash, block); lock; - lock = lock_rec_get_next_on_page(lock)) { - if (lock_rec_get_nth_bit(lock, heap_no)) { - return(lock); - } - } - - return(NULL); -} - -/*********************************************************************//** -Gets the nth bit of a record lock. -@return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/ -UNIV_INLINE -ibool -lock_rec_get_nth_bit( -/*=================*/ - const lock_t* lock, /*!< in: record lock */ - ulint i) /*!< in: index of the bit */ -{ - const byte* b; - - ut_ad(lock); - ut_ad(lock_get_type_low(lock) == LOCK_REC); - - if (i >= lock->un_member.rec_lock.n_bits) { - - return(FALSE); - } - - b = ((const byte*) &lock[1]) + (i / 8); - - return(1 & *b >> (i % 8)); -} - -/*********************************************************************//** -Gets the first or next record lock on a page. -@return next lock, NULL if none exists */ -UNIV_INLINE -const lock_t* -lock_rec_get_next_on_page_const( -/*============================*/ - const lock_t* lock) /*!< in: a record lock */ -{ - ut_ad(lock_mutex_own()); - ut_ad(lock_get_type_low(lock) == LOCK_REC); - - ulint space = lock->un_member.rec_lock.space; - ulint page_no = lock->un_member.rec_lock.page_no; - - while ((lock = static_cast(HASH_GET_NEXT(hash, lock))) - != NULL) { - - if (lock->un_member.rec_lock.space == space - && lock->un_member.rec_lock.page_no == page_no) { - - return(lock); - } - } - - return(NULL); -} - -/*********************************************************************//** -Gets the mode of a lock. -@return mode */ -UNIV_INLINE -enum lock_mode -lock_get_mode( -/*==========*/ - const lock_t* lock) /*!< in: lock */ -{ - ut_ad(lock); - - return(static_cast(lock->type_mode & LOCK_MODE_MASK)); -} - -/*********************************************************************//** -Calculates if lock mode 1 is compatible with lock mode 2. -@return nonzero if mode1 compatible with mode2 */ -UNIV_INLINE -ulint -lock_mode_compatible( -/*=================*/ - enum lock_mode mode1, /*!< in: lock mode */ - enum lock_mode mode2) /*!< in: lock mode */ -{ - ut_ad((ulint) mode1 < lock_types); - ut_ad((ulint) mode2 < lock_types); - - return(lock_compatibility_matrix[mode1][mode2]); -} - -/*********************************************************************//** -Calculates if lock mode 1 is stronger or equal to lock mode 2. -@return nonzero if mode1 stronger or equal to mode2 */ -UNIV_INLINE -ulint -lock_mode_stronger_or_eq( -/*=====================*/ - enum lock_mode mode1, /*!< in: lock mode */ - enum lock_mode mode2) /*!< in: lock mode */ -{ - ut_ad((ulint) mode1 < lock_types); - ut_ad((ulint) mode2 < lock_types); - - return(lock_strength_matrix[mode1][mode2]); -} - -/*********************************************************************//** -Gets the wait flag of a lock. -@return LOCK_WAIT if waiting, 0 if not */ -UNIV_INLINE -ulint -lock_get_wait( -/*==========*/ - const lock_t* lock) /*!< in: lock */ -{ - ut_ad(lock); - - return(lock->type_mode & LOCK_WAIT); -} - -/*********************************************************************//** -Looks for a suitable type record lock struct by the same trx on the same page. -This can be used to save space when a new record lock should be set on a page: -no new struct is needed, if a suitable old is found. -@return lock or NULL */ -UNIV_INLINE -lock_t* -lock_rec_find_similar_on_page( -/*==========================*/ - ulint type_mode, /*!< in: lock type_mode field */ - ulint heap_no, /*!< in: heap number of the record */ - lock_t* lock, /*!< in: lock_rec_get_first_on_page() */ - const trx_t* trx) /*!< in: transaction */ -{ - ut_ad(lock_mutex_own()); - - for (/* No op */; - lock != NULL; - lock = lock_rec_get_next_on_page(lock)) { - - if (lock->trx == trx - && lock->type_mode == type_mode - && lock_rec_get_n_bits(lock) > heap_no) { - - return(lock); - } - } - - return(NULL); -} - -/*********************************************************************//** -Checks if a transaction has the specified table lock, or stronger. This -function should only be called by the thread that owns the transaction. -@return lock or NULL */ -UNIV_INLINE -const lock_t* -lock_table_has( -/*===========*/ - const trx_t* trx, /*!< in: transaction */ - const dict_table_t* table, /*!< in: table */ - lock_mode in_mode)/*!< in: lock mode */ -{ - /* Look for stronger locks the same trx already has on the table */ - - for (lock_list::const_iterator it = trx->lock.table_locks.begin(), - end = trx->lock.table_locks.end(); it != end; ++it) { - - const lock_t* lock = *it; - - if (lock == NULL) { - continue; - } - - lock_mode mode = lock_get_mode(lock); - - ut_ad(trx == lock->trx); - ut_ad(lock_get_type_low(lock) & LOCK_TABLE); - ut_ad(lock->un_member.tab_lock.table != NULL); - - if (table == lock->un_member.tab_lock.table - && lock_mode_stronger_or_eq(mode, in_mode)) { - - ut_ad(!lock_get_wait(lock)); - - return(lock); - } - } - - return(NULL); -} - -/* vim: set filetype=c: */ diff --git a/storage/innobase/include/lock0priv.inl b/storage/innobase/include/lock0priv.inl new file mode 100644 index 00000000000..8bb145e41fc --- /dev/null +++ b/storage/innobase/include/lock0priv.inl @@ -0,0 +1,421 @@ +/***************************************************************************** + +Copyright (c) 2007, 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 +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/lock0priv.ic +Lock module internal inline methods. + +Created July 16, 2007 Vasil Dimov +*******************************************************/ + +/* This file contains only methods which are used in +lock/lock0* files, other than lock/lock0lock.cc. +I.e. lock/lock0lock.cc contains more internal inline +methods but they are used only in that file. */ + +#ifndef LOCK_MODULE_IMPLEMENTATION +#error Do not include lock0priv.ic outside of the lock/ module +#endif + +#include "row0row.h" + +/*********************************************************************//** +Gets the type of a lock. +@return LOCK_TABLE or LOCK_REC */ +UNIV_INLINE +ulint +lock_get_type_low( +/*==============*/ + const lock_t* lock) /*!< in: lock */ +{ + ut_ad(lock); + + return(lock->type_mode & LOCK_TYPE_MASK); +} + +/*********************************************************************//** +Checks if some transaction has an implicit x-lock on a record in a clustered +index. +@return transaction id of the transaction which has the x-lock, or 0 */ +UNIV_INLINE +trx_id_t +lock_clust_rec_some_has_impl( +/*=========================*/ + const rec_t* rec, /*!< in: user record */ + const dict_index_t* index, /*!< in: clustered index */ + const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ +{ + ut_ad(dict_index_is_clust(index)); + ut_ad(page_rec_is_user_rec(rec)); + + return(row_get_rec_trx_id(rec, index, offsets)); +} + +/*********************************************************************//** +Gets the number of bits in a record lock bitmap. +@return number of bits */ +UNIV_INLINE +ulint +lock_rec_get_n_bits( +/*================*/ + const lock_t* lock) /*!< in: record lock */ +{ + return(lock->un_member.rec_lock.n_bits); +} + +/**********************************************************************//** +Sets the nth bit of a record lock to TRUE. */ +UNIV_INLINE +void +lock_rec_set_nth_bit( +/*=================*/ + lock_t* lock, /*!< in: record lock */ + ulint i) /*!< in: index of the bit */ +{ + ulint byte_index; + ulint bit_index; + + ut_ad(lock); + ut_ad(lock_get_type_low(lock) == LOCK_REC); + ut_ad(i < lock->un_member.rec_lock.n_bits); + + byte_index = i / 8; + bit_index = i % 8; + + ((byte*) &lock[1])[byte_index] |= 1 << bit_index; + + ++lock->trx->lock.n_rec_locks; +} + +/*********************************************************************//** +Gets the first or next record lock on a page. +@return next lock, NULL if none exists */ +UNIV_INLINE +lock_t* +lock_rec_get_next_on_page( +/*======================*/ + lock_t* lock) /*!< in: a record lock */ +{ + return((lock_t*) lock_rec_get_next_on_page_const(lock)); +} + +/*********************************************************************//** +Gets the first record lock on a page, where the page is identified by its +file address. +@return first lock, NULL if none exists */ +UNIV_INLINE +lock_t* +lock_rec_get_first_on_page_addr( +/*============================*/ + hash_table_t* lock_hash, /* Lock hash table */ + ulint space, /*!< in: space */ + ulint page_no) /*!< in: page number */ +{ + ut_ad(lock_mutex_own()); + + for (lock_t* lock = static_cast( + HASH_GET_FIRST(lock_hash, + lock_rec_hash(space, page_no))); + lock != NULL; + lock = static_cast(HASH_GET_NEXT(hash, lock))) { + + if (lock->un_member.rec_lock.space == space + && lock->un_member.rec_lock.page_no == page_no) { + + return(lock); + } + } + + return(NULL); +} + +/*********************************************************************//** +Gets the first record lock on a page, where the page is identified by a +pointer to it. +@return first lock, NULL if none exists */ +UNIV_INLINE +lock_t* +lock_rec_get_first_on_page( +/*=======================*/ + hash_table_t* lock_hash, /*!< in: lock hash table */ + const buf_block_t* block) /*!< in: buffer block */ +{ + ut_ad(lock_mutex_own()); + + ulint space = block->page.id.space(); + ulint page_no = block->page.id.page_no(); + ulint hash = buf_block_get_lock_hash_val(block); + + for (lock_t* lock = static_cast( + HASH_GET_FIRST(lock_hash, hash)); + lock != NULL; + lock = static_cast(HASH_GET_NEXT(hash, lock))) { + + if (lock->un_member.rec_lock.space == space + && lock->un_member.rec_lock.page_no == page_no) { + + return(lock); + } + } + + return(NULL); +} + +/*********************************************************************//** +Gets the next explicit lock request on a record. +@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */ +UNIV_INLINE +lock_t* +lock_rec_get_next( +/*==============*/ + ulint heap_no,/*!< in: heap number of the record */ + lock_t* lock) /*!< in: lock */ +{ + ut_ad(lock_mutex_own()); + + do { + ut_ad(lock_get_type_low(lock) == LOCK_REC); + lock = lock_rec_get_next_on_page(lock); + } while (lock && !lock_rec_get_nth_bit(lock, heap_no)); + + return(lock); +} + +/*********************************************************************//** +Gets the next explicit lock request on a record. +@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */ +UNIV_INLINE +const lock_t* +lock_rec_get_next_const( +/*====================*/ + ulint heap_no,/*!< in: heap number of the record */ + const lock_t* lock) /*!< in: lock */ +{ + return(lock_rec_get_next(heap_no, (lock_t*) lock)); +} + +/*********************************************************************//** +Gets the first explicit lock request on a record. +@return first lock, NULL if none exists */ +UNIV_INLINE +lock_t* +lock_rec_get_first( +/*===============*/ + hash_table_t* hash, /*!< in: hash chain the lock on */ + const buf_block_t* block, /*!< in: block containing the record */ + ulint heap_no)/*!< in: heap number of the record */ +{ + ut_ad(lock_mutex_own()); + + for (lock_t* lock = lock_rec_get_first_on_page(hash, block); lock; + lock = lock_rec_get_next_on_page(lock)) { + if (lock_rec_get_nth_bit(lock, heap_no)) { + return(lock); + } + } + + return(NULL); +} + +/*********************************************************************//** +Gets the nth bit of a record lock. +@return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/ +UNIV_INLINE +ibool +lock_rec_get_nth_bit( +/*=================*/ + const lock_t* lock, /*!< in: record lock */ + ulint i) /*!< in: index of the bit */ +{ + const byte* b; + + ut_ad(lock); + ut_ad(lock_get_type_low(lock) == LOCK_REC); + + if (i >= lock->un_member.rec_lock.n_bits) { + + return(FALSE); + } + + b = ((const byte*) &lock[1]) + (i / 8); + + return(1 & *b >> (i % 8)); +} + +/*********************************************************************//** +Gets the first or next record lock on a page. +@return next lock, NULL if none exists */ +UNIV_INLINE +const lock_t* +lock_rec_get_next_on_page_const( +/*============================*/ + const lock_t* lock) /*!< in: a record lock */ +{ + ut_ad(lock_mutex_own()); + ut_ad(lock_get_type_low(lock) == LOCK_REC); + + ulint space = lock->un_member.rec_lock.space; + ulint page_no = lock->un_member.rec_lock.page_no; + + while ((lock = static_cast(HASH_GET_NEXT(hash, lock))) + != NULL) { + + if (lock->un_member.rec_lock.space == space + && lock->un_member.rec_lock.page_no == page_no) { + + return(lock); + } + } + + return(NULL); +} + +/*********************************************************************//** +Gets the mode of a lock. +@return mode */ +UNIV_INLINE +enum lock_mode +lock_get_mode( +/*==========*/ + const lock_t* lock) /*!< in: lock */ +{ + ut_ad(lock); + + return(static_cast(lock->type_mode & LOCK_MODE_MASK)); +} + +/*********************************************************************//** +Calculates if lock mode 1 is compatible with lock mode 2. +@return nonzero if mode1 compatible with mode2 */ +UNIV_INLINE +ulint +lock_mode_compatible( +/*=================*/ + enum lock_mode mode1, /*!< in: lock mode */ + enum lock_mode mode2) /*!< in: lock mode */ +{ + ut_ad((ulint) mode1 < lock_types); + ut_ad((ulint) mode2 < lock_types); + + return(lock_compatibility_matrix[mode1][mode2]); +} + +/*********************************************************************//** +Calculates if lock mode 1 is stronger or equal to lock mode 2. +@return nonzero if mode1 stronger or equal to mode2 */ +UNIV_INLINE +ulint +lock_mode_stronger_or_eq( +/*=====================*/ + enum lock_mode mode1, /*!< in: lock mode */ + enum lock_mode mode2) /*!< in: lock mode */ +{ + ut_ad((ulint) mode1 < lock_types); + ut_ad((ulint) mode2 < lock_types); + + return(lock_strength_matrix[mode1][mode2]); +} + +/*********************************************************************//** +Gets the wait flag of a lock. +@return LOCK_WAIT if waiting, 0 if not */ +UNIV_INLINE +ulint +lock_get_wait( +/*==========*/ + const lock_t* lock) /*!< in: lock */ +{ + ut_ad(lock); + + return(lock->type_mode & LOCK_WAIT); +} + +/*********************************************************************//** +Looks for a suitable type record lock struct by the same trx on the same page. +This can be used to save space when a new record lock should be set on a page: +no new struct is needed, if a suitable old is found. +@return lock or NULL */ +UNIV_INLINE +lock_t* +lock_rec_find_similar_on_page( +/*==========================*/ + ulint type_mode, /*!< in: lock type_mode field */ + ulint heap_no, /*!< in: heap number of the record */ + lock_t* lock, /*!< in: lock_rec_get_first_on_page() */ + const trx_t* trx) /*!< in: transaction */ +{ + ut_ad(lock_mutex_own()); + + for (/* No op */; + lock != NULL; + lock = lock_rec_get_next_on_page(lock)) { + + if (lock->trx == trx + && lock->type_mode == type_mode + && lock_rec_get_n_bits(lock) > heap_no) { + + return(lock); + } + } + + return(NULL); +} + +/*********************************************************************//** +Checks if a transaction has the specified table lock, or stronger. This +function should only be called by the thread that owns the transaction. +@return lock or NULL */ +UNIV_INLINE +const lock_t* +lock_table_has( +/*===========*/ + const trx_t* trx, /*!< in: transaction */ + const dict_table_t* table, /*!< in: table */ + lock_mode in_mode)/*!< in: lock mode */ +{ + /* Look for stronger locks the same trx already has on the table */ + + for (lock_list::const_iterator it = trx->lock.table_locks.begin(), + end = trx->lock.table_locks.end(); it != end; ++it) { + + const lock_t* lock = *it; + + if (lock == NULL) { + continue; + } + + lock_mode mode = lock_get_mode(lock); + + ut_ad(trx == lock->trx); + ut_ad(lock_get_type_low(lock) & LOCK_TABLE); + ut_ad(lock->un_member.tab_lock.table != NULL); + + if (table == lock->un_member.tab_lock.table + && lock_mode_stronger_or_eq(mode, in_mode)) { + + ut_ad(!lock_get_wait(lock)); + + return(lock); + } + } + + return(NULL); +} + +/* vim: set filetype=c: */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index c0b92fb7497..54720c97204 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -778,6 +778,6 @@ extern os_event_t log_scrub_event; /** Whether log_scrub_thread is active */ extern bool log_scrub_thread_active; -#include "log0log.ic" +#include "log0log.inl" #endif diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic deleted file mode 100644 index c366affcdef..00000000000 --- a/storage/innobase/include/log0log.ic +++ /dev/null @@ -1,484 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. -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 -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/log0log.ic -Database log - -Created 12/9/1995 Heikki Tuuri -*******************************************************/ - -#include "mach0data.h" -#include "srv0mon.h" -#include "srv0srv.h" -#include "ut0crc32.h" - -#ifdef UNIV_LOG_LSN_DEBUG -#include "mtr0types.h" -#endif /* UNIV_LOG_LSN_DEBUG */ - -/************************************************************//** -Gets a log block flush bit. -@return TRUE if this block was the first to be written in a log flush */ -UNIV_INLINE -ibool -log_block_get_flush_bit( -/*====================*/ - const byte* log_block) /*!< in: log block */ -{ - if (LOG_BLOCK_FLUSH_BIT_MASK - & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) { - - return(TRUE); - } - - return(FALSE); -} - -/************************************************************//** -Sets the log block flush bit. */ -UNIV_INLINE -void -log_block_set_flush_bit( -/*====================*/ - byte* log_block, /*!< in/out: log block */ - ibool val) /*!< in: value to set */ -{ - ulint field; - - field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO); - - if (val) { - field = field | LOG_BLOCK_FLUSH_BIT_MASK; - } else { - field = field & ~LOG_BLOCK_FLUSH_BIT_MASK; - } - - mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field); -} - -/************************************************************//** -Gets a log block number stored in the header. -@return log block number stored in the block header */ -UNIV_INLINE -ulint -log_block_get_hdr_no( -/*=================*/ - const byte* log_block) /*!< in: log block */ -{ - return(~LOG_BLOCK_FLUSH_BIT_MASK - & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)); -} - -/************************************************************//** -Sets the log block number stored in the header; NOTE that this must be set -before the flush bit! */ -UNIV_INLINE -void -log_block_set_hdr_no( -/*=================*/ - byte* log_block, /*!< in/out: log block */ - ulint n) /*!< in: log block number: must be > 0 and - < LOG_BLOCK_FLUSH_BIT_MASK */ -{ - ut_ad(n > 0); - ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK); - - mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n); -} - -/************************************************************//** -Gets a log block data length. -@return log block data length measured as a byte offset from the block start */ -UNIV_INLINE -ulint -log_block_get_data_len( -/*===================*/ - const byte* log_block) /*!< in: log block */ -{ - return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN)); -} - -/************************************************************//** -Sets the log block data length. */ -UNIV_INLINE -void -log_block_set_data_len( -/*===================*/ - byte* log_block, /*!< in/out: log block */ - ulint len) /*!< in: data length */ -{ - mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len); -} - -/************************************************************//** -Gets a log block first mtr log record group offset. -@return first mtr log record group byte offset from the block start, 0 -if none */ -UNIV_INLINE -ulint -log_block_get_first_rec_group( -/*==========================*/ - const byte* log_block) /*!< in: log block */ -{ - return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP)); -} - -/************************************************************//** -Sets the log block first mtr log record group offset. */ -UNIV_INLINE -void -log_block_set_first_rec_group( -/*==========================*/ - byte* log_block, /*!< in/out: log block */ - ulint offset) /*!< in: offset, 0 if none */ -{ - mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset); -} - -/************************************************************//** -Gets a log block checkpoint number field (4 lowest bytes). -@return checkpoint no (4 lowest bytes) */ -UNIV_INLINE -ulint -log_block_get_checkpoint_no( -/*========================*/ - const byte* log_block) /*!< in: log block */ -{ - return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO)); -} - -/************************************************************//** -Sets a log block checkpoint number field (4 lowest bytes). */ -UNIV_INLINE -void -log_block_set_checkpoint_no( -/*========================*/ - byte* log_block, /*!< in/out: log block */ - ib_uint64_t no) /*!< in: checkpoint no */ -{ - mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO, (ulint) no); -} - -/************************************************************//** -Converts a lsn to a log block number. -@return log block number, it is > 0 and <= 1G */ -UNIV_INLINE -ulint -log_block_convert_lsn_to_no( -/*========================*/ - lsn_t lsn) /*!< in: lsn of a byte within the block */ -{ - return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) & - DBUG_EVALUATE_IF("innodb_small_log_block_no_limit", - 0xFUL, 0x3FFFFFFFUL)) + 1); -} - -/** Calculate the checksum for a log block using the pre-5.7.9 algorithm. -@param[in] block log block -@return checksum */ -UNIV_INLINE -ulint -log_block_calc_checksum_format_0( - const byte* block) -{ - ulint sum; - ulint sh; - ulint i; - - sum = 1; - sh = 0; - - for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) { - ulint b = (ulint) block[i]; - sum &= 0x7FFFFFFFUL; - sum += b; - sum += b << sh; - sh++; - if (sh > 24) { - sh = 0; - } - } - - return(sum); -} - -/** Calculate the checksum for a log block using the MySQL 5.7 algorithm. -@param[in] block log block -@return checksum */ -UNIV_INLINE -ulint -log_block_calc_checksum_crc32( - const byte* block) -{ - return(ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE)); -} - -/************************************************************//** -Gets a log block checksum field value. -@return checksum */ -UNIV_INLINE -ulint -log_block_get_checksum( -/*===================*/ - const byte* log_block) /*!< in: log block */ -{ - return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE - - LOG_BLOCK_CHECKSUM)); -} - -/************************************************************//** -Sets a log block checksum field value. */ -UNIV_INLINE -void -log_block_set_checksum( -/*===================*/ - byte* log_block, /*!< in/out: log block */ - ulint checksum) /*!< in: checksum */ -{ - mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE - - LOG_BLOCK_CHECKSUM, - checksum); -} - -/************************************************************//** -Initializes a log block in the log buffer. */ -UNIV_INLINE -void -log_block_init( -/*===========*/ - byte* log_block, /*!< in: pointer to the log buffer */ - lsn_t lsn) /*!< in: lsn within the log block */ -{ - ulint no; - - no = log_block_convert_lsn_to_no(lsn); - - log_block_set_hdr_no(log_block, no); - - log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE); - log_block_set_first_rec_group(log_block, 0); -} - -/** Append a string to the log. -@param[in] str string -@param[in] len string length -@param[out] start_lsn start LSN of the log record -@return end lsn of the log record, zero if did not succeed */ -UNIV_INLINE -lsn_t -log_reserve_and_write_fast( - const void* str, - ulint len, - lsn_t* start_lsn) -{ - ut_ad(log_mutex_own()); - ut_ad(len > 0); - -#ifdef UNIV_LOG_LSN_DEBUG - /* Append a MLOG_LSN record after mtr_commit(), except when - the last bytes could be a MLOG_CHECKPOINT marker. We have special - handling when the log consists of only a single MLOG_CHECKPOINT - record since the latest checkpoint, and appending the - MLOG_LSN would ruin that. - - Note that a longer redo log record could happen to end in what - looks like MLOG_CHECKPOINT, and we could be omitting MLOG_LSN - without reason. This is OK, because writing the MLOG_LSN is - just a 'best effort', aimed at finding log corruption due to - bugs in the redo log writing logic. */ - const ulint lsn_len - = len >= SIZE_OF_MLOG_CHECKPOINT - && MLOG_CHECKPOINT == static_cast(str)[ - len - SIZE_OF_MLOG_CHECKPOINT] - ? 0 - : 1 - + mach_get_compressed_size(log_sys->lsn >> 32) - + mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL); -#endif /* UNIV_LOG_LSN_DEBUG */ - - const ulint data_len = len -#ifdef UNIV_LOG_LSN_DEBUG - + lsn_len -#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) { - - /* The string does not fit within the current log block - or the log block would become full */ - - return(0); - } - - *start_lsn = log_sys->lsn; - -#ifdef UNIV_LOG_LSN_DEBUG - if (lsn_len) { - /* Write the LSN pseudo-record. */ - byte* b = &log_sys->buf[log_sys->buf_free]; - - *b++ = MLOG_LSN | (MLOG_SINGLE_REC_FLAG & *(const byte*) str); - - /* Write the LSN in two parts, - as a pseudo page number and space id. */ - b += mach_write_compressed(b, log_sys->lsn >> 32); - b += mach_write_compressed(b, log_sys->lsn & 0xFFFFFFFFUL); - ut_a(b - lsn_len == &log_sys->buf[log_sys->buf_free]); - - ::memcpy(b, str, len); - - len += lsn_len; - } else -#endif /* UNIV_LOG_LSN_DEBUG */ - memcpy(log_sys->buf + log_sys->buf_free, str, len); - - log_block_set_data_len( - reinterpret_cast(ut_align_down( - log_sys->buf + log_sys->buf_free, - OS_FILE_LOG_BLOCK_SIZE)), - data_len); - - log_sys->buf_free += len; - - ut_ad(log_sys->buf_free <= log_sys->buf_size); - - log_sys->lsn += len; - - MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE, - log_sys->lsn - log_sys->last_checkpoint_lsn); - - return(log_sys->lsn); -} - -/************************************************************//** -Gets the current lsn. -@return current lsn */ -UNIV_INLINE -lsn_t -log_get_lsn(void) -/*=============*/ -{ - lsn_t lsn; - - log_mutex_enter(); - - lsn = log_sys->lsn; - - log_mutex_exit(); - - return(lsn); -} - -/************************************************************//** -Gets the last lsn that is fully flushed to disk. -@return last flushed lsn */ -UNIV_INLINE -ib_uint64_t -log_get_flush_lsn(void) -{ - ib_uint64_t lsn; - - log_mutex_enter(); - - lsn = log_sys->flushed_to_disk_lsn; - - log_mutex_exit(); - - return(lsn); -} - -/************************************************************//** -Gets the current lsn with a trylock -@return current lsn or 0 if false*/ -UNIV_INLINE -lsn_t -log_get_lsn_nowait(void) -/*====================*/ -{ - lsn_t lsn=0; - - if (!mutex_enter_nowait(&(log_sys->mutex))) { - - lsn = log_sys->lsn; - - mutex_exit(&(log_sys->mutex)); - } - - return(lsn); -} - -/**************************************************************** -Gets the log group capacity. It is OK to read the value without -holding log_sys->mutex because it is constant. -@return log group capacity */ -UNIV_INLINE -lsn_t -log_get_capacity(void) -/*==================*/ -{ - return(log_sys->log_group_capacity); -} - -/**************************************************************** -Get log_sys::max_modified_age_async. It is OK to read the value without -holding log_sys::mutex because it is constant. -@return max_modified_age_async */ -UNIV_INLINE -lsn_t -log_get_max_modified_age_async(void) -/*================================*/ -{ - return(log_sys->max_modified_age_async); -} - -/***********************************************************************//** -Checks if there is need for a log buffer flush or a new checkpoint, and does -this if yes. Any database operation should call this when it has modified -more than about 4 pages. NOTE that this function may only be called when the -OS thread owns no synchronization objects except the dictionary mutex. */ -UNIV_INLINE -void -log_free_check(void) -/*================*/ -{ - /* During row_log_table_apply(), this function will be called while we - are holding some latches. This is OK, as long as we are not holding - any latches on buffer blocks. */ - -#ifdef UNIV_DEBUG - static const latch_level_t latches[] = { - SYNC_DICT, /* dict_sys->mutex during - commit_try_rebuild() */ - SYNC_DICT_OPERATION, /* dict_operation_lock X-latch during - commit_try_rebuild() */ - SYNC_FTS_CACHE, /* fts_cache_t::lock */ - SYNC_INDEX_TREE /* index->lock */ - }; -#endif /* UNIV_DEBUG */ - - ut_ad(!sync_check_iterate( - sync_allowed_latches(latches, - latches + UT_ARR_SIZE(latches)))); - - if (log_sys->check_flush_or_checkpoint) { - - log_check_margins(); - } -} diff --git a/storage/innobase/include/log0log.inl b/storage/innobase/include/log0log.inl new file mode 100644 index 00000000000..c366affcdef --- /dev/null +++ b/storage/innobase/include/log0log.inl @@ -0,0 +1,484 @@ +/***************************************************************************** + +Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +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 +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/log0log.ic +Database log + +Created 12/9/1995 Heikki Tuuri +*******************************************************/ + +#include "mach0data.h" +#include "srv0mon.h" +#include "srv0srv.h" +#include "ut0crc32.h" + +#ifdef UNIV_LOG_LSN_DEBUG +#include "mtr0types.h" +#endif /* UNIV_LOG_LSN_DEBUG */ + +/************************************************************//** +Gets a log block flush bit. +@return TRUE if this block was the first to be written in a log flush */ +UNIV_INLINE +ibool +log_block_get_flush_bit( +/*====================*/ + const byte* log_block) /*!< in: log block */ +{ + if (LOG_BLOCK_FLUSH_BIT_MASK + & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) { + + return(TRUE); + } + + return(FALSE); +} + +/************************************************************//** +Sets the log block flush bit. */ +UNIV_INLINE +void +log_block_set_flush_bit( +/*====================*/ + byte* log_block, /*!< in/out: log block */ + ibool val) /*!< in: value to set */ +{ + ulint field; + + field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO); + + if (val) { + field = field | LOG_BLOCK_FLUSH_BIT_MASK; + } else { + field = field & ~LOG_BLOCK_FLUSH_BIT_MASK; + } + + mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field); +} + +/************************************************************//** +Gets a log block number stored in the header. +@return log block number stored in the block header */ +UNIV_INLINE +ulint +log_block_get_hdr_no( +/*=================*/ + const byte* log_block) /*!< in: log block */ +{ + return(~LOG_BLOCK_FLUSH_BIT_MASK + & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)); +} + +/************************************************************//** +Sets the log block number stored in the header; NOTE that this must be set +before the flush bit! */ +UNIV_INLINE +void +log_block_set_hdr_no( +/*=================*/ + byte* log_block, /*!< in/out: log block */ + ulint n) /*!< in: log block number: must be > 0 and + < LOG_BLOCK_FLUSH_BIT_MASK */ +{ + ut_ad(n > 0); + ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK); + + mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n); +} + +/************************************************************//** +Gets a log block data length. +@return log block data length measured as a byte offset from the block start */ +UNIV_INLINE +ulint +log_block_get_data_len( +/*===================*/ + const byte* log_block) /*!< in: log block */ +{ + return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN)); +} + +/************************************************************//** +Sets the log block data length. */ +UNIV_INLINE +void +log_block_set_data_len( +/*===================*/ + byte* log_block, /*!< in/out: log block */ + ulint len) /*!< in: data length */ +{ + mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len); +} + +/************************************************************//** +Gets a log block first mtr log record group offset. +@return first mtr log record group byte offset from the block start, 0 +if none */ +UNIV_INLINE +ulint +log_block_get_first_rec_group( +/*==========================*/ + const byte* log_block) /*!< in: log block */ +{ + return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP)); +} + +/************************************************************//** +Sets the log block first mtr log record group offset. */ +UNIV_INLINE +void +log_block_set_first_rec_group( +/*==========================*/ + byte* log_block, /*!< in/out: log block */ + ulint offset) /*!< in: offset, 0 if none */ +{ + mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset); +} + +/************************************************************//** +Gets a log block checkpoint number field (4 lowest bytes). +@return checkpoint no (4 lowest bytes) */ +UNIV_INLINE +ulint +log_block_get_checkpoint_no( +/*========================*/ + const byte* log_block) /*!< in: log block */ +{ + return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO)); +} + +/************************************************************//** +Sets a log block checkpoint number field (4 lowest bytes). */ +UNIV_INLINE +void +log_block_set_checkpoint_no( +/*========================*/ + byte* log_block, /*!< in/out: log block */ + ib_uint64_t no) /*!< in: checkpoint no */ +{ + mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO, (ulint) no); +} + +/************************************************************//** +Converts a lsn to a log block number. +@return log block number, it is > 0 and <= 1G */ +UNIV_INLINE +ulint +log_block_convert_lsn_to_no( +/*========================*/ + lsn_t lsn) /*!< in: lsn of a byte within the block */ +{ + return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) & + DBUG_EVALUATE_IF("innodb_small_log_block_no_limit", + 0xFUL, 0x3FFFFFFFUL)) + 1); +} + +/** Calculate the checksum for a log block using the pre-5.7.9 algorithm. +@param[in] block log block +@return checksum */ +UNIV_INLINE +ulint +log_block_calc_checksum_format_0( + const byte* block) +{ + ulint sum; + ulint sh; + ulint i; + + sum = 1; + sh = 0; + + for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) { + ulint b = (ulint) block[i]; + sum &= 0x7FFFFFFFUL; + sum += b; + sum += b << sh; + sh++; + if (sh > 24) { + sh = 0; + } + } + + return(sum); +} + +/** Calculate the checksum for a log block using the MySQL 5.7 algorithm. +@param[in] block log block +@return checksum */ +UNIV_INLINE +ulint +log_block_calc_checksum_crc32( + const byte* block) +{ + return(ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE)); +} + +/************************************************************//** +Gets a log block checksum field value. +@return checksum */ +UNIV_INLINE +ulint +log_block_get_checksum( +/*===================*/ + const byte* log_block) /*!< in: log block */ +{ + return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE + - LOG_BLOCK_CHECKSUM)); +} + +/************************************************************//** +Sets a log block checksum field value. */ +UNIV_INLINE +void +log_block_set_checksum( +/*===================*/ + byte* log_block, /*!< in/out: log block */ + ulint checksum) /*!< in: checksum */ +{ + mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE + - LOG_BLOCK_CHECKSUM, + checksum); +} + +/************************************************************//** +Initializes a log block in the log buffer. */ +UNIV_INLINE +void +log_block_init( +/*===========*/ + byte* log_block, /*!< in: pointer to the log buffer */ + lsn_t lsn) /*!< in: lsn within the log block */ +{ + ulint no; + + no = log_block_convert_lsn_to_no(lsn); + + log_block_set_hdr_no(log_block, no); + + log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE); + log_block_set_first_rec_group(log_block, 0); +} + +/** Append a string to the log. +@param[in] str string +@param[in] len string length +@param[out] start_lsn start LSN of the log record +@return end lsn of the log record, zero if did not succeed */ +UNIV_INLINE +lsn_t +log_reserve_and_write_fast( + const void* str, + ulint len, + lsn_t* start_lsn) +{ + ut_ad(log_mutex_own()); + ut_ad(len > 0); + +#ifdef UNIV_LOG_LSN_DEBUG + /* Append a MLOG_LSN record after mtr_commit(), except when + the last bytes could be a MLOG_CHECKPOINT marker. We have special + handling when the log consists of only a single MLOG_CHECKPOINT + record since the latest checkpoint, and appending the + MLOG_LSN would ruin that. + + Note that a longer redo log record could happen to end in what + looks like MLOG_CHECKPOINT, and we could be omitting MLOG_LSN + without reason. This is OK, because writing the MLOG_LSN is + just a 'best effort', aimed at finding log corruption due to + bugs in the redo log writing logic. */ + const ulint lsn_len + = len >= SIZE_OF_MLOG_CHECKPOINT + && MLOG_CHECKPOINT == static_cast(str)[ + len - SIZE_OF_MLOG_CHECKPOINT] + ? 0 + : 1 + + mach_get_compressed_size(log_sys->lsn >> 32) + + mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL); +#endif /* UNIV_LOG_LSN_DEBUG */ + + const ulint data_len = len +#ifdef UNIV_LOG_LSN_DEBUG + + lsn_len +#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) { + + /* The string does not fit within the current log block + or the log block would become full */ + + return(0); + } + + *start_lsn = log_sys->lsn; + +#ifdef UNIV_LOG_LSN_DEBUG + if (lsn_len) { + /* Write the LSN pseudo-record. */ + byte* b = &log_sys->buf[log_sys->buf_free]; + + *b++ = MLOG_LSN | (MLOG_SINGLE_REC_FLAG & *(const byte*) str); + + /* Write the LSN in two parts, + as a pseudo page number and space id. */ + b += mach_write_compressed(b, log_sys->lsn >> 32); + b += mach_write_compressed(b, log_sys->lsn & 0xFFFFFFFFUL); + ut_a(b - lsn_len == &log_sys->buf[log_sys->buf_free]); + + ::memcpy(b, str, len); + + len += lsn_len; + } else +#endif /* UNIV_LOG_LSN_DEBUG */ + memcpy(log_sys->buf + log_sys->buf_free, str, len); + + log_block_set_data_len( + reinterpret_cast(ut_align_down( + log_sys->buf + log_sys->buf_free, + OS_FILE_LOG_BLOCK_SIZE)), + data_len); + + log_sys->buf_free += len; + + ut_ad(log_sys->buf_free <= log_sys->buf_size); + + log_sys->lsn += len; + + MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE, + log_sys->lsn - log_sys->last_checkpoint_lsn); + + return(log_sys->lsn); +} + +/************************************************************//** +Gets the current lsn. +@return current lsn */ +UNIV_INLINE +lsn_t +log_get_lsn(void) +/*=============*/ +{ + lsn_t lsn; + + log_mutex_enter(); + + lsn = log_sys->lsn; + + log_mutex_exit(); + + return(lsn); +} + +/************************************************************//** +Gets the last lsn that is fully flushed to disk. +@return last flushed lsn */ +UNIV_INLINE +ib_uint64_t +log_get_flush_lsn(void) +{ + ib_uint64_t lsn; + + log_mutex_enter(); + + lsn = log_sys->flushed_to_disk_lsn; + + log_mutex_exit(); + + return(lsn); +} + +/************************************************************//** +Gets the current lsn with a trylock +@return current lsn or 0 if false*/ +UNIV_INLINE +lsn_t +log_get_lsn_nowait(void) +/*====================*/ +{ + lsn_t lsn=0; + + if (!mutex_enter_nowait(&(log_sys->mutex))) { + + lsn = log_sys->lsn; + + mutex_exit(&(log_sys->mutex)); + } + + return(lsn); +} + +/**************************************************************** +Gets the log group capacity. It is OK to read the value without +holding log_sys->mutex because it is constant. +@return log group capacity */ +UNIV_INLINE +lsn_t +log_get_capacity(void) +/*==================*/ +{ + return(log_sys->log_group_capacity); +} + +/**************************************************************** +Get log_sys::max_modified_age_async. It is OK to read the value without +holding log_sys::mutex because it is constant. +@return max_modified_age_async */ +UNIV_INLINE +lsn_t +log_get_max_modified_age_async(void) +/*================================*/ +{ + return(log_sys->max_modified_age_async); +} + +/***********************************************************************//** +Checks if there is need for a log buffer flush or a new checkpoint, and does +this if yes. Any database operation should call this when it has modified +more than about 4 pages. NOTE that this function may only be called when the +OS thread owns no synchronization objects except the dictionary mutex. */ +UNIV_INLINE +void +log_free_check(void) +/*================*/ +{ + /* During row_log_table_apply(), this function will be called while we + are holding some latches. This is OK, as long as we are not holding + any latches on buffer blocks. */ + +#ifdef UNIV_DEBUG + static const latch_level_t latches[] = { + SYNC_DICT, /* dict_sys->mutex during + commit_try_rebuild() */ + SYNC_DICT_OPERATION, /* dict_operation_lock X-latch during + commit_try_rebuild() */ + SYNC_FTS_CACHE, /* fts_cache_t::lock */ + SYNC_INDEX_TREE /* index->lock */ + }; +#endif /* UNIV_DEBUG */ + + ut_ad(!sync_check_iterate( + sync_allowed_latches(latches, + latches + UT_ARR_SIZE(latches)))); + + if (log_sys->check_flush_or_checkpoint) { + + log_check_margins(); + } +} diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h index 860ef20b8bd..27f3b986776 100644 --- a/storage/innobase/include/mach0data.h +++ b/storage/innobase/include/mach0data.h @@ -401,6 +401,6 @@ mach_read_ulint( mlog_id_t type) MY_ATTRIBUTE((warn_unused_result)); -#include "mach0data.ic" +#include "mach0data.inl" #endif diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic deleted file mode 100644 index 408044292a5..00000000000 --- a/storage/innobase/include/mach0data.ic +++ /dev/null @@ -1,893 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 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/mach0data.ic -Utilities for converting data from the database file -to the machine format. - -Created 11/28/1995 Heikki Tuuri -***********************************************************************/ - -#ifndef UNIV_INNOCHECKSUM - -#include "mtr0types.h" - -/*******************************************************//** -The following function is used to store data in one byte. */ -UNIV_INLINE -void -mach_write_to_1( -/*============*/ - byte* b, /*!< in: pointer to byte where to store */ - ulint n) /*!< in: ulint integer to be stored, >= 0, < 256 */ -{ - ut_ad((n & ~0xFFUL) == 0); - - b[0] = (byte) n; -} - -#endif /* !UNIV_INNOCHECKSUM */ - -/*******************************************************//** -The following function is used to store data in two consecutive -bytes. We store the most significant byte to the lowest address. */ -UNIV_INLINE -void -mach_write_to_2( -/*============*/ - byte* b, /*!< in: pointer to two bytes where to store */ - ulint n) /*!< in: ulint integer to be stored */ -{ - ut_ad((n & ~0xFFFFUL) == 0); - - b[0] = (byte)(n >> 8); - b[1] = (byte)(n); -} - -/** The following function is used to fetch data from one byte. -@param[in] b pointer to a byte to read -@return ulint integer, >= 0, < 256 */ -UNIV_INLINE -uint8_t -mach_read_from_1( - const byte* b) -{ - return(uint8_t(*b)); -} - -/** The following function is used to fetch data from 2 consecutive -bytes. The most significant byte is at the lowest address. -@param[in] b pointer to 2 bytes to read -@return 2-byte integer, >= 0, < 64k */ -UNIV_INLINE -uint16_t -mach_read_from_2( - const byte* b) -{ - return(uint16_t(uint16_t(b[0]) << 8 | b[1])); -} - -#ifndef UNIV_INNOCHECKSUM - -/********************************************************//** -The following function is used to convert a 16-bit data item -to the canonical format, for fast bytewise equality test -against memory. -@return 16-bit integer in canonical format */ -UNIV_INLINE -uint16 -mach_encode_2( -/*==========*/ - ulint n) /*!< in: integer in machine-dependent format */ -{ - uint16 ret; - ut_ad(2 == sizeof ret); - mach_write_to_2((byte*) &ret, n); - return(ret); -} -/********************************************************//** -The following function is used to convert a 16-bit data item -from the canonical format, for fast bytewise equality test -against memory. -@return integer in machine-dependent format */ -UNIV_INLINE -ulint -mach_decode_2( -/*==========*/ - uint16 n) /*!< in: 16-bit integer in canonical format */ -{ - ut_ad(2 == sizeof n); - return(mach_read_from_2((const byte*) &n)); -} - -/*******************************************************//** -The following function is used to store data in 3 consecutive -bytes. We store the most significant byte to the lowest address. */ -UNIV_INLINE -void -mach_write_to_3( -/*============*/ - byte* b, /*!< in: pointer to 3 bytes where to store */ - ulint n) /*!< in: ulint integer to be stored */ -{ - ut_ad((n & ~0xFFFFFFUL) == 0); - - b[0] = (byte)(n >> 16); - b[1] = (byte)(n >> 8); - b[2] = (byte)(n); -} - -/** The following function is used to fetch data from 3 consecutive -bytes. The most significant byte is at the lowest address. -@param[in] b pointer to 3 bytes to read -@return uint32_t integer */ -UNIV_INLINE -uint32_t -mach_read_from_3( - const byte* b) -{ - return( (static_cast(b[0]) << 16) - | (static_cast(b[1]) << 8) - | static_cast(b[2]) - ); -} -#endif /* !UNIV_INNOCHECKSUM */ - -/*******************************************************//** -The following function is used to store data in four consecutive -bytes. We store the most significant byte to the lowest address. */ -UNIV_INLINE -void -mach_write_to_4( -/*============*/ - byte* b, /*!< in: pointer to four bytes where to store */ - ulint n) /*!< in: ulint integer to be stored */ -{ - b[0] = (byte)(n >> 24); - b[1] = (byte)(n >> 16); - b[2] = (byte)(n >> 8); - b[3] = (byte) n; -} - -/** The following function is used to fetch data from 4 consecutive -bytes. The most significant byte is at the lowest address. -@param[in] b pointer to 4 bytes to read -@return 32 bit integer */ -UNIV_INLINE -uint32_t -mach_read_from_4( - const byte* b) -{ - return( (static_cast(b[0]) << 24) - | (static_cast(b[1]) << 16) - | (static_cast(b[2]) << 8) - | static_cast(b[3]) - ); -} - -#ifndef UNIV_INNOCHECKSUM - -/*********************************************************//** -Writes a ulint in a compressed form where the first byte codes the -length of the stored ulint. We look at the most significant bits of -the byte. If the most significant bit is zero, it means 1-byte storage, -else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, -it means 3-byte storage, else if 4th is 0, it means 4-byte storage, -else the storage is 5-byte. -@return compressed size in bytes */ -UNIV_INLINE -ulint -mach_write_compressed( -/*==================*/ - byte* b, /*!< in: pointer to memory where to store */ - ulint n) /*!< in: ulint integer (< 2^32) to be stored */ -{ - if (n < 0x80) { - /* 0nnnnnnn (7 bits) */ - mach_write_to_1(b, n); - return(1); - } else if (n < 0x4000) { - /* 10nnnnnn nnnnnnnn (14 bits) */ - mach_write_to_2(b, n | 0x8000); - return(2); - } else if (n < 0x200000) { - /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ - mach_write_to_3(b, n | 0xC00000); - return(3); - } else if (n < 0x10000000) { - /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ - mach_write_to_4(b, n | 0xE0000000); - return(4); - } else { - /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ - mach_write_to_1(b, 0xF0); - mach_write_to_4(b + 1, n); - return(5); - } -} - -/*********************************************************//** -Returns the size of a ulint when written in the compressed form. -@return compressed size in bytes */ -UNIV_INLINE -ulint -mach_get_compressed_size( -/*=====================*/ - ulint n) /*!< in: ulint integer (< 2^32) to be stored */ -{ - if (n < 0x80) { - /* 0nnnnnnn (7 bits) */ - return(1); - } else if (n < 0x4000) { - /* 10nnnnnn nnnnnnnn (14 bits) */ - return(2); - } else if (n < 0x200000) { - /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ - return(3); - } else if (n < 0x10000000) { - /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ - return(4); - } else { - /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ - return(5); - } -} - -/*********************************************************//** -Reads a ulint in a compressed form. -@return read integer (< 2^32) */ -UNIV_INLINE -ulint -mach_read_compressed( -/*=================*/ - const byte* b) /*!< in: pointer to memory from where to read */ -{ - ulint val; - - val = mach_read_from_1(b); - - if (val < 0x80) { - /* 0nnnnnnn (7 bits) */ - } else if (val < 0xC0) { - /* 10nnnnnn nnnnnnnn (14 bits) */ - val = mach_read_from_2(b) & 0x3FFF; - ut_ad(val > 0x7F); - } else if (val < 0xE0) { - /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ - val = mach_read_from_3(b) & 0x1FFFFF; - ut_ad(val > 0x3FFF); - } else if (val < 0xF0) { - /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ - val = mach_read_from_4(b) & 0xFFFFFFF; - ut_ad(val > 0x1FFFFF); - } else { - /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ - ut_ad(val == 0xF0); - val = mach_read_from_4(b + 1); - ut_ad(val > 0xFFFFFFF); - } - - return(val); -} - -/** Read a 32-bit integer in a compressed form. -@param[in,out] b pointer to memory where to read; -advanced by the number of bytes consumed -@return unsigned value */ -UNIV_INLINE -ib_uint32_t -mach_read_next_compressed( - const byte** b) -{ - ulint val = mach_read_from_1(*b); - - if (val < 0x80) { - /* 0nnnnnnn (7 bits) */ - ++*b; - } else if (val < 0xC0) { - /* 10nnnnnn nnnnnnnn (14 bits) */ - val = mach_read_from_2(*b) & 0x3FFF; - ut_ad(val > 0x7F); - *b += 2; - } else if (val < 0xE0) { - /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ - val = mach_read_from_3(*b) & 0x1FFFFF; - ut_ad(val > 0x3FFF); - *b += 3; - } else if (val < 0xF0) { - /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ - val = mach_read_from_4(*b) & 0xFFFFFFF; - ut_ad(val > 0x1FFFFF); - *b += 4; - } else { - /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ - ut_ad(val == 0xF0); - val = mach_read_from_4(*b + 1); - ut_ad(val > 0xFFFFFFF); - *b += 5; - } - - return(static_cast(val)); -} - -/*******************************************************//** -The following function is used to store data in 8 consecutive -bytes. We store the most significant byte to the lowest address. */ -UNIV_INLINE -void -mach_write_to_8( -/*============*/ - void* b, /*!< in: pointer to 8 bytes where to store */ - ib_uint64_t n) /*!< in: 64-bit integer to be stored */ -{ - mach_write_to_4(static_cast(b), (ulint) (n >> 32)); - mach_write_to_4(static_cast(b) + 4, (ulint) n); -} - -#endif /* !UNIV_INNOCHECKSUM */ - -/********************************************************//** -The following function is used to fetch data from 8 consecutive -bytes. The most significant byte is at the lowest address. -@return 64-bit integer */ -UNIV_INLINE -ib_uint64_t -mach_read_from_8( -/*=============*/ - const byte* b) /*!< in: pointer to 8 bytes */ -{ - ib_uint64_t u64; - - u64 = mach_read_from_4(b); - u64 <<= 32; - u64 |= mach_read_from_4(b + 4); - - return(u64); -} - -#ifndef UNIV_INNOCHECKSUM - -/*******************************************************//** -The following function is used to store data in 7 consecutive -bytes. We store the most significant byte to the lowest address. */ -UNIV_INLINE -void -mach_write_to_7( -/*============*/ - byte* b, /*!< in: pointer to 7 bytes where to store */ - ib_uint64_t n) /*!< in: 56-bit integer */ -{ - mach_write_to_3(b, (ulint) (n >> 32)); - mach_write_to_4(b + 3, (ulint) n); -} - -/********************************************************//** -The following function is used to fetch data from 7 consecutive -bytes. The most significant byte is at the lowest address. -@return 56-bit integer */ -UNIV_INLINE -ib_uint64_t -mach_read_from_7( -/*=============*/ - const byte* b) /*!< in: pointer to 7 bytes */ -{ - return(ut_ull_create(mach_read_from_3(b), mach_read_from_4(b + 3))); -} - -/*******************************************************//** -The following function is used to store data in 6 consecutive -bytes. We store the most significant byte to the lowest address. */ -UNIV_INLINE -void -mach_write_to_6( -/*============*/ - byte* b, /*!< in: pointer to 6 bytes where to store */ - ib_uint64_t n) /*!< in: 48-bit integer */ -{ - mach_write_to_2(b, (ulint) (n >> 32)); - mach_write_to_4(b + 2, (ulint) n); -} - -/********************************************************//** -The following function is used to fetch data from 6 consecutive -bytes. The most significant byte is at the lowest address. -@return 48-bit integer */ -UNIV_INLINE -ib_uint64_t -mach_read_from_6( -/*=============*/ - const byte* b) /*!< in: pointer to 6 bytes */ -{ - return(ut_ull_create(mach_read_from_2(b), mach_read_from_4(b + 2))); -} - -/*********************************************************//** -Writes a 64-bit integer in a compressed form (5..9 bytes). -@return size in bytes */ -UNIV_INLINE -ulint -mach_u64_write_compressed( -/*======================*/ - byte* b, /*!< in: pointer to memory where to store */ - ib_uint64_t n) /*!< in: 64-bit integer to be stored */ -{ - ulint size = mach_write_compressed(b, (ulint) (n >> 32)); - mach_write_to_4(b + size, (ulint) n); - - return(size + 4); -} - -/** Read a 64-bit integer in a compressed form. -@param[in,out] b pointer to memory where to read; -advanced by the number of bytes consumed -@return unsigned value */ -UNIV_INLINE -ib_uint64_t -mach_u64_read_next_compressed( - const byte** b) -{ - ib_uint64_t val; - - val = mach_read_next_compressed(b); - val <<= 32; - val |= mach_read_from_4(*b); - *b += 4; - return(val); -} - -/*********************************************************//** -Writes a 64-bit integer in a compressed form (1..11 bytes). -@return size in bytes */ -UNIV_INLINE -ulint -mach_u64_write_much_compressed( -/*===========================*/ - byte* b, /*!< in: pointer to memory where to store */ - ib_uint64_t n) /*!< in: 64-bit integer to be stored */ -{ - ulint size; - - if (!(n >> 32)) { - return(mach_write_compressed(b, (ulint) n)); - } - - *b = (byte)0xFF; - size = 1 + mach_write_compressed(b + 1, (ulint) (n >> 32)); - - size += mach_write_compressed(b + size, (ulint) n & 0xFFFFFFFF); - - return(size); -} - -/*********************************************************//** -Reads a 64-bit integer in a compressed form. -@return the value read */ -UNIV_INLINE -ib_uint64_t -mach_u64_read_much_compressed( -/*==========================*/ - const byte* b) /*!< in: pointer to memory from where to read */ -{ - ib_uint64_t n; - - if (*b != 0xFF) { - return(mach_read_compressed(b)); - } - - b++; - n = mach_read_next_compressed(&b); - n <<= 32; - n |= mach_read_compressed(b); - - return(n); -} - -/** Read a 64-bit integer in a compressed form. -@param[in,out] b pointer to memory where to read; -advanced by the number of bytes consumed -@return unsigned value */ -UNIV_INLINE -ib_uint64_t -mach_read_next_much_compressed( - const byte** b) -{ - ib_uint64_t val = mach_read_from_1(*b); - - if (val < 0x80) { - /* 0nnnnnnn (7 bits) */ - ++*b; - } else if (val < 0xC0) { - /* 10nnnnnn nnnnnnnn (14 bits) */ - val = mach_read_from_2(*b) & 0x3FFF; - ut_ad(val > 0x7F); - *b += 2; - } else if (val < 0xE0) { - /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ - val = mach_read_from_3(*b) & 0x1FFFFF; - ut_ad(val > 0x3FFF); - *b += 3; - } else if (val < 0xF0) { - /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ - val = mach_read_from_4(*b) & 0xFFFFFFF; - ut_ad(val > 0x1FFFFF); - *b += 4; - } else if (val == 0xF0) { - /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ - val = mach_read_from_4(*b + 1); - ut_ad(val > 0xFFFFFFF); - *b += 5; - } else { - /* 11111111 followed by up to 64 bits */ - ut_ad(val == 0xFF); - ++*b; - val = mach_read_next_compressed(b); - ut_ad(val > 0); - val <<= 32; - val |= mach_read_next_compressed(b); - } - - return(val); -} - -/** Read a 64-bit integer in a compressed form. -@param[in,out] ptr pointer to memory where to read; -advanced by the number of bytes consumed, or set NULL if out of space -@param[in] end_ptr end of the buffer -@return unsigned value */ -UNIV_INLINE -ib_uint64_t -mach_u64_parse_compressed( - const byte** ptr, - const byte* end_ptr) -{ - ib_uint64_t val = 0; - - if (end_ptr < *ptr + 5) { - *ptr = NULL; - return(val); - } - - val = mach_read_next_compressed(ptr); - - if (end_ptr < *ptr + 4) { - *ptr = NULL; - return(val); - } - - val <<= 32; - val |= mach_read_from_4(*ptr); - *ptr += 4; - - return(val); -} - -/*********************************************************//** -Reads a double. It is stored in a little-endian format. -@return double read */ -UNIV_INLINE -double -mach_double_read( -/*=============*/ - const byte* b) /*!< in: pointer to memory from where to read */ -{ - double d; - ulint i; - byte* ptr; - - ptr = (byte*) &d; - - for (i = 0; i < sizeof(double); i++) { -#ifdef WORDS_BIGENDIAN - ptr[sizeof(double) - i - 1] = b[i]; -#else - ptr[i] = b[i]; -#endif - } - - return(d); -} - -/*********************************************************//** -Writes a double. It is stored in a little-endian format. */ -UNIV_INLINE -void -mach_double_write( -/*==============*/ - byte* b, /*!< in: pointer to memory where to write */ - double d) /*!< in: double */ -{ - ulint i; - byte* ptr; - - ptr = (byte*) &d; - - for (i = 0; i < sizeof(double); i++) { -#ifdef WORDS_BIGENDIAN - b[i] = ptr[sizeof(double) - i - 1]; -#else - b[i] = ptr[i]; -#endif - } -} - -/*********************************************************//** -Reads a float. It is stored in a little-endian format. -@return float read */ -UNIV_INLINE -float -mach_float_read( -/*============*/ - const byte* b) /*!< in: pointer to memory from where to read */ -{ - float d; - ulint i; - byte* ptr; - - ptr = (byte*) &d; - - for (i = 0; i < sizeof(float); i++) { -#ifdef WORDS_BIGENDIAN - ptr[sizeof(float) - i - 1] = b[i]; -#else - ptr[i] = b[i]; -#endif - } - - return(d); -} - -/*********************************************************//** -Writes a float. It is stored in a little-endian format. */ -UNIV_INLINE -void -mach_float_write( -/*=============*/ - byte* b, /*!< in: pointer to memory where to write */ - float d) /*!< in: float */ -{ - ulint i; - byte* ptr; - - ptr = (byte*) &d; - - for (i = 0; i < sizeof(float); i++) { -#ifdef WORDS_BIGENDIAN - b[i] = ptr[sizeof(float) - i - 1]; -#else - b[i] = ptr[i]; -#endif - } -} - -/*********************************************************//** -Reads a ulint stored in the little-endian format. -@return unsigned long int */ -UNIV_INLINE -ulint -mach_read_from_n_little_endian( -/*===========================*/ - const byte* buf, /*!< in: from where to read */ - ulint buf_size) /*!< in: from how many bytes to read */ -{ - ulint n = 0; - const byte* ptr; - - ut_ad(buf_size > 0); - - ptr = buf + buf_size; - - for (;;) { - ptr--; - - n = n << 8; - - n += (ulint)(*ptr); - - if (ptr == buf) { - break; - } - } - - return(n); -} - -/*********************************************************//** -Writes a ulint in the little-endian format. */ -UNIV_INLINE -void -mach_write_to_n_little_endian( -/*==========================*/ - byte* dest, /*!< in: where to write */ - ulint dest_size, /*!< in: into how many bytes to write */ - ulint n) /*!< in: unsigned long int to write */ -{ - byte* end; - - ut_ad(dest_size <= sizeof(ulint)); - ut_ad(dest_size > 0); - - end = dest + dest_size; - - for (;;) { - *dest = (byte)(n & 0xFF); - - n = n >> 8; - - dest++; - - if (dest == end) { - break; - } - } - - ut_ad(n == 0); -} - -/*********************************************************//** -Reads a ulint stored in the little-endian format. -@return unsigned long int */ -UNIV_INLINE -ulint -mach_read_from_2_little_endian( -/*===========================*/ - const byte* buf) /*!< in: from where to read */ -{ - return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8)); -} - -/*********************************************************//** -Writes a ulint in the little-endian format. */ -UNIV_INLINE -void -mach_write_to_2_little_endian( -/*==========================*/ - byte* dest, /*!< in: where to write */ - ulint n) /*!< in: unsigned long int to write */ -{ - ut_ad(n < 256 * 256); - - *dest = (byte)(n & 0xFFUL); - - n = n >> 8; - dest++; - - *dest = (byte)(n & 0xFFUL); -} - -/*********************************************************//** -Convert integral type from storage byte order (big endian) to -host byte order. -@return integer value */ -UNIV_INLINE -ib_uint64_t -mach_read_int_type( -/*===============*/ - const byte* src, /*!< in: where to read from */ - ulint len, /*!< in: length of src */ - ibool unsigned_type) /*!< in: signed or unsigned flag */ -{ - /* XXX this can be optimized on big-endian machines */ - - uintmax_t ret; - uint i; - - if (unsigned_type || (src[0] & 0x80)) { - - ret = 0x0000000000000000ULL; - } else { - - ret = 0xFFFFFFFFFFFFFF00ULL; - } - - if (unsigned_type) { - - ret |= src[0]; - } else { - - ret |= src[0] ^ 0x80; - } - - for (i = 1; i < len; i++) { - ret <<= 8; - ret |= src[i]; - } - - return(ret); -} -/*********************************************************//** -Swap byte ordering. */ -UNIV_INLINE -void -mach_swap_byte_order( -/*=================*/ - byte* dest, /*!< out: where to write */ - const byte* from, /*!< in: where to read from */ - ulint len) /*!< in: length of src */ -{ - ut_ad(len > 0); - ut_ad(len <= 8); - - dest += len; - - switch (len & 0x7) { - case 0: *--dest = *from++; /* fall through */ - case 7: *--dest = *from++; /* fall through */ - case 6: *--dest = *from++; /* fall through */ - case 5: *--dest = *from++; /* fall through */ - case 4: *--dest = *from++; /* fall through */ - case 3: *--dest = *from++; /* fall through */ - case 2: *--dest = *from++; /* fall through */ - case 1: *--dest = *from; - } -} - -/************************************************************* -Convert a ulonglong integer from host byte order to (big-endian) -storage byte order. */ -UNIV_INLINE -void -mach_write_ulonglong( -/*=================*/ - byte* dest, /*!< in: where to write */ - ulonglong src, /*!< in: where to read from */ - ulint len, /*!< in: length of dest */ - bool usign) /*!< in: signed or unsigned flag */ -{ - byte* ptr = reinterpret_cast(&src); - - ut_ad(len <= sizeof(ulonglong)); - -#ifdef WORDS_BIGENDIAN - memcpy(dest, ptr + (sizeof(src) - len), len); -#else - mach_swap_byte_order(dest, reinterpret_cast(ptr), len); -#endif /* WORDS_BIGENDIAN */ - - if (!usign) { - *dest ^= 0x80; - } -} - -#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/mach0data.inl b/storage/innobase/include/mach0data.inl new file mode 100644 index 00000000000..408044292a5 --- /dev/null +++ b/storage/innobase/include/mach0data.inl @@ -0,0 +1,893 @@ +/***************************************************************************** + +Copyright (c) 1995, 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/mach0data.ic +Utilities for converting data from the database file +to the machine format. + +Created 11/28/1995 Heikki Tuuri +***********************************************************************/ + +#ifndef UNIV_INNOCHECKSUM + +#include "mtr0types.h" + +/*******************************************************//** +The following function is used to store data in one byte. */ +UNIV_INLINE +void +mach_write_to_1( +/*============*/ + byte* b, /*!< in: pointer to byte where to store */ + ulint n) /*!< in: ulint integer to be stored, >= 0, < 256 */ +{ + ut_ad((n & ~0xFFUL) == 0); + + b[0] = (byte) n; +} + +#endif /* !UNIV_INNOCHECKSUM */ + +/*******************************************************//** +The following function is used to store data in two consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_2( +/*============*/ + byte* b, /*!< in: pointer to two bytes where to store */ + ulint n) /*!< in: ulint integer to be stored */ +{ + ut_ad((n & ~0xFFFFUL) == 0); + + b[0] = (byte)(n >> 8); + b[1] = (byte)(n); +} + +/** The following function is used to fetch data from one byte. +@param[in] b pointer to a byte to read +@return ulint integer, >= 0, < 256 */ +UNIV_INLINE +uint8_t +mach_read_from_1( + const byte* b) +{ + return(uint8_t(*b)); +} + +/** The following function is used to fetch data from 2 consecutive +bytes. The most significant byte is at the lowest address. +@param[in] b pointer to 2 bytes to read +@return 2-byte integer, >= 0, < 64k */ +UNIV_INLINE +uint16_t +mach_read_from_2( + const byte* b) +{ + return(uint16_t(uint16_t(b[0]) << 8 | b[1])); +} + +#ifndef UNIV_INNOCHECKSUM + +/********************************************************//** +The following function is used to convert a 16-bit data item +to the canonical format, for fast bytewise equality test +against memory. +@return 16-bit integer in canonical format */ +UNIV_INLINE +uint16 +mach_encode_2( +/*==========*/ + ulint n) /*!< in: integer in machine-dependent format */ +{ + uint16 ret; + ut_ad(2 == sizeof ret); + mach_write_to_2((byte*) &ret, n); + return(ret); +} +/********************************************************//** +The following function is used to convert a 16-bit data item +from the canonical format, for fast bytewise equality test +against memory. +@return integer in machine-dependent format */ +UNIV_INLINE +ulint +mach_decode_2( +/*==========*/ + uint16 n) /*!< in: 16-bit integer in canonical format */ +{ + ut_ad(2 == sizeof n); + return(mach_read_from_2((const byte*) &n)); +} + +/*******************************************************//** +The following function is used to store data in 3 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_3( +/*============*/ + byte* b, /*!< in: pointer to 3 bytes where to store */ + ulint n) /*!< in: ulint integer to be stored */ +{ + ut_ad((n & ~0xFFFFFFUL) == 0); + + b[0] = (byte)(n >> 16); + b[1] = (byte)(n >> 8); + b[2] = (byte)(n); +} + +/** The following function is used to fetch data from 3 consecutive +bytes. The most significant byte is at the lowest address. +@param[in] b pointer to 3 bytes to read +@return uint32_t integer */ +UNIV_INLINE +uint32_t +mach_read_from_3( + const byte* b) +{ + return( (static_cast(b[0]) << 16) + | (static_cast(b[1]) << 8) + | static_cast(b[2]) + ); +} +#endif /* !UNIV_INNOCHECKSUM */ + +/*******************************************************//** +The following function is used to store data in four consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_4( +/*============*/ + byte* b, /*!< in: pointer to four bytes where to store */ + ulint n) /*!< in: ulint integer to be stored */ +{ + b[0] = (byte)(n >> 24); + b[1] = (byte)(n >> 16); + b[2] = (byte)(n >> 8); + b[3] = (byte) n; +} + +/** The following function is used to fetch data from 4 consecutive +bytes. The most significant byte is at the lowest address. +@param[in] b pointer to 4 bytes to read +@return 32 bit integer */ +UNIV_INLINE +uint32_t +mach_read_from_4( + const byte* b) +{ + return( (static_cast(b[0]) << 24) + | (static_cast(b[1]) << 16) + | (static_cast(b[2]) << 8) + | static_cast(b[3]) + ); +} + +#ifndef UNIV_INNOCHECKSUM + +/*********************************************************//** +Writes a ulint in a compressed form where the first byte codes the +length of the stored ulint. We look at the most significant bits of +the byte. If the most significant bit is zero, it means 1-byte storage, +else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, +it means 3-byte storage, else if 4th is 0, it means 4-byte storage, +else the storage is 5-byte. +@return compressed size in bytes */ +UNIV_INLINE +ulint +mach_write_compressed( +/*==================*/ + byte* b, /*!< in: pointer to memory where to store */ + ulint n) /*!< in: ulint integer (< 2^32) to be stored */ +{ + if (n < 0x80) { + /* 0nnnnnnn (7 bits) */ + mach_write_to_1(b, n); + return(1); + } else if (n < 0x4000) { + /* 10nnnnnn nnnnnnnn (14 bits) */ + mach_write_to_2(b, n | 0x8000); + return(2); + } else if (n < 0x200000) { + /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ + mach_write_to_3(b, n | 0xC00000); + return(3); + } else if (n < 0x10000000) { + /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ + mach_write_to_4(b, n | 0xE0000000); + return(4); + } else { + /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ + mach_write_to_1(b, 0xF0); + mach_write_to_4(b + 1, n); + return(5); + } +} + +/*********************************************************//** +Returns the size of a ulint when written in the compressed form. +@return compressed size in bytes */ +UNIV_INLINE +ulint +mach_get_compressed_size( +/*=====================*/ + ulint n) /*!< in: ulint integer (< 2^32) to be stored */ +{ + if (n < 0x80) { + /* 0nnnnnnn (7 bits) */ + return(1); + } else if (n < 0x4000) { + /* 10nnnnnn nnnnnnnn (14 bits) */ + return(2); + } else if (n < 0x200000) { + /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ + return(3); + } else if (n < 0x10000000) { + /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ + return(4); + } else { + /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ + return(5); + } +} + +/*********************************************************//** +Reads a ulint in a compressed form. +@return read integer (< 2^32) */ +UNIV_INLINE +ulint +mach_read_compressed( +/*=================*/ + const byte* b) /*!< in: pointer to memory from where to read */ +{ + ulint val; + + val = mach_read_from_1(b); + + if (val < 0x80) { + /* 0nnnnnnn (7 bits) */ + } else if (val < 0xC0) { + /* 10nnnnnn nnnnnnnn (14 bits) */ + val = mach_read_from_2(b) & 0x3FFF; + ut_ad(val > 0x7F); + } else if (val < 0xE0) { + /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ + val = mach_read_from_3(b) & 0x1FFFFF; + ut_ad(val > 0x3FFF); + } else if (val < 0xF0) { + /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ + val = mach_read_from_4(b) & 0xFFFFFFF; + ut_ad(val > 0x1FFFFF); + } else { + /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ + ut_ad(val == 0xF0); + val = mach_read_from_4(b + 1); + ut_ad(val > 0xFFFFFFF); + } + + return(val); +} + +/** Read a 32-bit integer in a compressed form. +@param[in,out] b pointer to memory where to read; +advanced by the number of bytes consumed +@return unsigned value */ +UNIV_INLINE +ib_uint32_t +mach_read_next_compressed( + const byte** b) +{ + ulint val = mach_read_from_1(*b); + + if (val < 0x80) { + /* 0nnnnnnn (7 bits) */ + ++*b; + } else if (val < 0xC0) { + /* 10nnnnnn nnnnnnnn (14 bits) */ + val = mach_read_from_2(*b) & 0x3FFF; + ut_ad(val > 0x7F); + *b += 2; + } else if (val < 0xE0) { + /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ + val = mach_read_from_3(*b) & 0x1FFFFF; + ut_ad(val > 0x3FFF); + *b += 3; + } else if (val < 0xF0) { + /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ + val = mach_read_from_4(*b) & 0xFFFFFFF; + ut_ad(val > 0x1FFFFF); + *b += 4; + } else { + /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ + ut_ad(val == 0xF0); + val = mach_read_from_4(*b + 1); + ut_ad(val > 0xFFFFFFF); + *b += 5; + } + + return(static_cast(val)); +} + +/*******************************************************//** +The following function is used to store data in 8 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_8( +/*============*/ + void* b, /*!< in: pointer to 8 bytes where to store */ + ib_uint64_t n) /*!< in: 64-bit integer to be stored */ +{ + mach_write_to_4(static_cast(b), (ulint) (n >> 32)); + mach_write_to_4(static_cast(b) + 4, (ulint) n); +} + +#endif /* !UNIV_INNOCHECKSUM */ + +/********************************************************//** +The following function is used to fetch data from 8 consecutive +bytes. The most significant byte is at the lowest address. +@return 64-bit integer */ +UNIV_INLINE +ib_uint64_t +mach_read_from_8( +/*=============*/ + const byte* b) /*!< in: pointer to 8 bytes */ +{ + ib_uint64_t u64; + + u64 = mach_read_from_4(b); + u64 <<= 32; + u64 |= mach_read_from_4(b + 4); + + return(u64); +} + +#ifndef UNIV_INNOCHECKSUM + +/*******************************************************//** +The following function is used to store data in 7 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_7( +/*============*/ + byte* b, /*!< in: pointer to 7 bytes where to store */ + ib_uint64_t n) /*!< in: 56-bit integer */ +{ + mach_write_to_3(b, (ulint) (n >> 32)); + mach_write_to_4(b + 3, (ulint) n); +} + +/********************************************************//** +The following function is used to fetch data from 7 consecutive +bytes. The most significant byte is at the lowest address. +@return 56-bit integer */ +UNIV_INLINE +ib_uint64_t +mach_read_from_7( +/*=============*/ + const byte* b) /*!< in: pointer to 7 bytes */ +{ + return(ut_ull_create(mach_read_from_3(b), mach_read_from_4(b + 3))); +} + +/*******************************************************//** +The following function is used to store data in 6 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_6( +/*============*/ + byte* b, /*!< in: pointer to 6 bytes where to store */ + ib_uint64_t n) /*!< in: 48-bit integer */ +{ + mach_write_to_2(b, (ulint) (n >> 32)); + mach_write_to_4(b + 2, (ulint) n); +} + +/********************************************************//** +The following function is used to fetch data from 6 consecutive +bytes. The most significant byte is at the lowest address. +@return 48-bit integer */ +UNIV_INLINE +ib_uint64_t +mach_read_from_6( +/*=============*/ + const byte* b) /*!< in: pointer to 6 bytes */ +{ + return(ut_ull_create(mach_read_from_2(b), mach_read_from_4(b + 2))); +} + +/*********************************************************//** +Writes a 64-bit integer in a compressed form (5..9 bytes). +@return size in bytes */ +UNIV_INLINE +ulint +mach_u64_write_compressed( +/*======================*/ + byte* b, /*!< in: pointer to memory where to store */ + ib_uint64_t n) /*!< in: 64-bit integer to be stored */ +{ + ulint size = mach_write_compressed(b, (ulint) (n >> 32)); + mach_write_to_4(b + size, (ulint) n); + + return(size + 4); +} + +/** Read a 64-bit integer in a compressed form. +@param[in,out] b pointer to memory where to read; +advanced by the number of bytes consumed +@return unsigned value */ +UNIV_INLINE +ib_uint64_t +mach_u64_read_next_compressed( + const byte** b) +{ + ib_uint64_t val; + + val = mach_read_next_compressed(b); + val <<= 32; + val |= mach_read_from_4(*b); + *b += 4; + return(val); +} + +/*********************************************************//** +Writes a 64-bit integer in a compressed form (1..11 bytes). +@return size in bytes */ +UNIV_INLINE +ulint +mach_u64_write_much_compressed( +/*===========================*/ + byte* b, /*!< in: pointer to memory where to store */ + ib_uint64_t n) /*!< in: 64-bit integer to be stored */ +{ + ulint size; + + if (!(n >> 32)) { + return(mach_write_compressed(b, (ulint) n)); + } + + *b = (byte)0xFF; + size = 1 + mach_write_compressed(b + 1, (ulint) (n >> 32)); + + size += mach_write_compressed(b + size, (ulint) n & 0xFFFFFFFF); + + return(size); +} + +/*********************************************************//** +Reads a 64-bit integer in a compressed form. +@return the value read */ +UNIV_INLINE +ib_uint64_t +mach_u64_read_much_compressed( +/*==========================*/ + const byte* b) /*!< in: pointer to memory from where to read */ +{ + ib_uint64_t n; + + if (*b != 0xFF) { + return(mach_read_compressed(b)); + } + + b++; + n = mach_read_next_compressed(&b); + n <<= 32; + n |= mach_read_compressed(b); + + return(n); +} + +/** Read a 64-bit integer in a compressed form. +@param[in,out] b pointer to memory where to read; +advanced by the number of bytes consumed +@return unsigned value */ +UNIV_INLINE +ib_uint64_t +mach_read_next_much_compressed( + const byte** b) +{ + ib_uint64_t val = mach_read_from_1(*b); + + if (val < 0x80) { + /* 0nnnnnnn (7 bits) */ + ++*b; + } else if (val < 0xC0) { + /* 10nnnnnn nnnnnnnn (14 bits) */ + val = mach_read_from_2(*b) & 0x3FFF; + ut_ad(val > 0x7F); + *b += 2; + } else if (val < 0xE0) { + /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ + val = mach_read_from_3(*b) & 0x1FFFFF; + ut_ad(val > 0x3FFF); + *b += 3; + } else if (val < 0xF0) { + /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ + val = mach_read_from_4(*b) & 0xFFFFFFF; + ut_ad(val > 0x1FFFFF); + *b += 4; + } else if (val == 0xF0) { + /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ + val = mach_read_from_4(*b + 1); + ut_ad(val > 0xFFFFFFF); + *b += 5; + } else { + /* 11111111 followed by up to 64 bits */ + ut_ad(val == 0xFF); + ++*b; + val = mach_read_next_compressed(b); + ut_ad(val > 0); + val <<= 32; + val |= mach_read_next_compressed(b); + } + + return(val); +} + +/** Read a 64-bit integer in a compressed form. +@param[in,out] ptr pointer to memory where to read; +advanced by the number of bytes consumed, or set NULL if out of space +@param[in] end_ptr end of the buffer +@return unsigned value */ +UNIV_INLINE +ib_uint64_t +mach_u64_parse_compressed( + const byte** ptr, + const byte* end_ptr) +{ + ib_uint64_t val = 0; + + if (end_ptr < *ptr + 5) { + *ptr = NULL; + return(val); + } + + val = mach_read_next_compressed(ptr); + + if (end_ptr < *ptr + 4) { + *ptr = NULL; + return(val); + } + + val <<= 32; + val |= mach_read_from_4(*ptr); + *ptr += 4; + + return(val); +} + +/*********************************************************//** +Reads a double. It is stored in a little-endian format. +@return double read */ +UNIV_INLINE +double +mach_double_read( +/*=============*/ + const byte* b) /*!< in: pointer to memory from where to read */ +{ + double d; + ulint i; + byte* ptr; + + ptr = (byte*) &d; + + for (i = 0; i < sizeof(double); i++) { +#ifdef WORDS_BIGENDIAN + ptr[sizeof(double) - i - 1] = b[i]; +#else + ptr[i] = b[i]; +#endif + } + + return(d); +} + +/*********************************************************//** +Writes a double. It is stored in a little-endian format. */ +UNIV_INLINE +void +mach_double_write( +/*==============*/ + byte* b, /*!< in: pointer to memory where to write */ + double d) /*!< in: double */ +{ + ulint i; + byte* ptr; + + ptr = (byte*) &d; + + for (i = 0; i < sizeof(double); i++) { +#ifdef WORDS_BIGENDIAN + b[i] = ptr[sizeof(double) - i - 1]; +#else + b[i] = ptr[i]; +#endif + } +} + +/*********************************************************//** +Reads a float. It is stored in a little-endian format. +@return float read */ +UNIV_INLINE +float +mach_float_read( +/*============*/ + const byte* b) /*!< in: pointer to memory from where to read */ +{ + float d; + ulint i; + byte* ptr; + + ptr = (byte*) &d; + + for (i = 0; i < sizeof(float); i++) { +#ifdef WORDS_BIGENDIAN + ptr[sizeof(float) - i - 1] = b[i]; +#else + ptr[i] = b[i]; +#endif + } + + return(d); +} + +/*********************************************************//** +Writes a float. It is stored in a little-endian format. */ +UNIV_INLINE +void +mach_float_write( +/*=============*/ + byte* b, /*!< in: pointer to memory where to write */ + float d) /*!< in: float */ +{ + ulint i; + byte* ptr; + + ptr = (byte*) &d; + + for (i = 0; i < sizeof(float); i++) { +#ifdef WORDS_BIGENDIAN + b[i] = ptr[sizeof(float) - i - 1]; +#else + b[i] = ptr[i]; +#endif + } +} + +/*********************************************************//** +Reads a ulint stored in the little-endian format. +@return unsigned long int */ +UNIV_INLINE +ulint +mach_read_from_n_little_endian( +/*===========================*/ + const byte* buf, /*!< in: from where to read */ + ulint buf_size) /*!< in: from how many bytes to read */ +{ + ulint n = 0; + const byte* ptr; + + ut_ad(buf_size > 0); + + ptr = buf + buf_size; + + for (;;) { + ptr--; + + n = n << 8; + + n += (ulint)(*ptr); + + if (ptr == buf) { + break; + } + } + + return(n); +} + +/*********************************************************//** +Writes a ulint in the little-endian format. */ +UNIV_INLINE +void +mach_write_to_n_little_endian( +/*==========================*/ + byte* dest, /*!< in: where to write */ + ulint dest_size, /*!< in: into how many bytes to write */ + ulint n) /*!< in: unsigned long int to write */ +{ + byte* end; + + ut_ad(dest_size <= sizeof(ulint)); + ut_ad(dest_size > 0); + + end = dest + dest_size; + + for (;;) { + *dest = (byte)(n & 0xFF); + + n = n >> 8; + + dest++; + + if (dest == end) { + break; + } + } + + ut_ad(n == 0); +} + +/*********************************************************//** +Reads a ulint stored in the little-endian format. +@return unsigned long int */ +UNIV_INLINE +ulint +mach_read_from_2_little_endian( +/*===========================*/ + const byte* buf) /*!< in: from where to read */ +{ + return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8)); +} + +/*********************************************************//** +Writes a ulint in the little-endian format. */ +UNIV_INLINE +void +mach_write_to_2_little_endian( +/*==========================*/ + byte* dest, /*!< in: where to write */ + ulint n) /*!< in: unsigned long int to write */ +{ + ut_ad(n < 256 * 256); + + *dest = (byte)(n & 0xFFUL); + + n = n >> 8; + dest++; + + *dest = (byte)(n & 0xFFUL); +} + +/*********************************************************//** +Convert integral type from storage byte order (big endian) to +host byte order. +@return integer value */ +UNIV_INLINE +ib_uint64_t +mach_read_int_type( +/*===============*/ + const byte* src, /*!< in: where to read from */ + ulint len, /*!< in: length of src */ + ibool unsigned_type) /*!< in: signed or unsigned flag */ +{ + /* XXX this can be optimized on big-endian machines */ + + uintmax_t ret; + uint i; + + if (unsigned_type || (src[0] & 0x80)) { + + ret = 0x0000000000000000ULL; + } else { + + ret = 0xFFFFFFFFFFFFFF00ULL; + } + + if (unsigned_type) { + + ret |= src[0]; + } else { + + ret |= src[0] ^ 0x80; + } + + for (i = 1; i < len; i++) { + ret <<= 8; + ret |= src[i]; + } + + return(ret); +} +/*********************************************************//** +Swap byte ordering. */ +UNIV_INLINE +void +mach_swap_byte_order( +/*=================*/ + byte* dest, /*!< out: where to write */ + const byte* from, /*!< in: where to read from */ + ulint len) /*!< in: length of src */ +{ + ut_ad(len > 0); + ut_ad(len <= 8); + + dest += len; + + switch (len & 0x7) { + case 0: *--dest = *from++; /* fall through */ + case 7: *--dest = *from++; /* fall through */ + case 6: *--dest = *from++; /* fall through */ + case 5: *--dest = *from++; /* fall through */ + case 4: *--dest = *from++; /* fall through */ + case 3: *--dest = *from++; /* fall through */ + case 2: *--dest = *from++; /* fall through */ + case 1: *--dest = *from; + } +} + +/************************************************************* +Convert a ulonglong integer from host byte order to (big-endian) +storage byte order. */ +UNIV_INLINE +void +mach_write_ulonglong( +/*=================*/ + byte* dest, /*!< in: where to write */ + ulonglong src, /*!< in: where to read from */ + ulint len, /*!< in: length of dest */ + bool usign) /*!< in: signed or unsigned flag */ +{ + byte* ptr = reinterpret_cast(&src); + + ut_ad(len <= sizeof(ulonglong)); + +#ifdef WORDS_BIGENDIAN + memcpy(dest, ptr + (sizeof(src) - len), len); +#else + mach_swap_byte_order(dest, reinterpret_cast(ptr), len); +#endif /* WORDS_BIGENDIAN */ + + if (!usign) { + *dest ^= 0x80; + } +} + +#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/mem0mem.h b/storage/innobase/include/mem0mem.h index 0cd15ebb261..cf403744983 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -339,5 +339,5 @@ struct mem_block_info_t { #define MEM_BLOCK_HEADER_SIZE UT_CALC_ALIGN(sizeof(mem_block_info_t),\ UNIV_MEM_ALIGNMENT) -#include "mem0mem.ic" +#include "mem0mem.inl" #endif diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic deleted file mode 100644 index bd0db9bf503..00000000000 --- a/storage/innobase/include/mem0mem.ic +++ /dev/null @@ -1,482 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -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 -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/mem0mem.ic -The memory management - -Created 6/8/1994 Heikki Tuuri -*************************************************************************/ - -#ifdef UNIV_DEBUG -# define mem_heap_create_block(heap, n, type, file_name, line) \ - mem_heap_create_block_func(heap, n, file_name, line, type) -# define mem_heap_create_at(N, file_name, line) \ - mem_heap_create_func(N, file_name, line, MEM_HEAP_DYNAMIC) -#else /* UNIV_DEBUG */ -# define mem_heap_create_block(heap, n, type, file_name, line) \ - mem_heap_create_block_func(heap, n, type) -# define mem_heap_create_at(N, file_name, line) \ - mem_heap_create_func(N, MEM_HEAP_DYNAMIC) -#endif /* UNIV_DEBUG */ -/***************************************************************//** -Creates a memory heap block where data can be allocated. -@return own: memory heap block, NULL if did not succeed (only possible -for MEM_HEAP_BTR_SEARCH type heaps) */ -mem_block_t* -mem_heap_create_block_func( -/*=======================*/ - mem_heap_t* heap, /*!< in: memory heap or NULL if first block - should be created */ - ulint n, /*!< in: number of bytes needed for user data */ -#ifdef UNIV_DEBUG - const char* file_name,/*!< in: file name where created */ - unsigned line, /*!< in: line where created */ -#endif /* UNIV_DEBUG */ - ulint type); /*!< in: type of heap: MEM_HEAP_DYNAMIC or - MEM_HEAP_BUFFER */ - -/******************************************************************//** -Frees a block from a memory heap. */ -void -mem_heap_block_free( -/*================*/ - mem_heap_t* heap, /*!< in: heap */ - mem_block_t* block); /*!< in: block to free */ - -/******************************************************************//** -Frees the free_block field from a memory heap. */ -void -mem_heap_free_block_free( -/*=====================*/ - mem_heap_t* heap); /*!< in: heap */ - -/***************************************************************//** -Adds a new block to a memory heap. -@param[in] heap memory heap -@param[in] n number of bytes needed -@return created block, NULL if did not succeed (only possible for -MEM_HEAP_BTR_SEARCH type heaps) */ -mem_block_t* -mem_heap_add_block( - mem_heap_t* heap, - ulint n); - -UNIV_INLINE -void -mem_block_set_len(mem_block_t* block, ulint len) -{ - ut_ad(len > 0); - - block->len = len; -} - -UNIV_INLINE -ulint -mem_block_get_len(mem_block_t* block) -{ - return(block->len); -} - -UNIV_INLINE -void -mem_block_set_type(mem_block_t* block, ulint type) -{ - ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER) - || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH)); - - block->type = type; -} - -UNIV_INLINE -ulint -mem_block_get_type(mem_block_t* block) -{ - return(block->type); -} - -UNIV_INLINE -void -mem_block_set_free(mem_block_t* block, ulint free) -{ - ut_ad(free > 0); - ut_ad(free <= mem_block_get_len(block)); - - block->free = free; -} - -UNIV_INLINE -ulint -mem_block_get_free(mem_block_t* block) -{ - return(block->free); -} - -UNIV_INLINE -void -mem_block_set_start(mem_block_t* block, ulint start) -{ - ut_ad(start > 0); - - block->start = start; -} - -UNIV_INLINE -ulint -mem_block_get_start(mem_block_t* block) -{ - return(block->start); -} - -/** Allocates and zero-fills n bytes of memory from a memory heap. -@param[in] heap memory heap -@param[in] n number of bytes; if the heap is allowed to grow into -the buffer pool, this must be <= MEM_MAX_ALLOC_IN_BUF -@return allocated, zero-filled storage */ -UNIV_INLINE -void* -mem_heap_zalloc( - mem_heap_t* heap, - ulint n) -{ - ut_ad(heap); - ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH)); - return(memset(mem_heap_alloc(heap, n), 0, n)); -} - -/** Allocates n bytes of memory from a memory heap. -@param[in] heap memory heap -@param[in] n number of bytes; if the heap is allowed to grow into -the buffer pool, this must be <= MEM_MAX_ALLOC_IN_BUF -@return allocated storage, NULL if did not succeed (only possible for -MEM_HEAP_BTR_SEARCH type heaps) */ -UNIV_INLINE -void* -mem_heap_alloc( - mem_heap_t* heap, - ulint n) -{ - mem_block_t* block; - byte* buf; - ulint free; - - block = UT_LIST_GET_LAST(heap->base); - - n += REDZONE_SIZE; - - ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF)); - - /* Check if there is enough space in block. If not, create a new - block to the heap */ - - if (mem_block_get_len(block) - < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) { - - block = mem_heap_add_block(heap, n); - - if (block == NULL) { - - return(NULL); - } - } - - free = mem_block_get_free(block); - - buf = (byte*) block + free; - - mem_block_set_free(block, free + MEM_SPACE_NEEDED(n)); - - buf = buf + REDZONE_SIZE; - MEM_UNDEFINED(buf, n - REDZONE_SIZE); - return(buf); -} - -/** Returns a pointer to the heap top. -@param[in] heap memory heap -@return pointer to the heap top */ -UNIV_INLINE -byte* -mem_heap_get_heap_top( - mem_heap_t* heap) -{ - mem_block_t* block; - byte* buf; - - block = UT_LIST_GET_LAST(heap->base); - - buf = (byte*) block + mem_block_get_free(block); - - return(buf); -} - -/** Frees the space in a memory heap exceeding the pointer given. -The pointer must have been acquired from mem_heap_get_heap_top. -The first memory block of the heap is not freed. -@param[in] heap heap from which to free -@param[in] old_top pointer to old top of heap */ -UNIV_INLINE -void -mem_heap_free_heap_top( - mem_heap_t* heap, - byte* old_top) -{ - mem_block_t* block; - mem_block_t* prev_block; - - ut_d(mem_heap_validate(heap)); - - block = UT_LIST_GET_LAST(heap->base); - - while (block != NULL) { - if (((byte*) block + mem_block_get_free(block) >= old_top) - && ((byte*) block <= old_top)) { - /* Found the right block */ - - break; - } - - /* Store prev_block value before freeing the current block - (the current block will be erased in freeing) */ - - prev_block = UT_LIST_GET_PREV(list, block); - - mem_heap_block_free(heap, block); - - block = prev_block; - } - - ut_ad(block); - - /* Set the free field of block */ - mem_block_set_free(block, old_top - (byte*) block); - - ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); - MEM_NOACCESS(old_top, (byte*) block + block->len - old_top); - - /* If free == start, we may free the block if it is not the first - one */ - - if ((heap != block) && (mem_block_get_free(block) - == mem_block_get_start(block))) { - mem_heap_block_free(heap, block); - } -} - -/** Empties a memory heap. -The first memory block of the heap is not freed. -@param[in] heap heap to empty */ -UNIV_INLINE -void -mem_heap_empty( - mem_heap_t* heap) -{ - mem_heap_free_heap_top(heap, (byte*) heap + mem_block_get_start(heap)); - - if (heap->free_block) { - mem_heap_free_block_free(heap); - } -} - -/** Returns a pointer to the topmost element in a memory heap. -The size of the element must be given. -@param[in] heap memory heap -@param[in] n size of the topmost element -@return pointer to the topmost element */ -UNIV_INLINE -void* -mem_heap_get_top( - mem_heap_t* heap, - ulint n) -{ - mem_block_t* block; - byte* buf; - - block = UT_LIST_GET_LAST(heap->base); - - buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n); - - return((void*) buf); -} - -/*****************************************************************//** -Frees the topmost element in a memory heap. The size of the element must be -given. */ -UNIV_INLINE -void -mem_heap_free_top( -/*==============*/ - mem_heap_t* heap, /*!< in: memory heap */ - ulint n) /*!< in: size of the topmost element */ -{ - mem_block_t* block; - - n += REDZONE_SIZE; - - block = UT_LIST_GET_LAST(heap->base); - - /* Subtract the free field of block */ - mem_block_set_free(block, mem_block_get_free(block) - - MEM_SPACE_NEEDED(n)); - - /* If free == start, we may free the block if it is not the first - one */ - - if ((heap != block) && (mem_block_get_free(block) - == mem_block_get_start(block))) { - mem_heap_block_free(heap, block); - } else { - MEM_NOACCESS((byte*) block + mem_block_get_free(block), n); - } -} - -/** Creates a memory heap. -NOTE: Use the corresponding macros instead of this function. -A single user buffer of 'size' will fit in the block. -0 creates a default size block. -@param[in] size Desired start block size. -@param[in] file_name File name where created -@param[in] line Line where created -@param[in] type Heap type -@return own: memory heap, NULL if did not succeed (only possible for -MEM_HEAP_BTR_SEARCH type heaps) */ -UNIV_INLINE -mem_heap_t* -mem_heap_create_func( - ulint size, -#ifdef UNIV_DEBUG - const char* file_name, - unsigned line, -#endif /* UNIV_DEBUG */ - ulint type) -{ - mem_block_t* block; - - if (!size) { - size = MEM_BLOCK_START_SIZE; - } - - block = mem_heap_create_block(NULL, size, type, file_name, line); - - if (block == NULL) { - - return(NULL); - } - - /* The first block should not be in buffer pool, - because it might be relocated to resize buffer pool. */ - ut_ad(block->buf_block == NULL); - - UT_LIST_INIT(block->base, &mem_block_t::list); - - /* Add the created block itself as the first block in the list */ - UT_LIST_ADD_FIRST(block->base, block); - - return(block); -} - -/** Frees the space occupied by a memory heap. -NOTE: Use the corresponding macro instead of this function. -@param[in] heap Heap to be freed */ -UNIV_INLINE -void -mem_heap_free( - mem_heap_t* heap) -{ - mem_block_t* block; - mem_block_t* prev_block; - - block = UT_LIST_GET_LAST(heap->base); - - if (heap->free_block) { - mem_heap_free_block_free(heap); - } - - while (block != NULL) { - /* Store the contents of info before freeing current block - (it is erased in freeing) */ - - prev_block = UT_LIST_GET_PREV(list, block); - - mem_heap_block_free(heap, block); - - block = prev_block; - } -} - -/*****************************************************************//** -Returns the space in bytes occupied by a memory heap. */ -UNIV_INLINE -ulint -mem_heap_get_size( -/*==============*/ - mem_heap_t* heap) /*!< in: heap */ -{ - ulint size = heap->total_size; - - if (heap->free_block) { - size += UNIV_PAGE_SIZE; - } - - return(size); -} - -/**********************************************************************//** -Duplicates a NUL-terminated string. -@return own: a copy of the string, must be deallocated with ut_free */ -UNIV_INLINE -char* -mem_strdup( -/*=======*/ - const char* str) /*!< in: string to be copied */ -{ - ulint len = strlen(str) + 1; - return(static_cast(memcpy(ut_malloc_nokey(len), str, len))); -} - -/**********************************************************************//** -Makes a NUL-terminated copy of a nonterminated string. -@return own: a copy of the string, must be deallocated with ut_free */ -UNIV_INLINE -char* -mem_strdupl( -/*========*/ - const char* str, /*!< in: string to be copied */ - ulint len) /*!< in: length of str, in bytes */ -{ - char* s = static_cast(ut_malloc_nokey(len + 1)); - s[len] = 0; - return(static_cast(memcpy(s, str, len))); -} - -/**********************************************************************//** -Makes a NUL-terminated copy of a nonterminated string, -allocated from a memory heap. -@return own: a copy of the string */ -UNIV_INLINE -char* -mem_heap_strdupl( -/*=============*/ - mem_heap_t* heap, /*!< in: memory heap where string is allocated */ - const char* str, /*!< in: string to be copied */ - ulint len) /*!< in: length of str, in bytes */ -{ - char* s = (char*) mem_heap_alloc(heap, len + 1); - s[len] = 0; - return((char*) memcpy(s, str, len)); -} diff --git a/storage/innobase/include/mem0mem.inl b/storage/innobase/include/mem0mem.inl new file mode 100644 index 00000000000..bd0db9bf503 --- /dev/null +++ b/storage/innobase/include/mem0mem.inl @@ -0,0 +1,482 @@ +/***************************************************************************** + +Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. +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 +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/mem0mem.ic +The memory management + +Created 6/8/1994 Heikki Tuuri +*************************************************************************/ + +#ifdef UNIV_DEBUG +# define mem_heap_create_block(heap, n, type, file_name, line) \ + mem_heap_create_block_func(heap, n, file_name, line, type) +# define mem_heap_create_at(N, file_name, line) \ + mem_heap_create_func(N, file_name, line, MEM_HEAP_DYNAMIC) +#else /* UNIV_DEBUG */ +# define mem_heap_create_block(heap, n, type, file_name, line) \ + mem_heap_create_block_func(heap, n, type) +# define mem_heap_create_at(N, file_name, line) \ + mem_heap_create_func(N, MEM_HEAP_DYNAMIC) +#endif /* UNIV_DEBUG */ +/***************************************************************//** +Creates a memory heap block where data can be allocated. +@return own: memory heap block, NULL if did not succeed (only possible +for MEM_HEAP_BTR_SEARCH type heaps) */ +mem_block_t* +mem_heap_create_block_func( +/*=======================*/ + mem_heap_t* heap, /*!< in: memory heap or NULL if first block + should be created */ + ulint n, /*!< in: number of bytes needed for user data */ +#ifdef UNIV_DEBUG + const char* file_name,/*!< in: file name where created */ + unsigned line, /*!< in: line where created */ +#endif /* UNIV_DEBUG */ + ulint type); /*!< in: type of heap: MEM_HEAP_DYNAMIC or + MEM_HEAP_BUFFER */ + +/******************************************************************//** +Frees a block from a memory heap. */ +void +mem_heap_block_free( +/*================*/ + mem_heap_t* heap, /*!< in: heap */ + mem_block_t* block); /*!< in: block to free */ + +/******************************************************************//** +Frees the free_block field from a memory heap. */ +void +mem_heap_free_block_free( +/*=====================*/ + mem_heap_t* heap); /*!< in: heap */ + +/***************************************************************//** +Adds a new block to a memory heap. +@param[in] heap memory heap +@param[in] n number of bytes needed +@return created block, NULL if did not succeed (only possible for +MEM_HEAP_BTR_SEARCH type heaps) */ +mem_block_t* +mem_heap_add_block( + mem_heap_t* heap, + ulint n); + +UNIV_INLINE +void +mem_block_set_len(mem_block_t* block, ulint len) +{ + ut_ad(len > 0); + + block->len = len; +} + +UNIV_INLINE +ulint +mem_block_get_len(mem_block_t* block) +{ + return(block->len); +} + +UNIV_INLINE +void +mem_block_set_type(mem_block_t* block, ulint type) +{ + ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER) + || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH)); + + block->type = type; +} + +UNIV_INLINE +ulint +mem_block_get_type(mem_block_t* block) +{ + return(block->type); +} + +UNIV_INLINE +void +mem_block_set_free(mem_block_t* block, ulint free) +{ + ut_ad(free > 0); + ut_ad(free <= mem_block_get_len(block)); + + block->free = free; +} + +UNIV_INLINE +ulint +mem_block_get_free(mem_block_t* block) +{ + return(block->free); +} + +UNIV_INLINE +void +mem_block_set_start(mem_block_t* block, ulint start) +{ + ut_ad(start > 0); + + block->start = start; +} + +UNIV_INLINE +ulint +mem_block_get_start(mem_block_t* block) +{ + return(block->start); +} + +/** Allocates and zero-fills n bytes of memory from a memory heap. +@param[in] heap memory heap +@param[in] n number of bytes; if the heap is allowed to grow into +the buffer pool, this must be <= MEM_MAX_ALLOC_IN_BUF +@return allocated, zero-filled storage */ +UNIV_INLINE +void* +mem_heap_zalloc( + mem_heap_t* heap, + ulint n) +{ + ut_ad(heap); + ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH)); + return(memset(mem_heap_alloc(heap, n), 0, n)); +} + +/** Allocates n bytes of memory from a memory heap. +@param[in] heap memory heap +@param[in] n number of bytes; if the heap is allowed to grow into +the buffer pool, this must be <= MEM_MAX_ALLOC_IN_BUF +@return allocated storage, NULL if did not succeed (only possible for +MEM_HEAP_BTR_SEARCH type heaps) */ +UNIV_INLINE +void* +mem_heap_alloc( + mem_heap_t* heap, + ulint n) +{ + mem_block_t* block; + byte* buf; + ulint free; + + block = UT_LIST_GET_LAST(heap->base); + + n += REDZONE_SIZE; + + ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF)); + + /* Check if there is enough space in block. If not, create a new + block to the heap */ + + if (mem_block_get_len(block) + < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) { + + block = mem_heap_add_block(heap, n); + + if (block == NULL) { + + return(NULL); + } + } + + free = mem_block_get_free(block); + + buf = (byte*) block + free; + + mem_block_set_free(block, free + MEM_SPACE_NEEDED(n)); + + buf = buf + REDZONE_SIZE; + MEM_UNDEFINED(buf, n - REDZONE_SIZE); + return(buf); +} + +/** Returns a pointer to the heap top. +@param[in] heap memory heap +@return pointer to the heap top */ +UNIV_INLINE +byte* +mem_heap_get_heap_top( + mem_heap_t* heap) +{ + mem_block_t* block; + byte* buf; + + block = UT_LIST_GET_LAST(heap->base); + + buf = (byte*) block + mem_block_get_free(block); + + return(buf); +} + +/** Frees the space in a memory heap exceeding the pointer given. +The pointer must have been acquired from mem_heap_get_heap_top. +The first memory block of the heap is not freed. +@param[in] heap heap from which to free +@param[in] old_top pointer to old top of heap */ +UNIV_INLINE +void +mem_heap_free_heap_top( + mem_heap_t* heap, + byte* old_top) +{ + mem_block_t* block; + mem_block_t* prev_block; + + ut_d(mem_heap_validate(heap)); + + block = UT_LIST_GET_LAST(heap->base); + + while (block != NULL) { + if (((byte*) block + mem_block_get_free(block) >= old_top) + && ((byte*) block <= old_top)) { + /* Found the right block */ + + break; + } + + /* Store prev_block value before freeing the current block + (the current block will be erased in freeing) */ + + prev_block = UT_LIST_GET_PREV(list, block); + + mem_heap_block_free(heap, block); + + block = prev_block; + } + + ut_ad(block); + + /* Set the free field of block */ + mem_block_set_free(block, old_top - (byte*) block); + + ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); + MEM_NOACCESS(old_top, (byte*) block + block->len - old_top); + + /* If free == start, we may free the block if it is not the first + one */ + + if ((heap != block) && (mem_block_get_free(block) + == mem_block_get_start(block))) { + mem_heap_block_free(heap, block); + } +} + +/** Empties a memory heap. +The first memory block of the heap is not freed. +@param[in] heap heap to empty */ +UNIV_INLINE +void +mem_heap_empty( + mem_heap_t* heap) +{ + mem_heap_free_heap_top(heap, (byte*) heap + mem_block_get_start(heap)); + + if (heap->free_block) { + mem_heap_free_block_free(heap); + } +} + +/** Returns a pointer to the topmost element in a memory heap. +The size of the element must be given. +@param[in] heap memory heap +@param[in] n size of the topmost element +@return pointer to the topmost element */ +UNIV_INLINE +void* +mem_heap_get_top( + mem_heap_t* heap, + ulint n) +{ + mem_block_t* block; + byte* buf; + + block = UT_LIST_GET_LAST(heap->base); + + buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n); + + return((void*) buf); +} + +/*****************************************************************//** +Frees the topmost element in a memory heap. The size of the element must be +given. */ +UNIV_INLINE +void +mem_heap_free_top( +/*==============*/ + mem_heap_t* heap, /*!< in: memory heap */ + ulint n) /*!< in: size of the topmost element */ +{ + mem_block_t* block; + + n += REDZONE_SIZE; + + block = UT_LIST_GET_LAST(heap->base); + + /* Subtract the free field of block */ + mem_block_set_free(block, mem_block_get_free(block) + - MEM_SPACE_NEEDED(n)); + + /* If free == start, we may free the block if it is not the first + one */ + + if ((heap != block) && (mem_block_get_free(block) + == mem_block_get_start(block))) { + mem_heap_block_free(heap, block); + } else { + MEM_NOACCESS((byte*) block + mem_block_get_free(block), n); + } +} + +/** Creates a memory heap. +NOTE: Use the corresponding macros instead of this function. +A single user buffer of 'size' will fit in the block. +0 creates a default size block. +@param[in] size Desired start block size. +@param[in] file_name File name where created +@param[in] line Line where created +@param[in] type Heap type +@return own: memory heap, NULL if did not succeed (only possible for +MEM_HEAP_BTR_SEARCH type heaps) */ +UNIV_INLINE +mem_heap_t* +mem_heap_create_func( + ulint size, +#ifdef UNIV_DEBUG + const char* file_name, + unsigned line, +#endif /* UNIV_DEBUG */ + ulint type) +{ + mem_block_t* block; + + if (!size) { + size = MEM_BLOCK_START_SIZE; + } + + block = mem_heap_create_block(NULL, size, type, file_name, line); + + if (block == NULL) { + + return(NULL); + } + + /* The first block should not be in buffer pool, + because it might be relocated to resize buffer pool. */ + ut_ad(block->buf_block == NULL); + + UT_LIST_INIT(block->base, &mem_block_t::list); + + /* Add the created block itself as the first block in the list */ + UT_LIST_ADD_FIRST(block->base, block); + + return(block); +} + +/** Frees the space occupied by a memory heap. +NOTE: Use the corresponding macro instead of this function. +@param[in] heap Heap to be freed */ +UNIV_INLINE +void +mem_heap_free( + mem_heap_t* heap) +{ + mem_block_t* block; + mem_block_t* prev_block; + + block = UT_LIST_GET_LAST(heap->base); + + if (heap->free_block) { + mem_heap_free_block_free(heap); + } + + while (block != NULL) { + /* Store the contents of info before freeing current block + (it is erased in freeing) */ + + prev_block = UT_LIST_GET_PREV(list, block); + + mem_heap_block_free(heap, block); + + block = prev_block; + } +} + +/*****************************************************************//** +Returns the space in bytes occupied by a memory heap. */ +UNIV_INLINE +ulint +mem_heap_get_size( +/*==============*/ + mem_heap_t* heap) /*!< in: heap */ +{ + ulint size = heap->total_size; + + if (heap->free_block) { + size += UNIV_PAGE_SIZE; + } + + return(size); +} + +/**********************************************************************//** +Duplicates a NUL-terminated string. +@return own: a copy of the string, must be deallocated with ut_free */ +UNIV_INLINE +char* +mem_strdup( +/*=======*/ + const char* str) /*!< in: string to be copied */ +{ + ulint len = strlen(str) + 1; + return(static_cast(memcpy(ut_malloc_nokey(len), str, len))); +} + +/**********************************************************************//** +Makes a NUL-terminated copy of a nonterminated string. +@return own: a copy of the string, must be deallocated with ut_free */ +UNIV_INLINE +char* +mem_strdupl( +/*========*/ + const char* str, /*!< in: string to be copied */ + ulint len) /*!< in: length of str, in bytes */ +{ + char* s = static_cast(ut_malloc_nokey(len + 1)); + s[len] = 0; + return(static_cast(memcpy(s, str, len))); +} + +/**********************************************************************//** +Makes a NUL-terminated copy of a nonterminated string, +allocated from a memory heap. +@return own: a copy of the string */ +UNIV_INLINE +char* +mem_heap_strdupl( +/*=============*/ + mem_heap_t* heap, /*!< in: memory heap where string is allocated */ + const char* str, /*!< in: string to be copied */ + ulint len) /*!< in: length of str, in bytes */ +{ + char* s = (char*) mem_heap_alloc(heap, len + 1); + s[len] = 0; + return((char*) memcpy(s, str, len)); +} diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h index eaf2fad9e7f..38ce2ac0274 100644 --- a/storage/innobase/include/mtr0log.h +++ b/storage/innobase/include/mtr0log.h @@ -242,6 +242,6 @@ mlog_parse_index( extra mlog buffer size for variable size data */ #define MLOG_BUF_MARGIN 256 -#include "mtr0log.ic" +#include "mtr0log.inl" #endif /* mtr0log_h */ diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic deleted file mode 100644 index 5cfc08622d5..00000000000 --- a/storage/innobase/include/mtr0log.ic +++ /dev/null @@ -1,248 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, 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/mtr0log.ic -Mini-transaction logging routines - -Created 12/7/1995 Heikki Tuuri -*******************************************************/ - -#include "buf0dblwr.h" -#include "fsp0types.h" -#include "mach0data.h" -#include "trx0types.h" - -/********************************************************//** -Opens a buffer to mlog. It must be closed with mlog_close. -@return buffer, NULL if log mode MTR_LOG_NONE or MTR_LOG_NO_REDO */ -UNIV_INLINE -byte* -mlog_open( -/*======*/ - mtr_t* mtr, /*!< in: mtr */ - ulint size) /*!< in: buffer size in bytes; MUST be - smaller than mtr_t::buf_t::MAX_DATA_SIZE! */ -{ - mtr->set_modified(); - - if (mtr_get_log_mode(mtr) == MTR_LOG_NONE - || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { - - return(NULL); - } - - return(mtr->get_log()->open(size)); -} - -/********************************************************//** -Closes a buffer opened to mlog. */ -UNIV_INLINE -void -mlog_close( -/*=======*/ - mtr_t* mtr, /*!< in: mtr */ - byte* ptr) /*!< in: buffer space from ptr up was not used */ -{ - ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NONE); - ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NO_REDO); - - mtr->get_log()->close(ptr); -} - -/********************************************************//** -Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ -UNIV_INLINE -void -mlog_catenate_ulint( -/*================*/ - mtr_buf_t* mtr_buf, /*!< in/out: buffer to write */ - ulint val, /*!< in: value to write */ - mlog_id_t type) /*!< in: type of value to write */ -{ - compile_time_assert(MLOG_1BYTE == 1); - compile_time_assert(MLOG_2BYTES == 2); - compile_time_assert(MLOG_4BYTES == 4); - compile_time_assert(MLOG_8BYTES == 8); - - byte* ptr = mtr_buf->push(type); - - switch (type) { - case MLOG_4BYTES: - mach_write_to_4(ptr, val); - break; - case MLOG_2BYTES: - mach_write_to_2(ptr, val); - break; - case MLOG_1BYTE: - mach_write_to_1(ptr, val); - break; - default: - ut_error; - } -} - -/********************************************************//** -Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ -UNIV_INLINE -void -mlog_catenate_ulint( -/*================*/ - mtr_t* mtr, /*!< in/out: mtr */ - ulint val, /*!< in: value to write */ - mlog_id_t type) /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ -{ - if (mtr_get_log_mode(mtr) == MTR_LOG_NONE - || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { - - return; - } - - mlog_catenate_ulint(mtr->get_log(), val, type); -} - -/********************************************************//** -Catenates a compressed ulint to mlog. */ -UNIV_INLINE -void -mlog_catenate_ulint_compressed( -/*===========================*/ - mtr_t* mtr, /*!< in: mtr */ - ulint val) /*!< in: value to write */ -{ - byte* log_ptr; - - log_ptr = mlog_open(mtr, 10); - - /* If no logging is requested, we may return now */ - if (log_ptr == NULL) { - - return; - } - - log_ptr += mach_write_compressed(log_ptr, val); - - mlog_close(mtr, log_ptr); -} - -/********************************************************//** -Catenates a compressed 64-bit integer to mlog. */ -UNIV_INLINE -void -mlog_catenate_ull_compressed( -/*=========================*/ - mtr_t* mtr, /*!< in: mtr */ - ib_uint64_t val) /*!< in: value to write */ -{ - byte* log_ptr; - - log_ptr = mlog_open(mtr, 15); - - /* If no logging is requested, we may return now */ - if (log_ptr == NULL) { - - return; - } - - log_ptr += mach_u64_write_compressed(log_ptr, val); - - mlog_close(mtr, log_ptr); -} - -/** Writes a log record about an operation. -@param[in] type redo log record type -@param[in] space_id tablespace identifier -@param[in] page_no page number -@param[in,out] log_ptr current end of mini-transaction log -@param[in,out] mtr mini-transaction -@return end of mini-transaction log */ -UNIV_INLINE -byte* -mlog_write_initial_log_record_low( - mlog_id_t type, - ulint space_id, - ulint page_no, - byte* log_ptr, - mtr_t* mtr) -{ - ut_ad(type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(type)); - ut_ad(type == MLOG_FILE_NAME - || type == MLOG_FILE_DELETE - || type == MLOG_FILE_CREATE2 - || type == MLOG_FILE_RENAME2 - || type == MLOG_INDEX_LOAD - || type == MLOG_TRUNCATE - || type == MLOG_FILE_WRITE_CRYPT_DATA - || mtr->is_named_space(space_id)); - - mach_write_to_1(log_ptr, type); - log_ptr++; - - log_ptr += mach_write_compressed(log_ptr, space_id); - log_ptr += mach_write_compressed(log_ptr, page_no); - - mtr->added_rec(); - return(log_ptr); -} - -/********************************************************//** -Writes the initial part of a log record (3..11 bytes). -If the implementation of this function is changed, all -size parameters to mlog_open() should be adjusted accordingly! -@return new value of log_ptr */ -UNIV_INLINE -byte* -mlog_write_initial_log_record_fast( -/*===============================*/ - const byte* ptr, /*!< in: pointer to (inside) a buffer - frame holding the file page where - modification is made */ - mlog_id_t type, /*!< in: log item type: MLOG_1BYTE, ... */ - byte* log_ptr,/*!< in: pointer to mtr log which has - been opened */ - mtr_t* mtr) /*!< in/out: mtr */ -{ - const byte* page; - ulint space; - ulint offset; - - ut_ad(log_ptr); - ut_d(mtr->memo_modify_page(ptr)); - - page = (const byte*) ut_align_down(ptr, UNIV_PAGE_SIZE); - space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - offset = mach_read_from_4(page + FIL_PAGE_OFFSET); - - /* check whether the page is in the doublewrite buffer; - the doublewrite buffer is located in pages - FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the - system tablespace */ - - if (space == TRX_SYS_SPACE - && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) { - ut_ad(buf_dblwr_being_created); - /* Do nothing: we only come to this branch in an - InnoDB database creation. We do not redo log - anything for the doublewrite buffer pages. */ - return(log_ptr); - } - - return(mlog_write_initial_log_record_low(type, space, offset, - log_ptr, mtr)); -} diff --git a/storage/innobase/include/mtr0log.inl b/storage/innobase/include/mtr0log.inl new file mode 100644 index 00000000000..5cfc08622d5 --- /dev/null +++ b/storage/innobase/include/mtr0log.inl @@ -0,0 +1,248 @@ +/***************************************************************************** + +Copyright (c) 1995, 2016, 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/mtr0log.ic +Mini-transaction logging routines + +Created 12/7/1995 Heikki Tuuri +*******************************************************/ + +#include "buf0dblwr.h" +#include "fsp0types.h" +#include "mach0data.h" +#include "trx0types.h" + +/********************************************************//** +Opens a buffer to mlog. It must be closed with mlog_close. +@return buffer, NULL if log mode MTR_LOG_NONE or MTR_LOG_NO_REDO */ +UNIV_INLINE +byte* +mlog_open( +/*======*/ + mtr_t* mtr, /*!< in: mtr */ + ulint size) /*!< in: buffer size in bytes; MUST be + smaller than mtr_t::buf_t::MAX_DATA_SIZE! */ +{ + mtr->set_modified(); + + if (mtr_get_log_mode(mtr) == MTR_LOG_NONE + || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { + + return(NULL); + } + + return(mtr->get_log()->open(size)); +} + +/********************************************************//** +Closes a buffer opened to mlog. */ +UNIV_INLINE +void +mlog_close( +/*=======*/ + mtr_t* mtr, /*!< in: mtr */ + byte* ptr) /*!< in: buffer space from ptr up was not used */ +{ + ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NONE); + ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NO_REDO); + + mtr->get_log()->close(ptr); +} + +/********************************************************//** +Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ +UNIV_INLINE +void +mlog_catenate_ulint( +/*================*/ + mtr_buf_t* mtr_buf, /*!< in/out: buffer to write */ + ulint val, /*!< in: value to write */ + mlog_id_t type) /*!< in: type of value to write */ +{ + compile_time_assert(MLOG_1BYTE == 1); + compile_time_assert(MLOG_2BYTES == 2); + compile_time_assert(MLOG_4BYTES == 4); + compile_time_assert(MLOG_8BYTES == 8); + + byte* ptr = mtr_buf->push(type); + + switch (type) { + case MLOG_4BYTES: + mach_write_to_4(ptr, val); + break; + case MLOG_2BYTES: + mach_write_to_2(ptr, val); + break; + case MLOG_1BYTE: + mach_write_to_1(ptr, val); + break; + default: + ut_error; + } +} + +/********************************************************//** +Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ +UNIV_INLINE +void +mlog_catenate_ulint( +/*================*/ + mtr_t* mtr, /*!< in/out: mtr */ + ulint val, /*!< in: value to write */ + mlog_id_t type) /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ +{ + if (mtr_get_log_mode(mtr) == MTR_LOG_NONE + || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { + + return; + } + + mlog_catenate_ulint(mtr->get_log(), val, type); +} + +/********************************************************//** +Catenates a compressed ulint to mlog. */ +UNIV_INLINE +void +mlog_catenate_ulint_compressed( +/*===========================*/ + mtr_t* mtr, /*!< in: mtr */ + ulint val) /*!< in: value to write */ +{ + byte* log_ptr; + + log_ptr = mlog_open(mtr, 10); + + /* If no logging is requested, we may return now */ + if (log_ptr == NULL) { + + return; + } + + log_ptr += mach_write_compressed(log_ptr, val); + + mlog_close(mtr, log_ptr); +} + +/********************************************************//** +Catenates a compressed 64-bit integer to mlog. */ +UNIV_INLINE +void +mlog_catenate_ull_compressed( +/*=========================*/ + mtr_t* mtr, /*!< in: mtr */ + ib_uint64_t val) /*!< in: value to write */ +{ + byte* log_ptr; + + log_ptr = mlog_open(mtr, 15); + + /* If no logging is requested, we may return now */ + if (log_ptr == NULL) { + + return; + } + + log_ptr += mach_u64_write_compressed(log_ptr, val); + + mlog_close(mtr, log_ptr); +} + +/** Writes a log record about an operation. +@param[in] type redo log record type +@param[in] space_id tablespace identifier +@param[in] page_no page number +@param[in,out] log_ptr current end of mini-transaction log +@param[in,out] mtr mini-transaction +@return end of mini-transaction log */ +UNIV_INLINE +byte* +mlog_write_initial_log_record_low( + mlog_id_t type, + ulint space_id, + ulint page_no, + byte* log_ptr, + mtr_t* mtr) +{ + ut_ad(type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(type)); + ut_ad(type == MLOG_FILE_NAME + || type == MLOG_FILE_DELETE + || type == MLOG_FILE_CREATE2 + || type == MLOG_FILE_RENAME2 + || type == MLOG_INDEX_LOAD + || type == MLOG_TRUNCATE + || type == MLOG_FILE_WRITE_CRYPT_DATA + || mtr->is_named_space(space_id)); + + mach_write_to_1(log_ptr, type); + log_ptr++; + + log_ptr += mach_write_compressed(log_ptr, space_id); + log_ptr += mach_write_compressed(log_ptr, page_no); + + mtr->added_rec(); + return(log_ptr); +} + +/********************************************************//** +Writes the initial part of a log record (3..11 bytes). +If the implementation of this function is changed, all +size parameters to mlog_open() should be adjusted accordingly! +@return new value of log_ptr */ +UNIV_INLINE +byte* +mlog_write_initial_log_record_fast( +/*===============================*/ + const byte* ptr, /*!< in: pointer to (inside) a buffer + frame holding the file page where + modification is made */ + mlog_id_t type, /*!< in: log item type: MLOG_1BYTE, ... */ + byte* log_ptr,/*!< in: pointer to mtr log which has + been opened */ + mtr_t* mtr) /*!< in/out: mtr */ +{ + const byte* page; + ulint space; + ulint offset; + + ut_ad(log_ptr); + ut_d(mtr->memo_modify_page(ptr)); + + page = (const byte*) ut_align_down(ptr, UNIV_PAGE_SIZE); + space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + offset = mach_read_from_4(page + FIL_PAGE_OFFSET); + + /* check whether the page is in the doublewrite buffer; + the doublewrite buffer is located in pages + FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the + system tablespace */ + + if (space == TRX_SYS_SPACE + && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) { + ut_ad(buf_dblwr_being_created); + /* Do nothing: we only come to this branch in an + InnoDB database creation. We do not redo log + anything for the doublewrite buffer pages. */ + return(log_ptr); + } + + return(mlog_write_initial_log_record_low(type, space, offset, + log_ptr, mtr)); +} diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 6d729beab12..8ca84a394f7 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -504,6 +504,6 @@ private: lsn_t m_commit_lsn; }; -#include "mtr0mtr.ic" +#include "mtr0mtr.inl" #endif /* mtr0mtr_h */ diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic deleted file mode 100644 index 24477689db8..00000000000 --- a/storage/innobase/include/mtr0mtr.ic +++ /dev/null @@ -1,280 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2021, 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/mtr0mtr.ic -Mini-transaction buffer - -Created 11/26/1995 Heikki Tuuri -*******************************************************/ - -#include "buf0buf.h" - -/** Check if a mini-transaction is dirtying a clean page. -@return true if the mtr is dirtying a clean page. */ -bool -mtr_t::is_block_dirtied(const buf_block_t* block) -{ - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_ad(block->page.buf_fix_count > 0); - - /* It is OK to read oldest_modification because no - other thread can be performing a write of it and it - is only during write that the value is reset to 0. */ - return(block->page.oldest_modification == 0); -} - -/** -Pushes an object to an mtr memo stack. */ -void -mtr_t::memo_push(void* object, mtr_memo_type_t type) -{ - ut_ad(is_active()); - ut_ad(object != NULL); - ut_ad(type >= MTR_MEMO_PAGE_S_FIX); - ut_ad(type <= MTR_MEMO_SPACE_X_LOCK); - ut_ad(ut_is_2pow(type)); - - /* If this mtr has x-fixed a clean page then we set - the made_dirty flag. This tells us if we need to - grab log_sys.flush_order_mutex at mtr_t::commit() so that we - can insert the dirtied page into the flush list. */ - - if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) - && !m_made_dirty) { - - m_made_dirty = is_block_dirtied( - reinterpret_cast(object)); - } - - mtr_memo_slot_t* slot = m_memo.push(sizeof(*slot)); - - slot->type = type; - slot->object = object; -} - -/** -Releases the (index tree) s-latch stored in an mtr memo after a -savepoint. */ -void -mtr_t::release_s_latch_at_savepoint( - ulint savepoint, - rw_lock_t* lock) -{ - ut_ad(is_active()); - ut_ad(m_memo.size() > savepoint); - - mtr_memo_slot_t* slot = m_memo.at(savepoint); - - ut_ad(slot->object == lock); - ut_ad(slot->type == MTR_MEMO_S_LOCK); - - rw_lock_s_unlock(lock); - - slot->object = NULL; -} - -/** -SX-latches the not yet latched block after a savepoint. */ - -void -mtr_t::sx_latch_at_savepoint( - ulint savepoint, - buf_block_t* block) -{ - ut_ad(is_active()); - ut_ad(m_memo.size() > savepoint); - - ut_ad(!memo_contains_flagged( - block, - MTR_MEMO_PAGE_S_FIX - | MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - - mtr_memo_slot_t* slot = m_memo.at(savepoint); - - ut_ad(slot->object == block); - - /* == RW_NO_LATCH */ - ut_a(slot->type == MTR_MEMO_BUF_FIX); - - rw_lock_sx_lock(&block->lock); - - if (!m_made_dirty) { - m_made_dirty = is_block_dirtied(block); - } - - slot->type = MTR_MEMO_PAGE_SX_FIX; -} - -/** -X-latches the not yet latched block after a savepoint. */ - -void -mtr_t::x_latch_at_savepoint( - ulint savepoint, - buf_block_t* block) -{ - ut_ad(is_active()); - ut_ad(m_memo.size() > savepoint); - - ut_ad(!memo_contains_flagged( - block, - MTR_MEMO_PAGE_S_FIX - | MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - - mtr_memo_slot_t* slot = m_memo.at(savepoint); - - ut_ad(slot->object == block); - - /* == RW_NO_LATCH */ - ut_a(slot->type == MTR_MEMO_BUF_FIX); - - rw_lock_x_lock(&block->lock); - - if (!m_made_dirty) { - m_made_dirty = is_block_dirtied(block); - } - - slot->type = MTR_MEMO_PAGE_X_FIX; -} - -/** -Releases the block in an mtr memo after a savepoint. */ - -void -mtr_t::release_block_at_savepoint( - ulint savepoint, - buf_block_t* block) -{ - ut_ad(is_active()); - - mtr_memo_slot_t* slot = m_memo.at(savepoint); - - ut_a(slot->object == block); - - buf_page_release_latch(block, slot->type); - - buf_block_unfix(reinterpret_cast(block)); - - slot->object = NULL; -} - -/** -Gets the logging mode of a mini-transaction. -@return logging mode: MTR_LOG_NONE, ... */ - -mtr_log_t -mtr_t::get_log_mode() const -{ - ut_ad(m_log_mode >= MTR_LOG_ALL); - ut_ad(m_log_mode <= MTR_LOG_SHORT_INSERTS); - - return m_log_mode; -} - -/** -Changes the logging mode of a mini-transaction. -@return old mode */ - -mtr_log_t -mtr_t::set_log_mode(mtr_log_t mode) -{ - ut_ad(mode >= MTR_LOG_ALL); - ut_ad(mode <= MTR_LOG_SHORT_INSERTS); - - const mtr_log_t old_mode = m_log_mode; - - switch (old_mode) { - case MTR_LOG_NO_REDO: - /* Once this mode is set, it must not be changed. */ - ut_ad(mode == MTR_LOG_NO_REDO || mode == MTR_LOG_NONE); - return(old_mode); - case MTR_LOG_NONE: - if (mode == old_mode || mode == MTR_LOG_SHORT_INSERTS) { - /* Keep MTR_LOG_NONE. */ - return(old_mode); - } - /* fall through */ - case MTR_LOG_SHORT_INSERTS: - ut_ad(mode == MTR_LOG_ALL); - /* fall through */ - case MTR_LOG_ALL: - /* MTR_LOG_NO_REDO can only be set before generating - any redo log records. */ - ut_ad(mode != MTR_LOG_NO_REDO || m_n_log_recs == 0); - m_log_mode = mode; - return(old_mode); - } - - ut_ad(0); - return(old_mode); -} - -/** -Locks a lock in s-mode. */ - -void -mtr_t::s_lock(rw_lock_t* lock, const char* file, unsigned line) -{ - rw_lock_s_lock_inline(lock, 0, file, line); - - memo_push(lock, MTR_MEMO_S_LOCK); -} - -/** -Locks a lock in x-mode. */ - -void -mtr_t::x_lock(rw_lock_t* lock, const char* file, unsigned line) -{ - rw_lock_x_lock_inline(lock, 0, file, line); - - memo_push(lock, MTR_MEMO_X_LOCK); -} - -/** -Locks a lock in sx-mode. */ - -void -mtr_t::sx_lock(rw_lock_t* lock, const char* file, unsigned line) -{ - rw_lock_sx_lock_inline(lock, 0, file, line); - - memo_push(lock, MTR_MEMO_SX_LOCK); -} - -/** -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/mtr0mtr.inl b/storage/innobase/include/mtr0mtr.inl new file mode 100644 index 00000000000..24477689db8 --- /dev/null +++ b/storage/innobase/include/mtr0mtr.inl @@ -0,0 +1,280 @@ +/***************************************************************************** + +Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2021, 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/mtr0mtr.ic +Mini-transaction buffer + +Created 11/26/1995 Heikki Tuuri +*******************************************************/ + +#include "buf0buf.h" + +/** Check if a mini-transaction is dirtying a clean page. +@return true if the mtr is dirtying a clean page. */ +bool +mtr_t::is_block_dirtied(const buf_block_t* block) +{ + ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.buf_fix_count > 0); + + /* It is OK to read oldest_modification because no + other thread can be performing a write of it and it + is only during write that the value is reset to 0. */ + return(block->page.oldest_modification == 0); +} + +/** +Pushes an object to an mtr memo stack. */ +void +mtr_t::memo_push(void* object, mtr_memo_type_t type) +{ + ut_ad(is_active()); + ut_ad(object != NULL); + ut_ad(type >= MTR_MEMO_PAGE_S_FIX); + ut_ad(type <= MTR_MEMO_SPACE_X_LOCK); + ut_ad(ut_is_2pow(type)); + + /* If this mtr has x-fixed a clean page then we set + the made_dirty flag. This tells us if we need to + grab log_sys.flush_order_mutex at mtr_t::commit() so that we + can insert the dirtied page into the flush list. */ + + if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) + && !m_made_dirty) { + + m_made_dirty = is_block_dirtied( + reinterpret_cast(object)); + } + + mtr_memo_slot_t* slot = m_memo.push(sizeof(*slot)); + + slot->type = type; + slot->object = object; +} + +/** +Releases the (index tree) s-latch stored in an mtr memo after a +savepoint. */ +void +mtr_t::release_s_latch_at_savepoint( + ulint savepoint, + rw_lock_t* lock) +{ + ut_ad(is_active()); + ut_ad(m_memo.size() > savepoint); + + mtr_memo_slot_t* slot = m_memo.at(savepoint); + + ut_ad(slot->object == lock); + ut_ad(slot->type == MTR_MEMO_S_LOCK); + + rw_lock_s_unlock(lock); + + slot->object = NULL; +} + +/** +SX-latches the not yet latched block after a savepoint. */ + +void +mtr_t::sx_latch_at_savepoint( + ulint savepoint, + buf_block_t* block) +{ + ut_ad(is_active()); + ut_ad(m_memo.size() > savepoint); + + ut_ad(!memo_contains_flagged( + block, + MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_SX_FIX)); + + mtr_memo_slot_t* slot = m_memo.at(savepoint); + + ut_ad(slot->object == block); + + /* == RW_NO_LATCH */ + ut_a(slot->type == MTR_MEMO_BUF_FIX); + + rw_lock_sx_lock(&block->lock); + + if (!m_made_dirty) { + m_made_dirty = is_block_dirtied(block); + } + + slot->type = MTR_MEMO_PAGE_SX_FIX; +} + +/** +X-latches the not yet latched block after a savepoint. */ + +void +mtr_t::x_latch_at_savepoint( + ulint savepoint, + buf_block_t* block) +{ + ut_ad(is_active()); + ut_ad(m_memo.size() > savepoint); + + ut_ad(!memo_contains_flagged( + block, + MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_SX_FIX)); + + mtr_memo_slot_t* slot = m_memo.at(savepoint); + + ut_ad(slot->object == block); + + /* == RW_NO_LATCH */ + ut_a(slot->type == MTR_MEMO_BUF_FIX); + + rw_lock_x_lock(&block->lock); + + if (!m_made_dirty) { + m_made_dirty = is_block_dirtied(block); + } + + slot->type = MTR_MEMO_PAGE_X_FIX; +} + +/** +Releases the block in an mtr memo after a savepoint. */ + +void +mtr_t::release_block_at_savepoint( + ulint savepoint, + buf_block_t* block) +{ + ut_ad(is_active()); + + mtr_memo_slot_t* slot = m_memo.at(savepoint); + + ut_a(slot->object == block); + + buf_page_release_latch(block, slot->type); + + buf_block_unfix(reinterpret_cast(block)); + + slot->object = NULL; +} + +/** +Gets the logging mode of a mini-transaction. +@return logging mode: MTR_LOG_NONE, ... */ + +mtr_log_t +mtr_t::get_log_mode() const +{ + ut_ad(m_log_mode >= MTR_LOG_ALL); + ut_ad(m_log_mode <= MTR_LOG_SHORT_INSERTS); + + return m_log_mode; +} + +/** +Changes the logging mode of a mini-transaction. +@return old mode */ + +mtr_log_t +mtr_t::set_log_mode(mtr_log_t mode) +{ + ut_ad(mode >= MTR_LOG_ALL); + ut_ad(mode <= MTR_LOG_SHORT_INSERTS); + + const mtr_log_t old_mode = m_log_mode; + + switch (old_mode) { + case MTR_LOG_NO_REDO: + /* Once this mode is set, it must not be changed. */ + ut_ad(mode == MTR_LOG_NO_REDO || mode == MTR_LOG_NONE); + return(old_mode); + case MTR_LOG_NONE: + if (mode == old_mode || mode == MTR_LOG_SHORT_INSERTS) { + /* Keep MTR_LOG_NONE. */ + return(old_mode); + } + /* fall through */ + case MTR_LOG_SHORT_INSERTS: + ut_ad(mode == MTR_LOG_ALL); + /* fall through */ + case MTR_LOG_ALL: + /* MTR_LOG_NO_REDO can only be set before generating + any redo log records. */ + ut_ad(mode != MTR_LOG_NO_REDO || m_n_log_recs == 0); + m_log_mode = mode; + return(old_mode); + } + + ut_ad(0); + return(old_mode); +} + +/** +Locks a lock in s-mode. */ + +void +mtr_t::s_lock(rw_lock_t* lock, const char* file, unsigned line) +{ + rw_lock_s_lock_inline(lock, 0, file, line); + + memo_push(lock, MTR_MEMO_S_LOCK); +} + +/** +Locks a lock in x-mode. */ + +void +mtr_t::x_lock(rw_lock_t* lock, const char* file, unsigned line) +{ + rw_lock_x_lock_inline(lock, 0, file, line); + + memo_push(lock, MTR_MEMO_X_LOCK); +} + +/** +Locks a lock in sx-mode. */ + +void +mtr_t::sx_lock(rw_lock_t* lock, const char* file, unsigned line) +{ + rw_lock_sx_lock_inline(lock, 0, file, line); + + memo_push(lock, MTR_MEMO_SX_LOCK); +} + +/** +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/os0file.h b/storage/innobase/include/os0file.h index 23de5bd0ef1..5ccb89d68fa 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -1675,6 +1675,6 @@ os_file_get_block_size( os_file_t file, /*!< in: handle to a file */ const char* name); /*!< in: file name */ -#include "os0file.ic" +#include "os0file.inl" #endif /* os0file_h */ diff --git a/storage/innobase/include/os0file.ic b/storage/innobase/include/os0file.ic deleted file mode 100644 index f363bd5135a..00000000000 --- a/storage/innobase/include/os0file.ic +++ /dev/null @@ -1,599 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2010, 2017, Oracle and/or its affiliates. All Rights Reserved. -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 -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/os0file.ic -The interface to the operating system file io - -Created 2/20/2010 Jimmy Yang -*******************************************************/ - -#ifdef UNIV_PFS_IO -/** NOTE! Please use the corresponding macro os_file_create_simple(), -not directly this function! -A performance schema instrumented wrapper function for -os_file_create_simple() which opens or creates a file. -@param[in] key Performance Schema Key -@param[in] name name of the file or path as a null-terminated - string -@param[in] create_mode create mode -@param[in] access_type OS_FILE_READ_ONLY or OS_FILE_READ_WRITE -@param[in] read_only if true read only mode checks are enforced -@param[out] success true if succeeded -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return own: handle to the file, not defined if error, error number -can be retrieved with os_file_get_last_error */ -UNIV_INLINE -pfs_os_file_t -pfs_os_file_create_simple_func( - mysql_pfs_key_t key, - const char* name, - ulint create_mode, - ulint access_type, - bool read_only, - bool* success, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - /* register a file open or creation depending on "create_mode" */ - register_pfs_file_open_begin( - &state, locker, key, - (create_mode == OS_FILE_CREATE) - ? PSI_FILE_CREATE : PSI_FILE_OPEN, - name, src_file, src_line); - - pfs_os_file_t file = os_file_create_simple_func( - name, create_mode, access_type, read_only, success); - - /* Register psi value for the file */ - register_pfs_file_open_end(locker, file, - (*success == TRUE ? success : 0)); - - return(file); -} - -/** NOTE! Please use the corresponding macro -os_file_create_simple_no_error_handling(), not directly this function! -A performance schema instrumented wrapper function for -os_file_create_simple_no_error_handling(). Add instrumentation to -monitor file creation/open. -@param[in] key Performance Schema Key -@param[in] name name of the file or path as a null-terminated - string -@param[in] create_mode create mode -@param[in] access_type OS_FILE_READ_ONLY, OS_FILE_READ_WRITE, or - OS_FILE_READ_ALLOW_DELETE; the last option is - used by a backup program reading the file -@param[in] read_only if true read only mode checks are enforced -@param[out] success true if succeeded -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return own: handle to the file, not defined if error, error number -can be retrieved with os_file_get_last_error */ -UNIV_INLINE -pfs_os_file_t -pfs_os_file_create_simple_no_error_handling_func( - mysql_pfs_key_t key, - const char* name, - ulint create_mode, - ulint access_type, - bool read_only, - bool* success, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - /* register a file open or creation depending on "create_mode" */ - register_pfs_file_open_begin( - &state, locker, key, - create_mode == OS_FILE_CREATE - ? PSI_FILE_CREATE : PSI_FILE_OPEN, - name, src_file, src_line); - - pfs_os_file_t file = os_file_create_simple_no_error_handling_func( - name, create_mode, access_type, read_only, success); - - register_pfs_file_open_end(locker, file, - (*success == TRUE ? success : 0)); - - return(file); -} - -/** NOTE! Please use the corresponding macro os_file_create(), not directly -this function! -A performance schema wrapper function for os_file_create(). -Add instrumentation to monitor file creation/open. -@param[in] key Performance Schema Key -@param[in] name name of the file or path as a null-terminated - string -@param[in] create_mode create mode -@param[in] purpose OS_FILE_AIO, if asynchronous, non-buffered I/O - is desired, OS_FILE_NORMAL, if any normal file; - NOTE that it also depends on type, os_aio_.. - and srv_.. variables whether we really us - async I/O or unbuffered I/O: look in the - function source code for the exact rules -@param[in] read_only if true read only mode checks are enforced -@param[out] success true if succeeded -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return own: handle to the file, not defined if error, error number -can be retrieved with os_file_get_last_error */ -UNIV_INLINE -pfs_os_file_t -pfs_os_file_create_func( - mysql_pfs_key_t key, - const char* name, - ulint create_mode, - ulint purpose, - ulint type, - bool read_only, - bool* success, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - /* register a file open or creation depending on "create_mode" */ - register_pfs_file_open_begin( - &state, locker, key, - create_mode == OS_FILE_CREATE - ? PSI_FILE_CREATE : PSI_FILE_OPEN, - name, src_file, src_line); - - pfs_os_file_t file = os_file_create_func( - name, create_mode, purpose, type, read_only, success); - - register_pfs_file_open_end(locker, file, - (*success == TRUE ? success : 0)); - - return(file); -} -/** -NOTE! Please use the corresponding macro os_file_close(), not directly -this function! -A performance schema instrumented wrapper function for os_file_close(). -@param[in] file handle to a file -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return true if success */ -UNIV_INLINE -bool -pfs_os_file_close_func( - pfs_os_file_t file, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - /* register the file close */ - register_pfs_file_io_begin( - &state, locker, file, 0, PSI_FILE_CLOSE, src_file, src_line); - - bool result = os_file_close_func(file); - - register_pfs_file_io_end(locker, 0); - - return(result); -} - -/** NOTE! Please use the corresponding macro os_aio(), not directly this -function! -Performance schema wrapper function of os_aio() which requests -an asynchronous i/o operation. -@param[in,type] type IO request context -@param[in] mode IO mode -@param[in] name Name of the file or path as NUL terminated - string -@param[in] file Open file handle -@param[out] buf buffer where to read -@param[in] offset file offset where to read -@param[in] n number of bytes to read -@param[in] read_only if true read only mode checks are enforced -@param[in,out] m1 Message for the AIO handler, (can be used to - identify a completed AIO operation); ignored - if mode is OS_AIO_SYNC -@param[in,out] m2 message for the AIO handler (can be used to - identify a completed AIO operation); ignored - if mode is OS_AIO_SYNC -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return DB_SUCCESS if request was queued successfully, FALSE if fail */ -UNIV_INLINE -dberr_t -pfs_os_aio_func( - IORequest& type, - ulint mode, - const char* name, - pfs_os_file_t file, - void* buf, - os_offset_t offset, - ulint n, - bool read_only, - fil_node_t* m1, - void* m2, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - ut_ad(type.validate()); - - /* Register the read or write I/O depending on "type" */ - register_pfs_file_io_begin( - &state, locker, file, n, - type.is_write() ? PSI_FILE_WRITE : PSI_FILE_READ, - src_file, src_line); - - dberr_t result = os_aio_func( - type, mode, name, file, buf, offset, n, read_only, m1, m2); - - register_pfs_file_io_end(locker, n); - - return(result); -} - -/** NOTE! Please use the corresponding macro os_file_read(), not directly -this function! -This is the performance schema instrumented wrapper function for -os_file_read() which requests a synchronous read operation. -@param[in] type IO request context -@param[in] file Open file handle -@param[out] buf buffer where to read -@param[in] offset file offset where to read -@param[in] n number of bytes to read -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return DB_SUCCESS if request was successful */ -UNIV_INLINE -dberr_t -pfs_os_file_read_func( - const IORequest& type, - pfs_os_file_t file, - void* buf, - os_offset_t offset, - ulint n, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - ut_ad(type.validate()); - - register_pfs_file_io_begin( - &state, locker, file, n, PSI_FILE_READ, src_file, src_line); - - dberr_t result; - - result = os_file_read_func(type, file, buf, offset, n); - - register_pfs_file_io_end(locker, n); - - return(result); -} - -/** NOTE! Please use the corresponding macro os_file_read_no_error_handling(), -not directly this function! -This is the performance schema instrumented wrapper function for -os_file_read_no_error_handling_func() which requests a synchronous -read operation. -@param[in] type IO request context -@param[in] file Open file handle -@param[out] buf buffer where to read -@param[in] offset file offset where to read -@param[in] n number of bytes to read -@param[out] o number of bytes actually read -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return DB_SUCCESS if request was successful */ -UNIV_INLINE -dberr_t -pfs_os_file_read_no_error_handling_func( - const IORequest& type, - pfs_os_file_t file, - void* buf, - os_offset_t offset, - ulint n, - ulint* o, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - register_pfs_file_io_begin( - &state, locker, file, n, PSI_FILE_READ, src_file, src_line); - - dberr_t result = os_file_read_no_error_handling_func( - type, file, buf, offset, n, o); - - register_pfs_file_io_end(locker, n); - - return(result); -} - -/** NOTE! Please use the corresponding macro -os_file_read_no_error_handling_int_fd() to request -a synchronous read operation. -@param[in] type read request -@param[in] file file handle -@param[out] buf buffer where to read -@param[in] offset file offset where to read -@param[in] n number of bytes to read -@param[in] src_file caller file name -@param[in] src_line caller line number -@return error code -@retval DB_SUCCESS if the operation succeeded */ -UNIV_INLINE -dberr_t -pfs_os_file_read_no_error_handling_int_fd_func( - const IORequest& type, - int file, - void* buf, - os_offset_t offset, - ulint n, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - - PSI_file_locker* locker = PSI_FILE_CALL( - get_thread_file_descriptor_locker)( - &state, file, PSI_FILE_READ); - if (locker != NULL) { - PSI_FILE_CALL(start_file_wait)( - locker, n, - __FILE__, __LINE__); - } - - dberr_t err = os_file_read_no_error_handling_func( - type, OS_FILE_FROM_FD(file), buf, offset, n, NULL); - - if (locker != NULL) { - PSI_FILE_CALL(end_file_wait)(locker, n); - } - - return err; -} - -/** NOTE! Please use the corresponding macro os_file_write(), not directly -this function! -This is the performance schema instrumented wrapper function for -os_file_write() which requests a synchronous write operation. -@param[in] type IO request context -@param[in] name Name of the file or path as NUL terminated - string -@param[in] file Open file handle -@param[out] buf buffer where to read -@param[in] offset file offset where to read -@param[in] n number of bytes to read -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return error code -@retval DB_SUCCESS if the request was successfully fulfilled */ -UNIV_INLINE -dberr_t -pfs_os_file_write_func( - const IORequest& type, - const char* name, - pfs_os_file_t file, - const void* buf, - os_offset_t offset, - ulint n, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - register_pfs_file_io_begin( - &state, locker, file, n, PSI_FILE_WRITE, src_file, src_line); - - dberr_t result; - - result = os_file_write_func(type, name, file, buf, offset, n); - - register_pfs_file_io_end(locker, n); - - return(result); -} - -/** NOTE! Please use the corresponding macro os_file_write_int_fd(), -not directly this function! -This is the performance schema instrumented wrapper function for -os_file_write_int_fd() which requests a synchronous write operation. -@param[in] type write request -@param[in] name file name -@param[in] file file handle -@param[in] buf buffer to write -@param[in] offset file offset -@param[in] n number of bytes -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return error code -@retval DB_SUCCESS if the operation succeeded */ -UNIV_INLINE -dberr_t -pfs_os_file_write_int_fd_func( - const IORequest& type, - const char* name, - int file, - const void* buf, - os_offset_t offset, - ulint n, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker; - - locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( - &state, file, PSI_FILE_WRITE); - if (locker != NULL) { - PSI_FILE_CALL(start_file_wait)( - locker, n, - __FILE__, __LINE__); - } - - dberr_t err = os_file_write_func( - type, name, OS_FILE_FROM_FD(file), buf, offset, n); - - if (locker != NULL) { - PSI_FILE_CALL(end_file_wait)(locker, n); - } - - return err; -} - -/** NOTE! Please use the corresponding macro os_file_flush(), not directly -this function! -This is the performance schema instrumented wrapper function for -os_file_flush() which flushes the write buffers of a given file to the disk. -Flushes the write buffers of a given file to the disk. -@param[in] file Open file handle -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return TRUE if success */ -UNIV_INLINE -bool -pfs_os_file_flush_func( - pfs_os_file_t file, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - register_pfs_file_io_begin( - &state, locker, file, 0, PSI_FILE_SYNC, src_file, src_line); - - bool result = os_file_flush_func(file); - - register_pfs_file_io_end(locker, 0); - - return(result); -} - -/** NOTE! Please use the corresponding macro os_file_rename(), not directly -this function! -This is the performance schema instrumented wrapper function for -os_file_rename() -@param[in] key Performance Schema Key -@param[in] oldpath old file path as a null-terminated string -@param[in] newpath new file path -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return true if success */ -UNIV_INLINE -bool -pfs_os_file_rename_func( - mysql_pfs_key_t key, - const char* oldpath, - const char* newpath, - const char* src_file, - uint src_line) - -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - register_pfs_file_open_begin( - &state, locker, key, PSI_FILE_RENAME, newpath, - src_file, src_line); - - bool result = os_file_rename_func(oldpath, newpath); - - register_pfs_file_rename_end(locker, 0); - - return(result); -} - -/** NOTE! Please use the corresponding macro os_file_delete(), not directly -this function! -This is the performance schema instrumented wrapper function for -os_file_delete() -@param[in] key Performance Schema Key -@param[in] name old file path as a null-terminated string -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return true if success */ -UNIV_INLINE -bool -pfs_os_file_delete_func( - mysql_pfs_key_t key, - const char* name, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - register_pfs_file_close_begin( - &state, locker, key, PSI_FILE_DELETE, name, src_file, src_line); - - bool result = os_file_delete_func(name); - - register_pfs_file_close_end(locker, 0); - - return(result); -} - -/** -NOTE! Please use the corresponding macro os_file_delete_if_exists(), not -directly this function! -This is the performance schema instrumented wrapper function for -os_file_delete_if_exists() -@param[in] key Performance Schema Key -@param[in] name old file path as a null-terminated string -@param[in] exist indicate if file pre-exist -@param[in] src_file file name where func invoked -@param[in] src_line line where the func invoked -@return true if success */ -UNIV_INLINE -bool -pfs_os_file_delete_if_exists_func( - mysql_pfs_key_t key, - const char* name, - bool* exist, - const char* src_file, - uint src_line) -{ - PSI_file_locker_state state; - struct PSI_file_locker* locker = NULL; - - register_pfs_file_close_begin( - &state, locker, key, PSI_FILE_DELETE, name, src_file, src_line); - - bool result = os_file_delete_if_exists_func(name, exist); - - register_pfs_file_close_end(locker, 0); - - return(result); -} -#endif /* UNIV_PFS_IO */ diff --git a/storage/innobase/include/os0file.inl b/storage/innobase/include/os0file.inl new file mode 100644 index 00000000000..f363bd5135a --- /dev/null +++ b/storage/innobase/include/os0file.inl @@ -0,0 +1,599 @@ +/***************************************************************************** + +Copyright (c) 2010, 2017, Oracle and/or its affiliates. All Rights Reserved. +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 +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/os0file.ic +The interface to the operating system file io + +Created 2/20/2010 Jimmy Yang +*******************************************************/ + +#ifdef UNIV_PFS_IO +/** NOTE! Please use the corresponding macro os_file_create_simple(), +not directly this function! +A performance schema instrumented wrapper function for +os_file_create_simple() which opens or creates a file. +@param[in] key Performance Schema Key +@param[in] name name of the file or path as a null-terminated + string +@param[in] create_mode create mode +@param[in] access_type OS_FILE_READ_ONLY or OS_FILE_READ_WRITE +@param[in] read_only if true read only mode checks are enforced +@param[out] success true if succeeded +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return own: handle to the file, not defined if error, error number +can be retrieved with os_file_get_last_error */ +UNIV_INLINE +pfs_os_file_t +pfs_os_file_create_simple_func( + mysql_pfs_key_t key, + const char* name, + ulint create_mode, + ulint access_type, + bool read_only, + bool* success, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + /* register a file open or creation depending on "create_mode" */ + register_pfs_file_open_begin( + &state, locker, key, + (create_mode == OS_FILE_CREATE) + ? PSI_FILE_CREATE : PSI_FILE_OPEN, + name, src_file, src_line); + + pfs_os_file_t file = os_file_create_simple_func( + name, create_mode, access_type, read_only, success); + + /* Register psi value for the file */ + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); + + return(file); +} + +/** NOTE! Please use the corresponding macro +os_file_create_simple_no_error_handling(), not directly this function! +A performance schema instrumented wrapper function for +os_file_create_simple_no_error_handling(). Add instrumentation to +monitor file creation/open. +@param[in] key Performance Schema Key +@param[in] name name of the file or path as a null-terminated + string +@param[in] create_mode create mode +@param[in] access_type OS_FILE_READ_ONLY, OS_FILE_READ_WRITE, or + OS_FILE_READ_ALLOW_DELETE; the last option is + used by a backup program reading the file +@param[in] read_only if true read only mode checks are enforced +@param[out] success true if succeeded +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return own: handle to the file, not defined if error, error number +can be retrieved with os_file_get_last_error */ +UNIV_INLINE +pfs_os_file_t +pfs_os_file_create_simple_no_error_handling_func( + mysql_pfs_key_t key, + const char* name, + ulint create_mode, + ulint access_type, + bool read_only, + bool* success, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + /* register a file open or creation depending on "create_mode" */ + register_pfs_file_open_begin( + &state, locker, key, + create_mode == OS_FILE_CREATE + ? PSI_FILE_CREATE : PSI_FILE_OPEN, + name, src_file, src_line); + + pfs_os_file_t file = os_file_create_simple_no_error_handling_func( + name, create_mode, access_type, read_only, success); + + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); + + return(file); +} + +/** NOTE! Please use the corresponding macro os_file_create(), not directly +this function! +A performance schema wrapper function for os_file_create(). +Add instrumentation to monitor file creation/open. +@param[in] key Performance Schema Key +@param[in] name name of the file or path as a null-terminated + string +@param[in] create_mode create mode +@param[in] purpose OS_FILE_AIO, if asynchronous, non-buffered I/O + is desired, OS_FILE_NORMAL, if any normal file; + NOTE that it also depends on type, os_aio_.. + and srv_.. variables whether we really us + async I/O or unbuffered I/O: look in the + function source code for the exact rules +@param[in] read_only if true read only mode checks are enforced +@param[out] success true if succeeded +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return own: handle to the file, not defined if error, error number +can be retrieved with os_file_get_last_error */ +UNIV_INLINE +pfs_os_file_t +pfs_os_file_create_func( + mysql_pfs_key_t key, + const char* name, + ulint create_mode, + ulint purpose, + ulint type, + bool read_only, + bool* success, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + /* register a file open or creation depending on "create_mode" */ + register_pfs_file_open_begin( + &state, locker, key, + create_mode == OS_FILE_CREATE + ? PSI_FILE_CREATE : PSI_FILE_OPEN, + name, src_file, src_line); + + pfs_os_file_t file = os_file_create_func( + name, create_mode, purpose, type, read_only, success); + + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); + + return(file); +} +/** +NOTE! Please use the corresponding macro os_file_close(), not directly +this function! +A performance schema instrumented wrapper function for os_file_close(). +@param[in] file handle to a file +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return true if success */ +UNIV_INLINE +bool +pfs_os_file_close_func( + pfs_os_file_t file, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + /* register the file close */ + register_pfs_file_io_begin( + &state, locker, file, 0, PSI_FILE_CLOSE, src_file, src_line); + + bool result = os_file_close_func(file); + + register_pfs_file_io_end(locker, 0); + + return(result); +} + +/** NOTE! Please use the corresponding macro os_aio(), not directly this +function! +Performance schema wrapper function of os_aio() which requests +an asynchronous i/o operation. +@param[in,type] type IO request context +@param[in] mode IO mode +@param[in] name Name of the file or path as NUL terminated + string +@param[in] file Open file handle +@param[out] buf buffer where to read +@param[in] offset file offset where to read +@param[in] n number of bytes to read +@param[in] read_only if true read only mode checks are enforced +@param[in,out] m1 Message for the AIO handler, (can be used to + identify a completed AIO operation); ignored + if mode is OS_AIO_SYNC +@param[in,out] m2 message for the AIO handler (can be used to + identify a completed AIO operation); ignored + if mode is OS_AIO_SYNC +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return DB_SUCCESS if request was queued successfully, FALSE if fail */ +UNIV_INLINE +dberr_t +pfs_os_aio_func( + IORequest& type, + ulint mode, + const char* name, + pfs_os_file_t file, + void* buf, + os_offset_t offset, + ulint n, + bool read_only, + fil_node_t* m1, + void* m2, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + ut_ad(type.validate()); + + /* Register the read or write I/O depending on "type" */ + register_pfs_file_io_begin( + &state, locker, file, n, + type.is_write() ? PSI_FILE_WRITE : PSI_FILE_READ, + src_file, src_line); + + dberr_t result = os_aio_func( + type, mode, name, file, buf, offset, n, read_only, m1, m2); + + register_pfs_file_io_end(locker, n); + + return(result); +} + +/** NOTE! Please use the corresponding macro os_file_read(), not directly +this function! +This is the performance schema instrumented wrapper function for +os_file_read() which requests a synchronous read operation. +@param[in] type IO request context +@param[in] file Open file handle +@param[out] buf buffer where to read +@param[in] offset file offset where to read +@param[in] n number of bytes to read +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return DB_SUCCESS if request was successful */ +UNIV_INLINE +dberr_t +pfs_os_file_read_func( + const IORequest& type, + pfs_os_file_t file, + void* buf, + os_offset_t offset, + ulint n, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + ut_ad(type.validate()); + + register_pfs_file_io_begin( + &state, locker, file, n, PSI_FILE_READ, src_file, src_line); + + dberr_t result; + + result = os_file_read_func(type, file, buf, offset, n); + + register_pfs_file_io_end(locker, n); + + return(result); +} + +/** NOTE! Please use the corresponding macro os_file_read_no_error_handling(), +not directly this function! +This is the performance schema instrumented wrapper function for +os_file_read_no_error_handling_func() which requests a synchronous +read operation. +@param[in] type IO request context +@param[in] file Open file handle +@param[out] buf buffer where to read +@param[in] offset file offset where to read +@param[in] n number of bytes to read +@param[out] o number of bytes actually read +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return DB_SUCCESS if request was successful */ +UNIV_INLINE +dberr_t +pfs_os_file_read_no_error_handling_func( + const IORequest& type, + pfs_os_file_t file, + void* buf, + os_offset_t offset, + ulint n, + ulint* o, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + register_pfs_file_io_begin( + &state, locker, file, n, PSI_FILE_READ, src_file, src_line); + + dberr_t result = os_file_read_no_error_handling_func( + type, file, buf, offset, n, o); + + register_pfs_file_io_end(locker, n); + + return(result); +} + +/** NOTE! Please use the corresponding macro +os_file_read_no_error_handling_int_fd() to request +a synchronous read operation. +@param[in] type read request +@param[in] file file handle +@param[out] buf buffer where to read +@param[in] offset file offset where to read +@param[in] n number of bytes to read +@param[in] src_file caller file name +@param[in] src_line caller line number +@return error code +@retval DB_SUCCESS if the operation succeeded */ +UNIV_INLINE +dberr_t +pfs_os_file_read_no_error_handling_int_fd_func( + const IORequest& type, + int file, + void* buf, + os_offset_t offset, + ulint n, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + + PSI_file_locker* locker = PSI_FILE_CALL( + get_thread_file_descriptor_locker)( + &state, file, PSI_FILE_READ); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, n, + __FILE__, __LINE__); + } + + dberr_t err = os_file_read_no_error_handling_func( + type, OS_FILE_FROM_FD(file), buf, offset, n, NULL); + + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, n); + } + + return err; +} + +/** NOTE! Please use the corresponding macro os_file_write(), not directly +this function! +This is the performance schema instrumented wrapper function for +os_file_write() which requests a synchronous write operation. +@param[in] type IO request context +@param[in] name Name of the file or path as NUL terminated + string +@param[in] file Open file handle +@param[out] buf buffer where to read +@param[in] offset file offset where to read +@param[in] n number of bytes to read +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return error code +@retval DB_SUCCESS if the request was successfully fulfilled */ +UNIV_INLINE +dberr_t +pfs_os_file_write_func( + const IORequest& type, + const char* name, + pfs_os_file_t file, + const void* buf, + os_offset_t offset, + ulint n, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + register_pfs_file_io_begin( + &state, locker, file, n, PSI_FILE_WRITE, src_file, src_line); + + dberr_t result; + + result = os_file_write_func(type, name, file, buf, offset, n); + + register_pfs_file_io_end(locker, n); + + return(result); +} + +/** NOTE! Please use the corresponding macro os_file_write_int_fd(), +not directly this function! +This is the performance schema instrumented wrapper function for +os_file_write_int_fd() which requests a synchronous write operation. +@param[in] type write request +@param[in] name file name +@param[in] file file handle +@param[in] buf buffer to write +@param[in] offset file offset +@param[in] n number of bytes +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return error code +@retval DB_SUCCESS if the operation succeeded */ +UNIV_INLINE +dberr_t +pfs_os_file_write_int_fd_func( + const IORequest& type, + const char* name, + int file, + const void* buf, + os_offset_t offset, + ulint n, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker; + + locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &state, file, PSI_FILE_WRITE); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, n, + __FILE__, __LINE__); + } + + dberr_t err = os_file_write_func( + type, name, OS_FILE_FROM_FD(file), buf, offset, n); + + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, n); + } + + return err; +} + +/** NOTE! Please use the corresponding macro os_file_flush(), not directly +this function! +This is the performance schema instrumented wrapper function for +os_file_flush() which flushes the write buffers of a given file to the disk. +Flushes the write buffers of a given file to the disk. +@param[in] file Open file handle +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return TRUE if success */ +UNIV_INLINE +bool +pfs_os_file_flush_func( + pfs_os_file_t file, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + register_pfs_file_io_begin( + &state, locker, file, 0, PSI_FILE_SYNC, src_file, src_line); + + bool result = os_file_flush_func(file); + + register_pfs_file_io_end(locker, 0); + + return(result); +} + +/** NOTE! Please use the corresponding macro os_file_rename(), not directly +this function! +This is the performance schema instrumented wrapper function for +os_file_rename() +@param[in] key Performance Schema Key +@param[in] oldpath old file path as a null-terminated string +@param[in] newpath new file path +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return true if success */ +UNIV_INLINE +bool +pfs_os_file_rename_func( + mysql_pfs_key_t key, + const char* oldpath, + const char* newpath, + const char* src_file, + uint src_line) + +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + register_pfs_file_open_begin( + &state, locker, key, PSI_FILE_RENAME, newpath, + src_file, src_line); + + bool result = os_file_rename_func(oldpath, newpath); + + register_pfs_file_rename_end(locker, 0); + + return(result); +} + +/** NOTE! Please use the corresponding macro os_file_delete(), not directly +this function! +This is the performance schema instrumented wrapper function for +os_file_delete() +@param[in] key Performance Schema Key +@param[in] name old file path as a null-terminated string +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return true if success */ +UNIV_INLINE +bool +pfs_os_file_delete_func( + mysql_pfs_key_t key, + const char* name, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + register_pfs_file_close_begin( + &state, locker, key, PSI_FILE_DELETE, name, src_file, src_line); + + bool result = os_file_delete_func(name); + + register_pfs_file_close_end(locker, 0); + + return(result); +} + +/** +NOTE! Please use the corresponding macro os_file_delete_if_exists(), not +directly this function! +This is the performance schema instrumented wrapper function for +os_file_delete_if_exists() +@param[in] key Performance Schema Key +@param[in] name old file path as a null-terminated string +@param[in] exist indicate if file pre-exist +@param[in] src_file file name where func invoked +@param[in] src_line line where the func invoked +@return true if success */ +UNIV_INLINE +bool +pfs_os_file_delete_if_exists_func( + mysql_pfs_key_t key, + const char* name, + bool* exist, + const char* src_file, + uint src_line) +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + register_pfs_file_close_begin( + &state, locker, key, PSI_FILE_DELETE, name, src_file, src_line); + + bool result = os_file_delete_if_exists_func(name, exist); + + register_pfs_file_close_end(locker, 0); + + return(result); +} +#endif /* UNIV_PFS_IO */ diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h index 817902b6404..c77e759c004 100644 --- a/storage/innobase/include/page0cur.h +++ b/storage/innobase/include/page0cur.h @@ -400,6 +400,6 @@ struct page_cur_t{ buf_block_t* block; /*!< pointer to the block containing rec */ }; -#include "page0cur.ic" +#include "page0cur.inl" #endif diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic deleted file mode 100644 index e57d3f9dee1..00000000000 --- a/storage/innobase/include/page0cur.ic +++ /dev/null @@ -1,328 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 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/page0cur.ic -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 */ -UNIV_INLINE -page_t* -page_cur_get_page( -/*==============*/ - page_cur_t* cur) /*!< in: page cursor */ -{ - ut_ad(cur); - - if (cur->rec) { - ut_ad(page_align(cur->rec) == cur->block->frame); - } - - return(page_align(cur->rec)); -} - -/*********************************************************//** -Gets pointer to the buffer block where the cursor is positioned. -@return page */ -UNIV_INLINE -buf_block_t* -page_cur_get_block( -/*===============*/ - page_cur_t* cur) /*!< in: page cursor */ -{ - ut_ad(cur); - - if (cur->rec) { - ut_ad(page_align(cur->rec) == cur->block->frame); - } - - return(cur->block); -} - -/*********************************************************//** -Gets pointer to the page frame where the cursor is positioned. -@return page */ -UNIV_INLINE -page_zip_des_t* -page_cur_get_page_zip( -/*==================*/ - page_cur_t* cur) /*!< in: page cursor */ -{ - return(buf_block_get_page_zip(page_cur_get_block(cur))); -} - -/*********************************************************//** -Gets the record where the cursor is positioned. -@return record */ -UNIV_INLINE -rec_t* -page_cur_get_rec( -/*=============*/ - page_cur_t* cur) /*!< in: page cursor */ -{ - ut_ad(cur); - - if (cur->rec) { - ut_ad(page_align(cur->rec) == cur->block->frame); - } - - return(cur->rec); -} -#endif /* UNIV_DEBUG */ - -/*********************************************************//** -Sets the cursor object to point before the first user record -on the page. */ -UNIV_INLINE -void -page_cur_set_before_first( -/*======================*/ - const buf_block_t* block, /*!< in: index page */ - page_cur_t* cur) /*!< in: cursor */ -{ - cur->block = (buf_block_t*) block; - cur->rec = page_get_infimum_rec(buf_block_get_frame(cur->block)); -} - -/*********************************************************//** -Sets the cursor object to point after the last user record on -the page. */ -UNIV_INLINE -void -page_cur_set_after_last( -/*====================*/ - const buf_block_t* block, /*!< in: index page */ - page_cur_t* cur) /*!< in: cursor */ -{ - cur->block = (buf_block_t*) block; - cur->rec = page_get_supremum_rec(buf_block_get_frame(cur->block)); -} - -/*********************************************************//** -Returns TRUE if the cursor is before first user record on page. -@return TRUE if at start */ -UNIV_INLINE -ibool -page_cur_is_before_first( -/*=====================*/ - const page_cur_t* cur) /*!< in: cursor */ -{ - ut_ad(cur); - ut_ad(page_align(cur->rec) == cur->block->frame); - return(page_rec_is_infimum(cur->rec)); -} - -/*********************************************************//** -Returns TRUE if the cursor is after last user record. -@return TRUE if at end */ -UNIV_INLINE -ibool -page_cur_is_after_last( -/*===================*/ - const page_cur_t* cur) /*!< in: cursor */ -{ - ut_ad(cur); - ut_ad(page_align(cur->rec) == cur->block->frame); - return(page_rec_is_supremum(cur->rec)); -} - -/**********************************************************//** -Positions the cursor on the given record. */ -UNIV_INLINE -void -page_cur_position( -/*==============*/ - const rec_t* rec, /*!< in: record on a page */ - const buf_block_t* block, /*!< in: buffer block containing - the record */ - page_cur_t* cur) /*!< out: page cursor */ -{ - ut_ad(rec && block && cur); - ut_ad(page_align(rec) == block->frame); - - cur->rec = (rec_t*) rec; - cur->block = (buf_block_t*) block; -} - -/**********************************************************//** -Moves the cursor to the next record on page. */ -UNIV_INLINE -void -page_cur_move_to_next( -/*==================*/ - page_cur_t* cur) /*!< in/out: cursor; must not be after last */ -{ - ut_ad(!page_cur_is_after_last(cur)); - - cur->rec = page_rec_get_next(cur->rec); -} - -/**********************************************************//** -Moves the cursor to the previous record on page. */ -UNIV_INLINE -void -page_cur_move_to_prev( -/*==================*/ - page_cur_t* cur) /*!< in/out: page cursor, not before first */ -{ - ut_ad(!page_cur_is_before_first(cur)); - - cur->rec = page_rec_get_prev(cur->rec); -} - -/** Search the right position for a page cursor. -@param[in] block buffer block -@param[in] index index tree -@param[in] tuple data tuple -@param[in] mode PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE -@param[out] cursor page cursor -@return number of matched fields on the left */ -UNIV_INLINE -ulint -page_cur_search( - const buf_block_t* block, - const dict_index_t* index, - const dtuple_t* tuple, - page_cur_mode_t mode, - page_cur_t* cursor) -{ - ulint low_match = 0; - ulint up_match = 0; - - ut_ad(dtuple_check_typed(tuple)); - - page_cur_search_with_match(block, index, tuple, mode, - &up_match, &low_match, cursor, NULL); - return(low_match); -} - -/** Search the right position for a page cursor. -@param[in] block buffer block -@param[in] index index tree -@param[in] tuple data tuple -@param[out] cursor page cursor -@return number of matched fields on the left */ -UNIV_INLINE -ulint -page_cur_search( - const buf_block_t* block, - const dict_index_t* index, - const dtuple_t* tuple, - page_cur_t* cursor) -{ - return(page_cur_search(block, index, tuple, PAGE_CUR_LE, cursor)); -} - -/***********************************************************//** -Inserts a record next to page cursor. Returns pointer to inserted record if -succeed, i.e., enough space available, NULL otherwise. The cursor stays at -the same logical position, but the physical position may change if it is -pointing to a compressed page that was reorganized. - -IMPORTANT: The caller will have to update IBUF_BITMAP_FREE -if this is a compressed leaf page in a secondary index. -This has to be done either within the same mini-transaction, -or by invoking ibuf_reset_free_bits() before mtr_commit(). - -@return pointer to record if succeed, NULL otherwise */ -UNIV_INLINE -rec_t* -page_cur_tuple_insert( -/*==================*/ - page_cur_t* cursor, /*!< in/out: a page cursor */ - const dtuple_t* tuple, /*!< in: pointer to a data tuple */ - dict_index_t* index, /*!< in: record descriptor */ - rec_offs** offsets,/*!< out: offsets on *rec */ - mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ - ulint n_ext, /*!< in: number of externally stored columns */ - mtr_t* mtr, /*!< in: mini-transaction handle, or NULL */ - bool use_cache) - /*!< in: if true, then use record cache to - hold the tuple converted record. */ -{ - rec_t* rec; - ulint size = rec_get_converted_size(index, tuple, n_ext); - - if (!*heap) { - *heap = mem_heap_create(size - + (4 + REC_OFFS_HEADER_SIZE - + dtuple_get_n_fields(tuple)) - * sizeof **offsets); - } - - rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size), - index, tuple, n_ext); - - *offsets = rec_get_offsets(rec, index, *offsets, - page_is_leaf(cursor->block->frame), - ULINT_UNDEFINED, heap); - - if (buf_block_get_page_zip(cursor->block)) { - rec = page_cur_insert_rec_zip( - cursor, index, rec, *offsets, mtr); - } else { - rec = page_cur_insert_rec_low(cursor->rec, - index, rec, *offsets, mtr); - } - - ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, *offsets)); - return(rec); -} - -/***********************************************************//** -Inserts a record next to page cursor. Returns pointer to inserted record if -succeed, i.e., enough space available, NULL otherwise. The cursor stays at -the same logical position, but the physical position may change if it is -pointing to a compressed page that was reorganized. - -IMPORTANT: The caller will have to update IBUF_BITMAP_FREE -if this is a compressed leaf page in a secondary index. -This has to be done either within the same mini-transaction, -or by invoking ibuf_reset_free_bits() before mtr_commit(). - -@return pointer to record if succeed, NULL otherwise */ -UNIV_INLINE -rec_t* -page_cur_rec_insert( -/*================*/ - page_cur_t* cursor, /*!< in/out: a page cursor */ - const rec_t* rec, /*!< in: record to insert */ - dict_index_t* index, /*!< in: record descriptor */ - rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ - mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ -{ - if (buf_block_get_page_zip(cursor->block)) { - return(page_cur_insert_rec_zip( - cursor, index, rec, offsets, mtr)); - } else { - return(page_cur_insert_rec_low(cursor->rec, - index, rec, offsets, mtr)); - } -} diff --git a/storage/innobase/include/page0cur.inl b/storage/innobase/include/page0cur.inl new file mode 100644 index 00000000000..e57d3f9dee1 --- /dev/null +++ b/storage/innobase/include/page0cur.inl @@ -0,0 +1,328 @@ +/***************************************************************************** + +Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 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/page0cur.ic +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 */ +UNIV_INLINE +page_t* +page_cur_get_page( +/*==============*/ + page_cur_t* cur) /*!< in: page cursor */ +{ + ut_ad(cur); + + if (cur->rec) { + ut_ad(page_align(cur->rec) == cur->block->frame); + } + + return(page_align(cur->rec)); +} + +/*********************************************************//** +Gets pointer to the buffer block where the cursor is positioned. +@return page */ +UNIV_INLINE +buf_block_t* +page_cur_get_block( +/*===============*/ + page_cur_t* cur) /*!< in: page cursor */ +{ + ut_ad(cur); + + if (cur->rec) { + ut_ad(page_align(cur->rec) == cur->block->frame); + } + + return(cur->block); +} + +/*********************************************************//** +Gets pointer to the page frame where the cursor is positioned. +@return page */ +UNIV_INLINE +page_zip_des_t* +page_cur_get_page_zip( +/*==================*/ + page_cur_t* cur) /*!< in: page cursor */ +{ + return(buf_block_get_page_zip(page_cur_get_block(cur))); +} + +/*********************************************************//** +Gets the record where the cursor is positioned. +@return record */ +UNIV_INLINE +rec_t* +page_cur_get_rec( +/*=============*/ + page_cur_t* cur) /*!< in: page cursor */ +{ + ut_ad(cur); + + if (cur->rec) { + ut_ad(page_align(cur->rec) == cur->block->frame); + } + + return(cur->rec); +} +#endif /* UNIV_DEBUG */ + +/*********************************************************//** +Sets the cursor object to point before the first user record +on the page. */ +UNIV_INLINE +void +page_cur_set_before_first( +/*======================*/ + const buf_block_t* block, /*!< in: index page */ + page_cur_t* cur) /*!< in: cursor */ +{ + cur->block = (buf_block_t*) block; + cur->rec = page_get_infimum_rec(buf_block_get_frame(cur->block)); +} + +/*********************************************************//** +Sets the cursor object to point after the last user record on +the page. */ +UNIV_INLINE +void +page_cur_set_after_last( +/*====================*/ + const buf_block_t* block, /*!< in: index page */ + page_cur_t* cur) /*!< in: cursor */ +{ + cur->block = (buf_block_t*) block; + cur->rec = page_get_supremum_rec(buf_block_get_frame(cur->block)); +} + +/*********************************************************//** +Returns TRUE if the cursor is before first user record on page. +@return TRUE if at start */ +UNIV_INLINE +ibool +page_cur_is_before_first( +/*=====================*/ + const page_cur_t* cur) /*!< in: cursor */ +{ + ut_ad(cur); + ut_ad(page_align(cur->rec) == cur->block->frame); + return(page_rec_is_infimum(cur->rec)); +} + +/*********************************************************//** +Returns TRUE if the cursor is after last user record. +@return TRUE if at end */ +UNIV_INLINE +ibool +page_cur_is_after_last( +/*===================*/ + const page_cur_t* cur) /*!< in: cursor */ +{ + ut_ad(cur); + ut_ad(page_align(cur->rec) == cur->block->frame); + return(page_rec_is_supremum(cur->rec)); +} + +/**********************************************************//** +Positions the cursor on the given record. */ +UNIV_INLINE +void +page_cur_position( +/*==============*/ + const rec_t* rec, /*!< in: record on a page */ + const buf_block_t* block, /*!< in: buffer block containing + the record */ + page_cur_t* cur) /*!< out: page cursor */ +{ + ut_ad(rec && block && cur); + ut_ad(page_align(rec) == block->frame); + + cur->rec = (rec_t*) rec; + cur->block = (buf_block_t*) block; +} + +/**********************************************************//** +Moves the cursor to the next record on page. */ +UNIV_INLINE +void +page_cur_move_to_next( +/*==================*/ + page_cur_t* cur) /*!< in/out: cursor; must not be after last */ +{ + ut_ad(!page_cur_is_after_last(cur)); + + cur->rec = page_rec_get_next(cur->rec); +} + +/**********************************************************//** +Moves the cursor to the previous record on page. */ +UNIV_INLINE +void +page_cur_move_to_prev( +/*==================*/ + page_cur_t* cur) /*!< in/out: page cursor, not before first */ +{ + ut_ad(!page_cur_is_before_first(cur)); + + cur->rec = page_rec_get_prev(cur->rec); +} + +/** Search the right position for a page cursor. +@param[in] block buffer block +@param[in] index index tree +@param[in] tuple data tuple +@param[in] mode PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE +@param[out] cursor page cursor +@return number of matched fields on the left */ +UNIV_INLINE +ulint +page_cur_search( + const buf_block_t* block, + const dict_index_t* index, + const dtuple_t* tuple, + page_cur_mode_t mode, + page_cur_t* cursor) +{ + ulint low_match = 0; + ulint up_match = 0; + + ut_ad(dtuple_check_typed(tuple)); + + page_cur_search_with_match(block, index, tuple, mode, + &up_match, &low_match, cursor, NULL); + return(low_match); +} + +/** Search the right position for a page cursor. +@param[in] block buffer block +@param[in] index index tree +@param[in] tuple data tuple +@param[out] cursor page cursor +@return number of matched fields on the left */ +UNIV_INLINE +ulint +page_cur_search( + const buf_block_t* block, + const dict_index_t* index, + const dtuple_t* tuple, + page_cur_t* cursor) +{ + return(page_cur_search(block, index, tuple, PAGE_CUR_LE, cursor)); +} + +/***********************************************************//** +Inserts a record next to page cursor. Returns pointer to inserted record if +succeed, i.e., enough space available, NULL otherwise. The cursor stays at +the same logical position, but the physical position may change if it is +pointing to a compressed page that was reorganized. + +IMPORTANT: The caller will have to update IBUF_BITMAP_FREE +if this is a compressed leaf page in a secondary index. +This has to be done either within the same mini-transaction, +or by invoking ibuf_reset_free_bits() before mtr_commit(). + +@return pointer to record if succeed, NULL otherwise */ +UNIV_INLINE +rec_t* +page_cur_tuple_insert( +/*==================*/ + page_cur_t* cursor, /*!< in/out: a page cursor */ + const dtuple_t* tuple, /*!< in: pointer to a data tuple */ + dict_index_t* index, /*!< in: record descriptor */ + rec_offs** offsets,/*!< out: offsets on *rec */ + mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ + ulint n_ext, /*!< in: number of externally stored columns */ + mtr_t* mtr, /*!< in: mini-transaction handle, or NULL */ + bool use_cache) + /*!< in: if true, then use record cache to + hold the tuple converted record. */ +{ + rec_t* rec; + ulint size = rec_get_converted_size(index, tuple, n_ext); + + if (!*heap) { + *heap = mem_heap_create(size + + (4 + REC_OFFS_HEADER_SIZE + + dtuple_get_n_fields(tuple)) + * sizeof **offsets); + } + + rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size), + index, tuple, n_ext); + + *offsets = rec_get_offsets(rec, index, *offsets, + page_is_leaf(cursor->block->frame), + ULINT_UNDEFINED, heap); + + if (buf_block_get_page_zip(cursor->block)) { + rec = page_cur_insert_rec_zip( + cursor, index, rec, *offsets, mtr); + } else { + rec = page_cur_insert_rec_low(cursor->rec, + index, rec, *offsets, mtr); + } + + ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, *offsets)); + return(rec); +} + +/***********************************************************//** +Inserts a record next to page cursor. Returns pointer to inserted record if +succeed, i.e., enough space available, NULL otherwise. The cursor stays at +the same logical position, but the physical position may change if it is +pointing to a compressed page that was reorganized. + +IMPORTANT: The caller will have to update IBUF_BITMAP_FREE +if this is a compressed leaf page in a secondary index. +This has to be done either within the same mini-transaction, +or by invoking ibuf_reset_free_bits() before mtr_commit(). + +@return pointer to record if succeed, NULL otherwise */ +UNIV_INLINE +rec_t* +page_cur_rec_insert( +/*================*/ + page_cur_t* cursor, /*!< in/out: a page cursor */ + const rec_t* rec, /*!< in: record to insert */ + dict_index_t* index, /*!< in: record descriptor */ + rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ + mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ +{ + if (buf_block_get_page_zip(cursor->block)) { + return(page_cur_insert_rec_zip( + cursor, index, rec, offsets, mtr)); + } else { + return(page_cur_insert_rec_low(cursor->rec, + index, rec, offsets, mtr)); + } +} diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index a569912b82b..3799f2024bd 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -1251,7 +1251,7 @@ page_find_rec_max_not_deleted( #endif /* !UNIV_INNOCHECKSUM */ -#include "page0page.ic" +#include "page0page.inl" #endif diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic deleted file mode 100644 index 5f69925a41a..00000000000 --- a/storage/innobase/include/page0page.ic +++ /dev/null @@ -1,1062 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. -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 -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/page0page.ic -Index page routines - -Created 2/2/1994 Heikki Tuuri -*******************************************************/ - -#ifndef page0page_ic -#define page0page_ic - -#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 -trx_id_t -page_get_max_trx_id( -/*================*/ - const page_t* page) /*!< in: page */ -{ - ut_ad(page); - - return(mach_read_from_8(page + PAGE_HEADER + PAGE_MAX_TRX_ID)); -} - -/*************************************************************//** -Sets the max trx id field value if trx_id is bigger than the previous -value. */ -UNIV_INLINE -void -page_update_max_trx_id( -/*===================*/ - buf_block_t* block, /*!< in/out: page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL */ - trx_id_t trx_id, /*!< in: transaction id */ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - ut_ad(block); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); - /* During crash recovery, this function may be called on - something else than a leaf page of a secondary index or the - insert buffer index tree (dict_index_is_sec_or_ibuf() returns - TRUE for the dummy indexes constructed during redo log - application). In that case, PAGE_MAX_TRX_ID is unused, - and trx_id is usually zero. */ - ut_ad(trx_id || recv_recovery_is_on()); - ut_ad(page_is_leaf(buf_block_get_frame(block))); - - if (page_get_max_trx_id(buf_block_get_frame(block)) < trx_id) { - - page_set_max_trx_id(block, page_zip, trx_id, mtr); - } -} - -/** Read the AUTO_INCREMENT value from a clustered index root page. -@param[in] page clustered index root page -@return the persisted AUTO_INCREMENT value */ -UNIV_INLINE -ib_uint64_t -page_get_autoinc(const page_t* page) -{ - ut_ad(fil_page_index_page_check(page)); - ut_ad(!page_has_siblings(page)); - return(mach_read_from_8(PAGE_HEADER + PAGE_ROOT_AUTO_INC + page)); -} - -/*************************************************************//** -Returns the RTREE SPLIT SEQUENCE NUMBER (FIL_RTREE_SPLIT_SEQ_NUM). -@return SPLIT SEQUENCE NUMBER */ -UNIV_INLINE -node_seq_t -page_get_ssn_id( -/*============*/ - const page_t* page) /*!< in: page */ -{ - ut_ad(page); - - return(static_cast( - mach_read_from_8(page + FIL_RTREE_SPLIT_SEQ_NUM))); -} - -/*************************************************************//** -Sets the RTREE SPLIT SEQUENCE NUMBER field value */ -UNIV_INLINE -void -page_set_ssn_id( -/*============*/ - buf_block_t* block, /*!< in/out: page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL */ - node_seq_t ssn_id, /*!< in: transaction id */ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - page_t* page = buf_block_get_frame(block); - - ut_ad(!mtr || mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_SX_FIX - | MTR_MEMO_PAGE_X_FIX)); - - if (page_zip) { - mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id); - page_zip_write_header(page_zip, - page + FIL_RTREE_SPLIT_SEQ_NUM, - 8, mtr); - } else if (mtr) { - mlog_write_ull(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id, mtr); - } else { - mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id); - } -} - -#endif /* !UNIV_INNOCHECKSUM */ - -/*************************************************************//** -Reads the given header field. */ -UNIV_INLINE -uint16_t -page_header_get_field( -/*==================*/ - const page_t* page, /*!< in: page */ - ulint field) /*!< in: PAGE_LEVEL, ... */ -{ - ut_ad(page); - ut_ad(field <= PAGE_INDEX_ID); - - return(mach_read_from_2(page + PAGE_HEADER + field)); -} - -#ifndef UNIV_INNOCHECKSUM -/*************************************************************//** -Sets the given header field. */ -UNIV_INLINE -void -page_header_set_field( -/*==================*/ - page_t* page, /*!< in/out: page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL */ - ulint field, /*!< in: PAGE_N_DIR_SLOTS, ... */ - ulint val) /*!< in: value */ -{ - ut_ad(page); - ut_ad(field <= PAGE_N_RECS); - ut_ad(field == PAGE_N_HEAP || val < srv_page_size); - ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < srv_page_size); - - mach_write_to_2(page + PAGE_HEADER + field, val); - if (page_zip) { - page_zip_write_header(page_zip, - page + PAGE_HEADER + field, 2, NULL); - } -} - -/*************************************************************//** -Returns the offset stored in the given header field. -@return offset from the start of the page, or 0 */ -UNIV_INLINE -uint16_t -page_header_get_offs( -/*=================*/ - const page_t* page, /*!< in: page */ - ulint field) /*!< in: PAGE_FREE, ... */ -{ - ut_ad((field == PAGE_FREE) - || (field == PAGE_LAST_INSERT) - || (field == PAGE_HEAP_TOP)); - - uint16_t offs = page_header_get_field(page, field); - - ut_ad((field != PAGE_HEAP_TOP) || offs); - - return(offs); -} - -/*************************************************************//** -Sets the pointer stored in the given header field. */ -UNIV_INLINE -void -page_header_set_ptr( -/*================*/ - page_t* page, /*!< in: page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL */ - ulint field, /*!< in: PAGE_FREE, ... */ - const byte* ptr) /*!< in: pointer or NULL*/ -{ - ulint offs; - - ut_ad(page); - ut_ad((field == PAGE_FREE) - || (field == PAGE_LAST_INSERT) - || (field == PAGE_HEAP_TOP)); - - if (ptr == NULL) { - offs = 0; - } else { - offs = ulint(ptr - page); - } - - ut_ad((field != PAGE_HEAP_TOP) || offs); - - page_header_set_field(page, page_zip, field, offs); -} - -/*************************************************************//** -Resets the last insert info field in the page header. Writes to mlog -about this operation. */ -UNIV_INLINE -void -page_header_reset_last_insert( -/*==========================*/ - page_t* page, /*!< in/out: page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(page != NULL); - ut_ad(mtr != NULL); - - if (page_zip) { - mach_write_to_2(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0); - page_zip_write_header(page_zip, - page + (PAGE_HEADER + PAGE_LAST_INSERT), - 2, mtr); - } else { - mlog_write_ulint(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0, - MLOG_2BYTES, mtr); - } -} - -/***************************************************************//** -Returns the heap number of a record. -@return heap number */ -UNIV_INLINE -ulint -page_rec_get_heap_no( -/*=================*/ - const rec_t* rec) /*!< in: the physical record */ -{ - if (page_rec_is_comp(rec)) { - return(rec_get_heap_no_new(rec)); - } else { - return(rec_get_heap_no_old(rec)); - } -} - -/** Determine whether an index page record is a user record. -@param[in] rec record in an index page -@return true if a user record */ -inline -bool -page_rec_is_user_rec(const rec_t* rec) -{ - ut_ad(page_rec_check(rec)); - return(page_rec_is_user_rec_low(page_offset(rec))); -} - -/** Determine whether an index page record is the supremum record. -@param[in] rec record in an index page -@return true if the supremum record */ -inline -bool -page_rec_is_supremum(const rec_t* rec) -{ - ut_ad(page_rec_check(rec)); - return(page_rec_is_supremum_low(page_offset(rec))); -} - -/** Determine whether an index page record is the infimum record. -@param[in] rec record in an index page -@return true if the infimum record */ -inline -bool -page_rec_is_infimum(const rec_t* rec) -{ - ut_ad(page_rec_check(rec)); - return(page_rec_is_infimum_low(page_offset(rec))); -} - -/************************************************************//** -true if the record is the first user record on a page. -@return true if the first user record */ -UNIV_INLINE -bool -page_rec_is_first( -/*==============*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ -{ - ut_ad(page_get_n_recs(page) > 0); - - return(page_rec_get_next_const(page_get_infimum_rec(page)) == rec); -} - -/************************************************************//** -true if the record is the second user record on a page. -@return true if the second user record */ -UNIV_INLINE -bool -page_rec_is_second( -/*===============*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ -{ - ut_ad(page_get_n_recs(page) > 1); - - return(page_rec_get_next_const( - page_rec_get_next_const(page_get_infimum_rec(page))) == rec); -} - -/************************************************************//** -true if the record is the last user record on a page. -@return true if the last user record */ -UNIV_INLINE -bool -page_rec_is_last( -/*=============*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ -{ - ut_ad(page_get_n_recs(page) > 0); - - return(page_rec_get_next_const(rec) == page_get_supremum_rec(page)); -} - -/************************************************************//** -true if distance between the records (measured in number of times we have to -move to the next record) is at most the specified value */ -UNIV_INLINE -bool -page_rec_distance_is_at_most( -/*=========================*/ - const rec_t* left_rec, - const rec_t* right_rec, - ulint val) -{ - for (ulint i = 0; i <= val; i++) { - if (left_rec == right_rec) { - return (true); - } - left_rec = page_rec_get_next_const(left_rec); - } - return (false); -} - -/************************************************************//** -true if the record is the second last user record on a page. -@return true if the second last user record */ -UNIV_INLINE -bool -page_rec_is_second_last( -/*====================*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ -{ - ut_ad(page_get_n_recs(page) > 1); - ut_ad(!page_rec_is_last(rec, page)); - - return(page_rec_get_next_const( - page_rec_get_next_const(rec)) == page_get_supremum_rec(page)); -} - -/************************************************************//** -Returns the nth record of the record list. -This is the inverse function of page_rec_get_n_recs_before(). -@return nth record */ -UNIV_INLINE -rec_t* -page_rec_get_nth( -/*=============*/ - page_t* page, /*!< in: page */ - ulint nth) /*!< in: nth record */ -{ - return((rec_t*) page_rec_get_nth_const(page, nth)); -} - -/************************************************************//** -Returns the middle record of the records on the page. If there is an -even number of records in the list, returns the first record of the -upper half-list. -@return middle record */ -UNIV_INLINE -rec_t* -page_get_middle_rec( -/*================*/ - page_t* page) /*!< in: page */ -{ - ulint middle = (ulint(page_get_n_recs(page)) - + PAGE_HEAP_NO_USER_LOW) / 2; - - return(page_rec_get_nth(page, middle)); -} - -#endif /* !UNIV_INNOCHECKSUM */ - -/*************************************************************//** -Gets the page number. -@return page number */ -UNIV_INLINE -ulint -page_get_page_no( -/*=============*/ - const page_t* page) /*!< in: page */ -{ - ut_ad(page == page_align((page_t*) page)); - return(mach_read_from_4(page + FIL_PAGE_OFFSET)); -} - -#ifndef UNIV_INNOCHECKSUM -/*************************************************************//** -Gets the tablespace identifier. -@return space id */ -UNIV_INLINE -ulint -page_get_space_id( -/*==============*/ - const page_t* page) /*!< in: page */ -{ - ut_ad(page == page_align((page_t*) page)); - return(mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID)); -} - -#endif /* !UNIV_INNOCHECKSUM */ - -/*************************************************************//** -Gets the number of user records on page (infimum and supremum records -are not user records). -@return number of user records */ -UNIV_INLINE -uint16_t -page_get_n_recs( -/*============*/ - const page_t* page) /*!< in: index page */ -{ - return(page_header_get_field(page, PAGE_N_RECS)); -} - -#ifndef UNIV_INNOCHECKSUM -/*************************************************************//** -Gets the number of dir slots in directory. -@return number of slots */ -UNIV_INLINE -uint16_t -page_dir_get_n_slots( -/*=================*/ - const page_t* page) /*!< in: index page */ -{ - return(page_header_get_field(page, PAGE_N_DIR_SLOTS)); -} -/*************************************************************//** -Sets the number of dir slots in directory. */ -UNIV_INLINE -void -page_dir_set_n_slots( -/*=================*/ - page_t* page, /*!< in/out: page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL */ - ulint n_slots)/*!< in: number of slots */ -{ - page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots); -} - -/*************************************************************//** -Gets the number of records in the heap. -@return number of user records */ -UNIV_INLINE -uint16_t -page_dir_get_n_heap( -/*================*/ - const page_t* page) /*!< in: index page */ -{ - return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff); -} - -/*************************************************************//** -Sets the number of records in the heap. */ -UNIV_INLINE -void -page_dir_set_n_heap( -/*================*/ - page_t* page, /*!< in/out: index page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL. - Note that the size of the dense page directory - in the compressed page trailer is - n_heap * PAGE_ZIP_DIR_SLOT_SIZE. */ - ulint n_heap) /*!< in: number of records */ -{ - ut_ad(n_heap < 0x8000); - ut_ad(!page_zip || uint16_t(n_heap) - == (page_header_get_field(page, PAGE_N_HEAP) & 0x7fff) + 1); - - page_header_set_field(page, page_zip, PAGE_N_HEAP, n_heap - | (0x8000 - & page_header_get_field(page, PAGE_N_HEAP))); -} - -#ifdef UNIV_DEBUG -/*************************************************************//** -Gets pointer to nth directory slot. -@return pointer to dir slot */ -UNIV_INLINE -page_dir_slot_t* -page_dir_get_nth_slot( -/*==================*/ - const page_t* page, /*!< in: index page */ - ulint n) /*!< in: position */ -{ - ut_ad(page_dir_get_n_slots(page) > n); - - return((page_dir_slot_t*) - page + srv_page_size - PAGE_DIR - - (n + 1) * PAGE_DIR_SLOT_SIZE); -} -#endif /* UNIV_DEBUG */ - -/**************************************************************//** -Used to check the consistency of a record on a page. -@return TRUE if succeed */ -UNIV_INLINE -ibool -page_rec_check( -/*===========*/ - const rec_t* rec) /*!< in: record */ -{ - const page_t* page = page_align(rec); - - ut_a(rec); - - ut_a(page_offset(rec) <= page_header_get_field(page, PAGE_HEAP_TOP)); - ut_a(page_offset(rec) >= PAGE_DATA); - - return(TRUE); -} - -/***************************************************************//** -Gets the record pointed to by a directory slot. -@return pointer to record */ -UNIV_INLINE -const rec_t* -page_dir_slot_get_rec( -/*==================*/ - const page_dir_slot_t* slot) /*!< in: directory slot */ -{ - return(page_align(slot) + mach_read_from_2(slot)); -} - -/***************************************************************//** -This is used to set the record offset in a directory slot. */ -UNIV_INLINE -void -page_dir_slot_set_rec( -/*==================*/ - page_dir_slot_t* slot, /*!< in: directory slot */ - rec_t* rec) /*!< in: record on the page */ -{ - ut_ad(page_rec_check(rec)); - - mach_write_to_2(slot, page_offset(rec)); -} - -/***************************************************************//** -Gets the number of records owned by a directory slot. -@return number of records */ -UNIV_INLINE -ulint -page_dir_slot_get_n_owned( -/*======================*/ - const page_dir_slot_t* slot) /*!< in: page directory slot */ -{ - const rec_t* rec = page_dir_slot_get_rec(slot); - if (page_rec_is_comp(slot)) { - return(rec_get_n_owned_new(rec)); - } else { - return(rec_get_n_owned_old(rec)); - } -} - -/***************************************************************//** -This is used to set the owned records field of a directory slot. */ -UNIV_INLINE -void -page_dir_slot_set_n_owned( -/*======================*/ - page_dir_slot_t*slot, /*!< in/out: directory slot */ - page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ - ulint n) /*!< in: number of records owned by the slot */ -{ - rec_t* rec = (rec_t*) page_dir_slot_get_rec(slot); - if (page_rec_is_comp(slot)) { - rec_set_n_owned_new(rec, page_zip, n); - } else { - ut_ad(!page_zip); - rec_set_n_owned_old(rec, n); - } -} - -/************************************************************//** -Calculates the space reserved for directory slots of a given number of -records. The exact value is a fraction number n * PAGE_DIR_SLOT_SIZE / -PAGE_DIR_SLOT_MIN_N_OWNED, and it is rounded upwards to an integer. */ -UNIV_INLINE -ulint -page_dir_calc_reserved_space( -/*=========================*/ - ulint n_recs) /*!< in: number of records */ -{ - return((PAGE_DIR_SLOT_SIZE * n_recs + PAGE_DIR_SLOT_MIN_N_OWNED - 1) - / PAGE_DIR_SLOT_MIN_N_OWNED); -} - -/************************************************************//** -Gets the pointer to the next record on the page. -@return pointer to next record */ -UNIV_INLINE -const rec_t* -page_rec_get_next_low( -/*==================*/ - const rec_t* rec, /*!< in: pointer to record */ - ulint comp) /*!< in: nonzero=compact page layout */ -{ - ulint offs; - const page_t* page; - - ut_ad(page_rec_check(rec)); - - page = page_align(rec); - - offs = rec_get_next_offs(rec, comp); - - if (offs >= srv_page_size) { - fprintf(stderr, - "InnoDB: Next record offset is nonsensical %lu" - " in record at offset %lu\n" - "InnoDB: rec address %p, space id %lu, page %lu\n", - (ulong) offs, (ulong) page_offset(rec), - (void*) rec, - (ulong) page_get_space_id(page), - (ulong) page_get_page_no(page)); - ut_error; - } else if (offs == 0) { - - return(NULL); - } - - ut_ad(page_rec_is_infimum(rec) - || (!page_is_leaf(page) && !page_has_prev(page)) - || !(rec_get_info_bits(page + offs, comp) - & REC_INFO_MIN_REC_FLAG)); - - return(page + offs); -} - -/************************************************************//** -Gets the pointer to the next record on the page. -@return pointer to next record */ -UNIV_INLINE -rec_t* -page_rec_get_next( -/*==============*/ - rec_t* rec) /*!< in: pointer to record */ -{ - return((rec_t*) page_rec_get_next_low(rec, page_rec_is_comp(rec))); -} - -/************************************************************//** -Gets the pointer to the next record on the page. -@return pointer to next record */ -UNIV_INLINE -const rec_t* -page_rec_get_next_const( -/*====================*/ - const rec_t* rec) /*!< in: pointer to record */ -{ - return(page_rec_get_next_low(rec, page_rec_is_comp(rec))); -} - -/************************************************************//** -Gets the pointer to the next non delete-marked record on the page. -If all subsequent records are delete-marked, then this function -will return the supremum record. -@return pointer to next non delete-marked record or pointer to supremum */ -UNIV_INLINE -const rec_t* -page_rec_get_next_non_del_marked( -/*=============================*/ - const rec_t* rec) /*!< in: pointer to record */ -{ - const rec_t* r; - ulint page_is_compact = page_rec_is_comp(rec); - - for (r = page_rec_get_next_const(rec); - !page_rec_is_supremum(r) - && rec_get_deleted_flag(r, page_is_compact); - r = page_rec_get_next_const(r)) { - /* noop */ - } - - return(r); -} - -/************************************************************//** -Sets the pointer to the next record on the page. */ -UNIV_INLINE -void -page_rec_set_next( -/*==============*/ - rec_t* rec, /*!< in: pointer to record, - must not be page supremum */ - const rec_t* next) /*!< in: pointer to next record, - must not be page infimum */ -{ - ulint offs; - - ut_ad(page_rec_check(rec)); - ut_ad(!page_rec_is_supremum(rec)); - ut_ad(rec != next); - - ut_ad(!next || !page_rec_is_infimum(next)); - ut_ad(!next || page_align(rec) == page_align(next)); - - offs = next != NULL ? page_offset(next) : 0; - - if (page_rec_is_comp(rec)) { - rec_set_next_offs_new(rec, offs); - } else { - rec_set_next_offs_old(rec, offs); - } -} - -/************************************************************//** -Gets the pointer to the previous record. -@return pointer to previous record */ -UNIV_INLINE -const rec_t* -page_rec_get_prev_const( -/*====================*/ - const rec_t* rec) /*!< in: pointer to record, must not be page - infimum */ -{ - const page_dir_slot_t* slot; - ulint slot_no; - const rec_t* rec2; - const rec_t* prev_rec = NULL; - const page_t* page; - - ut_ad(page_rec_check(rec)); - - page = page_align(rec); - - ut_ad(!page_rec_is_infimum(rec)); - - slot_no = page_dir_find_owner_slot(rec); - - ut_a(slot_no != 0); - - slot = page_dir_get_nth_slot(page, slot_no - 1); - - rec2 = page_dir_slot_get_rec(slot); - - if (page_is_comp(page)) { - while (rec != rec2) { - prev_rec = rec2; - rec2 = page_rec_get_next_low(rec2, TRUE); - } - } else { - while (rec != rec2) { - prev_rec = rec2; - rec2 = page_rec_get_next_low(rec2, FALSE); - } - } - - ut_a(prev_rec); - - return(prev_rec); -} - -/************************************************************//** -Gets the pointer to the previous record. -@return pointer to previous record */ -UNIV_INLINE -rec_t* -page_rec_get_prev( -/*==============*/ - rec_t* rec) /*!< in: pointer to record, must not be page - infimum */ -{ - return((rec_t*) page_rec_get_prev_const(rec)); -} - -/***************************************************************//** -Looks for the record which owns the given record. -@return the owner record */ -UNIV_INLINE -rec_t* -page_rec_find_owner_rec( -/*====================*/ - rec_t* rec) /*!< in: the physical record */ -{ - ut_ad(page_rec_check(rec)); - - if (page_rec_is_comp(rec)) { - while (rec_get_n_owned_new(rec) == 0) { - rec = page_rec_get_next(rec); - } - } else { - while (rec_get_n_owned_old(rec) == 0) { - rec = page_rec_get_next(rec); - } - } - - return(rec); -} - -/**********************************************************//** -Returns the base extra size of a physical record. This is the -size of the fixed header, independent of the record size. -@return REC_N_NEW_EXTRA_BYTES or REC_N_OLD_EXTRA_BYTES */ -UNIV_INLINE -ulint -page_rec_get_base_extra_size( -/*=========================*/ - const rec_t* rec) /*!< in: physical record */ -{ - compile_time_assert(REC_N_NEW_EXTRA_BYTES + 1 - == REC_N_OLD_EXTRA_BYTES); - return(REC_N_NEW_EXTRA_BYTES + (ulint) !page_rec_is_comp(rec)); -} - -#endif /* UNIV_INNOCHECKSUM */ - -/************************************************************//** -Returns the sum of the sizes of the records in the record list, excluding -the infimum and supremum records. -@return data in bytes */ -UNIV_INLINE -uint16_t -page_get_data_size( -/*===============*/ - const page_t* page) /*!< in: index page */ -{ - uint16_t ret = page_header_get_field(page, PAGE_HEAP_TOP) - - (page_is_comp(page) - ? PAGE_NEW_SUPREMUM_END - : PAGE_OLD_SUPREMUM_END) - - page_header_get_field(page, PAGE_GARBAGE); - ut_ad(ret < srv_page_size); - return(ret); -} - -#ifndef UNIV_INNOCHECKSUM -/************************************************************//** -Allocates a block of memory from the free list of an index page. */ -UNIV_INLINE -void -page_mem_alloc_free( -/*================*/ - page_t* page, /*!< in/out: index page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page with enough - space available for inserting the record, - or NULL */ - rec_t* next_rec,/*!< in: pointer to the new head of the - free record list */ - ulint need) /*!< in: number of bytes allocated */ -{ - ulint garbage; - -#ifdef UNIV_DEBUG - const rec_t* old_rec = page_header_get_ptr(page, PAGE_FREE); - ulint next_offs; - - ut_ad(old_rec); - next_offs = rec_get_next_offs(old_rec, page_is_comp(page)); - ut_ad(next_rec == (next_offs ? page + next_offs : NULL)); -#endif - - page_header_set_ptr(page, page_zip, PAGE_FREE, next_rec); - - garbage = page_header_get_field(page, PAGE_GARBAGE); - ut_ad(garbage >= need); - - page_header_set_field(page, page_zip, PAGE_GARBAGE, garbage - need); -} - -/*************************************************************//** -Calculates free space if a page is emptied. -@return free space */ -UNIV_INLINE -ulint -page_get_free_space_of_empty( -/*=========================*/ - ulint comp) /*!< in: nonzero=compact page layout */ -{ - if (comp) { - return((ulint)(srv_page_size - - PAGE_NEW_SUPREMUM_END - - PAGE_DIR - - 2 * PAGE_DIR_SLOT_SIZE)); - } - - return((ulint)(srv_page_size - - PAGE_OLD_SUPREMUM_END - - PAGE_DIR - - 2 * PAGE_DIR_SLOT_SIZE)); -} - -/************************************************************//** -Each user record on a page, and also the deleted user records in the heap -takes its size plus the fraction of the dir cell size / -PAGE_DIR_SLOT_MIN_N_OWNED bytes for it. If the sum of these exceeds the -value of page_get_free_space_of_empty, the insert is impossible, otherwise -it is allowed. This function returns the maximum combined size of records -which can be inserted on top of the record heap. -@return maximum combined size for inserted records */ -UNIV_INLINE -ulint -page_get_max_insert_size( -/*=====================*/ - const page_t* page, /*!< in: index page */ - ulint n_recs) /*!< in: number of records */ -{ - ulint occupied; - ulint free_space; - - if (page_is_comp(page)) { - occupied = page_header_get_field(page, PAGE_HEAP_TOP) - - PAGE_NEW_SUPREMUM_END - + page_dir_calc_reserved_space( - n_recs + page_dir_get_n_heap(page) - 2); - - free_space = page_get_free_space_of_empty(TRUE); - } else { - occupied = page_header_get_field(page, PAGE_HEAP_TOP) - - PAGE_OLD_SUPREMUM_END - + page_dir_calc_reserved_space( - n_recs + page_dir_get_n_heap(page) - 2); - - free_space = page_get_free_space_of_empty(FALSE); - } - - /* Above the 'n_recs +' part reserves directory space for the new - inserted records; the '- 2' excludes page infimum and supremum - records */ - - if (occupied > free_space) { - - return(0); - } - - return(free_space - occupied); -} - -/************************************************************//** -Returns the maximum combined size of records which can be inserted on top -of the record heap if a page is first reorganized. -@return maximum combined size for inserted records */ -UNIV_INLINE -ulint -page_get_max_insert_size_after_reorganize( -/*======================================*/ - const page_t* page, /*!< in: index page */ - ulint n_recs) /*!< in: number of records */ -{ - ulint occupied; - ulint free_space; - - occupied = page_get_data_size(page) - + page_dir_calc_reserved_space(n_recs + page_get_n_recs(page)); - - free_space = page_get_free_space_of_empty(page_is_comp(page)); - - if (occupied > free_space) { - - return(0); - } - - return(free_space - occupied); -} - -/************************************************************//** -Puts a record to free list. */ -UNIV_INLINE -void -page_mem_free( -/*==========*/ - page_t* page, /*!< in/out: index page */ - page_zip_des_t* page_zip, /*!< in/out: compressed page, - or NULL */ - rec_t* rec, /*!< in: pointer to the - (origin of) record */ - const dict_index_t* index, /*!< in: index of rec */ - const rec_offs* offsets) /*!< in: array returned by - rec_get_offsets() */ -{ - rec_t* free; - ulint garbage; - - ut_ad(rec_offs_validate(rec, index, offsets)); - free = page_header_get_ptr(page, PAGE_FREE); - - if (srv_immediate_scrub_data_uncompressed) { - /* scrub record */ - memset(rec, 0, rec_offs_data_size(offsets)); - } - - page_rec_set_next(rec, free); - page_header_set_ptr(page, page_zip, PAGE_FREE, rec); - - garbage = page_header_get_field(page, PAGE_GARBAGE); - - page_header_set_field(page, page_zip, PAGE_GARBAGE, - garbage + rec_offs_size(offsets)); - - if (page_zip) { - page_zip_dir_delete(page_zip, rec, index, offsets, free); - } else { - page_header_set_field(page, page_zip, PAGE_N_RECS, - ulint(page_get_n_recs(page)) - 1); - } -} - -#endif /* !UNIV_INNOCHECKSUM */ - -#ifdef UNIV_MATERIALIZE -#undef UNIV_INLINE -#define UNIV_INLINE UNIV_INLINE_ORIGINAL -#endif - -#endif diff --git a/storage/innobase/include/page0page.inl b/storage/innobase/include/page0page.inl new file mode 100644 index 00000000000..5f69925a41a --- /dev/null +++ b/storage/innobase/include/page0page.inl @@ -0,0 +1,1062 @@ +/***************************************************************************** + +Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. +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 +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/page0page.ic +Index page routines + +Created 2/2/1994 Heikki Tuuri +*******************************************************/ + +#ifndef page0page_ic +#define page0page_ic + +#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 +trx_id_t +page_get_max_trx_id( +/*================*/ + const page_t* page) /*!< in: page */ +{ + ut_ad(page); + + return(mach_read_from_8(page + PAGE_HEADER + PAGE_MAX_TRX_ID)); +} + +/*************************************************************//** +Sets the max trx id field value if trx_id is bigger than the previous +value. */ +UNIV_INLINE +void +page_update_max_trx_id( +/*===================*/ + buf_block_t* block, /*!< in/out: page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL */ + trx_id_t trx_id, /*!< in: transaction id */ + mtr_t* mtr) /*!< in/out: mini-transaction */ +{ + ut_ad(block); + ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + /* During crash recovery, this function may be called on + something else than a leaf page of a secondary index or the + insert buffer index tree (dict_index_is_sec_or_ibuf() returns + TRUE for the dummy indexes constructed during redo log + application). In that case, PAGE_MAX_TRX_ID is unused, + and trx_id is usually zero. */ + ut_ad(trx_id || recv_recovery_is_on()); + ut_ad(page_is_leaf(buf_block_get_frame(block))); + + if (page_get_max_trx_id(buf_block_get_frame(block)) < trx_id) { + + page_set_max_trx_id(block, page_zip, trx_id, mtr); + } +} + +/** Read the AUTO_INCREMENT value from a clustered index root page. +@param[in] page clustered index root page +@return the persisted AUTO_INCREMENT value */ +UNIV_INLINE +ib_uint64_t +page_get_autoinc(const page_t* page) +{ + ut_ad(fil_page_index_page_check(page)); + ut_ad(!page_has_siblings(page)); + return(mach_read_from_8(PAGE_HEADER + PAGE_ROOT_AUTO_INC + page)); +} + +/*************************************************************//** +Returns the RTREE SPLIT SEQUENCE NUMBER (FIL_RTREE_SPLIT_SEQ_NUM). +@return SPLIT SEQUENCE NUMBER */ +UNIV_INLINE +node_seq_t +page_get_ssn_id( +/*============*/ + const page_t* page) /*!< in: page */ +{ + ut_ad(page); + + return(static_cast( + mach_read_from_8(page + FIL_RTREE_SPLIT_SEQ_NUM))); +} + +/*************************************************************//** +Sets the RTREE SPLIT SEQUENCE NUMBER field value */ +UNIV_INLINE +void +page_set_ssn_id( +/*============*/ + buf_block_t* block, /*!< in/out: page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL */ + node_seq_t ssn_id, /*!< in: transaction id */ + mtr_t* mtr) /*!< in/out: mini-transaction */ +{ + page_t* page = buf_block_get_frame(block); + + ut_ad(!mtr || mtr_memo_contains_flagged(mtr, block, + MTR_MEMO_PAGE_SX_FIX + | MTR_MEMO_PAGE_X_FIX)); + + if (page_zip) { + mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id); + page_zip_write_header(page_zip, + page + FIL_RTREE_SPLIT_SEQ_NUM, + 8, mtr); + } else if (mtr) { + mlog_write_ull(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id, mtr); + } else { + mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id); + } +} + +#endif /* !UNIV_INNOCHECKSUM */ + +/*************************************************************//** +Reads the given header field. */ +UNIV_INLINE +uint16_t +page_header_get_field( +/*==================*/ + const page_t* page, /*!< in: page */ + ulint field) /*!< in: PAGE_LEVEL, ... */ +{ + ut_ad(page); + ut_ad(field <= PAGE_INDEX_ID); + + return(mach_read_from_2(page + PAGE_HEADER + field)); +} + +#ifndef UNIV_INNOCHECKSUM +/*************************************************************//** +Sets the given header field. */ +UNIV_INLINE +void +page_header_set_field( +/*==================*/ + page_t* page, /*!< in/out: page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL */ + ulint field, /*!< in: PAGE_N_DIR_SLOTS, ... */ + ulint val) /*!< in: value */ +{ + ut_ad(page); + ut_ad(field <= PAGE_N_RECS); + ut_ad(field == PAGE_N_HEAP || val < srv_page_size); + ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < srv_page_size); + + mach_write_to_2(page + PAGE_HEADER + field, val); + if (page_zip) { + page_zip_write_header(page_zip, + page + PAGE_HEADER + field, 2, NULL); + } +} + +/*************************************************************//** +Returns the offset stored in the given header field. +@return offset from the start of the page, or 0 */ +UNIV_INLINE +uint16_t +page_header_get_offs( +/*=================*/ + const page_t* page, /*!< in: page */ + ulint field) /*!< in: PAGE_FREE, ... */ +{ + ut_ad((field == PAGE_FREE) + || (field == PAGE_LAST_INSERT) + || (field == PAGE_HEAP_TOP)); + + uint16_t offs = page_header_get_field(page, field); + + ut_ad((field != PAGE_HEAP_TOP) || offs); + + return(offs); +} + +/*************************************************************//** +Sets the pointer stored in the given header field. */ +UNIV_INLINE +void +page_header_set_ptr( +/*================*/ + page_t* page, /*!< in: page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL */ + ulint field, /*!< in: PAGE_FREE, ... */ + const byte* ptr) /*!< in: pointer or NULL*/ +{ + ulint offs; + + ut_ad(page); + ut_ad((field == PAGE_FREE) + || (field == PAGE_LAST_INSERT) + || (field == PAGE_HEAP_TOP)); + + if (ptr == NULL) { + offs = 0; + } else { + offs = ulint(ptr - page); + } + + ut_ad((field != PAGE_HEAP_TOP) || offs); + + page_header_set_field(page, page_zip, field, offs); +} + +/*************************************************************//** +Resets the last insert info field in the page header. Writes to mlog +about this operation. */ +UNIV_INLINE +void +page_header_reset_last_insert( +/*==========================*/ + page_t* page, /*!< in/out: page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(page != NULL); + ut_ad(mtr != NULL); + + if (page_zip) { + mach_write_to_2(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0); + page_zip_write_header(page_zip, + page + (PAGE_HEADER + PAGE_LAST_INSERT), + 2, mtr); + } else { + mlog_write_ulint(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0, + MLOG_2BYTES, mtr); + } +} + +/***************************************************************//** +Returns the heap number of a record. +@return heap number */ +UNIV_INLINE +ulint +page_rec_get_heap_no( +/*=================*/ + const rec_t* rec) /*!< in: the physical record */ +{ + if (page_rec_is_comp(rec)) { + return(rec_get_heap_no_new(rec)); + } else { + return(rec_get_heap_no_old(rec)); + } +} + +/** Determine whether an index page record is a user record. +@param[in] rec record in an index page +@return true if a user record */ +inline +bool +page_rec_is_user_rec(const rec_t* rec) +{ + ut_ad(page_rec_check(rec)); + return(page_rec_is_user_rec_low(page_offset(rec))); +} + +/** Determine whether an index page record is the supremum record. +@param[in] rec record in an index page +@return true if the supremum record */ +inline +bool +page_rec_is_supremum(const rec_t* rec) +{ + ut_ad(page_rec_check(rec)); + return(page_rec_is_supremum_low(page_offset(rec))); +} + +/** Determine whether an index page record is the infimum record. +@param[in] rec record in an index page +@return true if the infimum record */ +inline +bool +page_rec_is_infimum(const rec_t* rec) +{ + ut_ad(page_rec_check(rec)); + return(page_rec_is_infimum_low(page_offset(rec))); +} + +/************************************************************//** +true if the record is the first user record on a page. +@return true if the first user record */ +UNIV_INLINE +bool +page_rec_is_first( +/*==============*/ + const rec_t* rec, /*!< in: record */ + const page_t* page) /*!< in: page */ +{ + ut_ad(page_get_n_recs(page) > 0); + + return(page_rec_get_next_const(page_get_infimum_rec(page)) == rec); +} + +/************************************************************//** +true if the record is the second user record on a page. +@return true if the second user record */ +UNIV_INLINE +bool +page_rec_is_second( +/*===============*/ + const rec_t* rec, /*!< in: record */ + const page_t* page) /*!< in: page */ +{ + ut_ad(page_get_n_recs(page) > 1); + + return(page_rec_get_next_const( + page_rec_get_next_const(page_get_infimum_rec(page))) == rec); +} + +/************************************************************//** +true if the record is the last user record on a page. +@return true if the last user record */ +UNIV_INLINE +bool +page_rec_is_last( +/*=============*/ + const rec_t* rec, /*!< in: record */ + const page_t* page) /*!< in: page */ +{ + ut_ad(page_get_n_recs(page) > 0); + + return(page_rec_get_next_const(rec) == page_get_supremum_rec(page)); +} + +/************************************************************//** +true if distance between the records (measured in number of times we have to +move to the next record) is at most the specified value */ +UNIV_INLINE +bool +page_rec_distance_is_at_most( +/*=========================*/ + const rec_t* left_rec, + const rec_t* right_rec, + ulint val) +{ + for (ulint i = 0; i <= val; i++) { + if (left_rec == right_rec) { + return (true); + } + left_rec = page_rec_get_next_const(left_rec); + } + return (false); +} + +/************************************************************//** +true if the record is the second last user record on a page. +@return true if the second last user record */ +UNIV_INLINE +bool +page_rec_is_second_last( +/*====================*/ + const rec_t* rec, /*!< in: record */ + const page_t* page) /*!< in: page */ +{ + ut_ad(page_get_n_recs(page) > 1); + ut_ad(!page_rec_is_last(rec, page)); + + return(page_rec_get_next_const( + page_rec_get_next_const(rec)) == page_get_supremum_rec(page)); +} + +/************************************************************//** +Returns the nth record of the record list. +This is the inverse function of page_rec_get_n_recs_before(). +@return nth record */ +UNIV_INLINE +rec_t* +page_rec_get_nth( +/*=============*/ + page_t* page, /*!< in: page */ + ulint nth) /*!< in: nth record */ +{ + return((rec_t*) page_rec_get_nth_const(page, nth)); +} + +/************************************************************//** +Returns the middle record of the records on the page. If there is an +even number of records in the list, returns the first record of the +upper half-list. +@return middle record */ +UNIV_INLINE +rec_t* +page_get_middle_rec( +/*================*/ + page_t* page) /*!< in: page */ +{ + ulint middle = (ulint(page_get_n_recs(page)) + + PAGE_HEAP_NO_USER_LOW) / 2; + + return(page_rec_get_nth(page, middle)); +} + +#endif /* !UNIV_INNOCHECKSUM */ + +/*************************************************************//** +Gets the page number. +@return page number */ +UNIV_INLINE +ulint +page_get_page_no( +/*=============*/ + const page_t* page) /*!< in: page */ +{ + ut_ad(page == page_align((page_t*) page)); + return(mach_read_from_4(page + FIL_PAGE_OFFSET)); +} + +#ifndef UNIV_INNOCHECKSUM +/*************************************************************//** +Gets the tablespace identifier. +@return space id */ +UNIV_INLINE +ulint +page_get_space_id( +/*==============*/ + const page_t* page) /*!< in: page */ +{ + ut_ad(page == page_align((page_t*) page)); + return(mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID)); +} + +#endif /* !UNIV_INNOCHECKSUM */ + +/*************************************************************//** +Gets the number of user records on page (infimum and supremum records +are not user records). +@return number of user records */ +UNIV_INLINE +uint16_t +page_get_n_recs( +/*============*/ + const page_t* page) /*!< in: index page */ +{ + return(page_header_get_field(page, PAGE_N_RECS)); +} + +#ifndef UNIV_INNOCHECKSUM +/*************************************************************//** +Gets the number of dir slots in directory. +@return number of slots */ +UNIV_INLINE +uint16_t +page_dir_get_n_slots( +/*=================*/ + const page_t* page) /*!< in: index page */ +{ + return(page_header_get_field(page, PAGE_N_DIR_SLOTS)); +} +/*************************************************************//** +Sets the number of dir slots in directory. */ +UNIV_INLINE +void +page_dir_set_n_slots( +/*=================*/ + page_t* page, /*!< in/out: page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL */ + ulint n_slots)/*!< in: number of slots */ +{ + page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots); +} + +/*************************************************************//** +Gets the number of records in the heap. +@return number of user records */ +UNIV_INLINE +uint16_t +page_dir_get_n_heap( +/*================*/ + const page_t* page) /*!< in: index page */ +{ + return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff); +} + +/*************************************************************//** +Sets the number of records in the heap. */ +UNIV_INLINE +void +page_dir_set_n_heap( +/*================*/ + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL. + Note that the size of the dense page directory + in the compressed page trailer is + n_heap * PAGE_ZIP_DIR_SLOT_SIZE. */ + ulint n_heap) /*!< in: number of records */ +{ + ut_ad(n_heap < 0x8000); + ut_ad(!page_zip || uint16_t(n_heap) + == (page_header_get_field(page, PAGE_N_HEAP) & 0x7fff) + 1); + + page_header_set_field(page, page_zip, PAGE_N_HEAP, n_heap + | (0x8000 + & page_header_get_field(page, PAGE_N_HEAP))); +} + +#ifdef UNIV_DEBUG +/*************************************************************//** +Gets pointer to nth directory slot. +@return pointer to dir slot */ +UNIV_INLINE +page_dir_slot_t* +page_dir_get_nth_slot( +/*==================*/ + const page_t* page, /*!< in: index page */ + ulint n) /*!< in: position */ +{ + ut_ad(page_dir_get_n_slots(page) > n); + + return((page_dir_slot_t*) + page + srv_page_size - PAGE_DIR + - (n + 1) * PAGE_DIR_SLOT_SIZE); +} +#endif /* UNIV_DEBUG */ + +/**************************************************************//** +Used to check the consistency of a record on a page. +@return TRUE if succeed */ +UNIV_INLINE +ibool +page_rec_check( +/*===========*/ + const rec_t* rec) /*!< in: record */ +{ + const page_t* page = page_align(rec); + + ut_a(rec); + + ut_a(page_offset(rec) <= page_header_get_field(page, PAGE_HEAP_TOP)); + ut_a(page_offset(rec) >= PAGE_DATA); + + return(TRUE); +} + +/***************************************************************//** +Gets the record pointed to by a directory slot. +@return pointer to record */ +UNIV_INLINE +const rec_t* +page_dir_slot_get_rec( +/*==================*/ + const page_dir_slot_t* slot) /*!< in: directory slot */ +{ + return(page_align(slot) + mach_read_from_2(slot)); +} + +/***************************************************************//** +This is used to set the record offset in a directory slot. */ +UNIV_INLINE +void +page_dir_slot_set_rec( +/*==================*/ + page_dir_slot_t* slot, /*!< in: directory slot */ + rec_t* rec) /*!< in: record on the page */ +{ + ut_ad(page_rec_check(rec)); + + mach_write_to_2(slot, page_offset(rec)); +} + +/***************************************************************//** +Gets the number of records owned by a directory slot. +@return number of records */ +UNIV_INLINE +ulint +page_dir_slot_get_n_owned( +/*======================*/ + const page_dir_slot_t* slot) /*!< in: page directory slot */ +{ + const rec_t* rec = page_dir_slot_get_rec(slot); + if (page_rec_is_comp(slot)) { + return(rec_get_n_owned_new(rec)); + } else { + return(rec_get_n_owned_old(rec)); + } +} + +/***************************************************************//** +This is used to set the owned records field of a directory slot. */ +UNIV_INLINE +void +page_dir_slot_set_n_owned( +/*======================*/ + page_dir_slot_t*slot, /*!< in/out: directory slot */ + page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ + ulint n) /*!< in: number of records owned by the slot */ +{ + rec_t* rec = (rec_t*) page_dir_slot_get_rec(slot); + if (page_rec_is_comp(slot)) { + rec_set_n_owned_new(rec, page_zip, n); + } else { + ut_ad(!page_zip); + rec_set_n_owned_old(rec, n); + } +} + +/************************************************************//** +Calculates the space reserved for directory slots of a given number of +records. The exact value is a fraction number n * PAGE_DIR_SLOT_SIZE / +PAGE_DIR_SLOT_MIN_N_OWNED, and it is rounded upwards to an integer. */ +UNIV_INLINE +ulint +page_dir_calc_reserved_space( +/*=========================*/ + ulint n_recs) /*!< in: number of records */ +{ + return((PAGE_DIR_SLOT_SIZE * n_recs + PAGE_DIR_SLOT_MIN_N_OWNED - 1) + / PAGE_DIR_SLOT_MIN_N_OWNED); +} + +/************************************************************//** +Gets the pointer to the next record on the page. +@return pointer to next record */ +UNIV_INLINE +const rec_t* +page_rec_get_next_low( +/*==================*/ + const rec_t* rec, /*!< in: pointer to record */ + ulint comp) /*!< in: nonzero=compact page layout */ +{ + ulint offs; + const page_t* page; + + ut_ad(page_rec_check(rec)); + + page = page_align(rec); + + offs = rec_get_next_offs(rec, comp); + + if (offs >= srv_page_size) { + fprintf(stderr, + "InnoDB: Next record offset is nonsensical %lu" + " in record at offset %lu\n" + "InnoDB: rec address %p, space id %lu, page %lu\n", + (ulong) offs, (ulong) page_offset(rec), + (void*) rec, + (ulong) page_get_space_id(page), + (ulong) page_get_page_no(page)); + ut_error; + } else if (offs == 0) { + + return(NULL); + } + + ut_ad(page_rec_is_infimum(rec) + || (!page_is_leaf(page) && !page_has_prev(page)) + || !(rec_get_info_bits(page + offs, comp) + & REC_INFO_MIN_REC_FLAG)); + + return(page + offs); +} + +/************************************************************//** +Gets the pointer to the next record on the page. +@return pointer to next record */ +UNIV_INLINE +rec_t* +page_rec_get_next( +/*==============*/ + rec_t* rec) /*!< in: pointer to record */ +{ + return((rec_t*) page_rec_get_next_low(rec, page_rec_is_comp(rec))); +} + +/************************************************************//** +Gets the pointer to the next record on the page. +@return pointer to next record */ +UNIV_INLINE +const rec_t* +page_rec_get_next_const( +/*====================*/ + const rec_t* rec) /*!< in: pointer to record */ +{ + return(page_rec_get_next_low(rec, page_rec_is_comp(rec))); +} + +/************************************************************//** +Gets the pointer to the next non delete-marked record on the page. +If all subsequent records are delete-marked, then this function +will return the supremum record. +@return pointer to next non delete-marked record or pointer to supremum */ +UNIV_INLINE +const rec_t* +page_rec_get_next_non_del_marked( +/*=============================*/ + const rec_t* rec) /*!< in: pointer to record */ +{ + const rec_t* r; + ulint page_is_compact = page_rec_is_comp(rec); + + for (r = page_rec_get_next_const(rec); + !page_rec_is_supremum(r) + && rec_get_deleted_flag(r, page_is_compact); + r = page_rec_get_next_const(r)) { + /* noop */ + } + + return(r); +} + +/************************************************************//** +Sets the pointer to the next record on the page. */ +UNIV_INLINE +void +page_rec_set_next( +/*==============*/ + rec_t* rec, /*!< in: pointer to record, + must not be page supremum */ + const rec_t* next) /*!< in: pointer to next record, + must not be page infimum */ +{ + ulint offs; + + ut_ad(page_rec_check(rec)); + ut_ad(!page_rec_is_supremum(rec)); + ut_ad(rec != next); + + ut_ad(!next || !page_rec_is_infimum(next)); + ut_ad(!next || page_align(rec) == page_align(next)); + + offs = next != NULL ? page_offset(next) : 0; + + if (page_rec_is_comp(rec)) { + rec_set_next_offs_new(rec, offs); + } else { + rec_set_next_offs_old(rec, offs); + } +} + +/************************************************************//** +Gets the pointer to the previous record. +@return pointer to previous record */ +UNIV_INLINE +const rec_t* +page_rec_get_prev_const( +/*====================*/ + const rec_t* rec) /*!< in: pointer to record, must not be page + infimum */ +{ + const page_dir_slot_t* slot; + ulint slot_no; + const rec_t* rec2; + const rec_t* prev_rec = NULL; + const page_t* page; + + ut_ad(page_rec_check(rec)); + + page = page_align(rec); + + ut_ad(!page_rec_is_infimum(rec)); + + slot_no = page_dir_find_owner_slot(rec); + + ut_a(slot_no != 0); + + slot = page_dir_get_nth_slot(page, slot_no - 1); + + rec2 = page_dir_slot_get_rec(slot); + + if (page_is_comp(page)) { + while (rec != rec2) { + prev_rec = rec2; + rec2 = page_rec_get_next_low(rec2, TRUE); + } + } else { + while (rec != rec2) { + prev_rec = rec2; + rec2 = page_rec_get_next_low(rec2, FALSE); + } + } + + ut_a(prev_rec); + + return(prev_rec); +} + +/************************************************************//** +Gets the pointer to the previous record. +@return pointer to previous record */ +UNIV_INLINE +rec_t* +page_rec_get_prev( +/*==============*/ + rec_t* rec) /*!< in: pointer to record, must not be page + infimum */ +{ + return((rec_t*) page_rec_get_prev_const(rec)); +} + +/***************************************************************//** +Looks for the record which owns the given record. +@return the owner record */ +UNIV_INLINE +rec_t* +page_rec_find_owner_rec( +/*====================*/ + rec_t* rec) /*!< in: the physical record */ +{ + ut_ad(page_rec_check(rec)); + + if (page_rec_is_comp(rec)) { + while (rec_get_n_owned_new(rec) == 0) { + rec = page_rec_get_next(rec); + } + } else { + while (rec_get_n_owned_old(rec) == 0) { + rec = page_rec_get_next(rec); + } + } + + return(rec); +} + +/**********************************************************//** +Returns the base extra size of a physical record. This is the +size of the fixed header, independent of the record size. +@return REC_N_NEW_EXTRA_BYTES or REC_N_OLD_EXTRA_BYTES */ +UNIV_INLINE +ulint +page_rec_get_base_extra_size( +/*=========================*/ + const rec_t* rec) /*!< in: physical record */ +{ + compile_time_assert(REC_N_NEW_EXTRA_BYTES + 1 + == REC_N_OLD_EXTRA_BYTES); + return(REC_N_NEW_EXTRA_BYTES + (ulint) !page_rec_is_comp(rec)); +} + +#endif /* UNIV_INNOCHECKSUM */ + +/************************************************************//** +Returns the sum of the sizes of the records in the record list, excluding +the infimum and supremum records. +@return data in bytes */ +UNIV_INLINE +uint16_t +page_get_data_size( +/*===============*/ + const page_t* page) /*!< in: index page */ +{ + uint16_t ret = page_header_get_field(page, PAGE_HEAP_TOP) + - (page_is_comp(page) + ? PAGE_NEW_SUPREMUM_END + : PAGE_OLD_SUPREMUM_END) + - page_header_get_field(page, PAGE_GARBAGE); + ut_ad(ret < srv_page_size); + return(ret); +} + +#ifndef UNIV_INNOCHECKSUM +/************************************************************//** +Allocates a block of memory from the free list of an index page. */ +UNIV_INLINE +void +page_mem_alloc_free( +/*================*/ + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page with enough + space available for inserting the record, + or NULL */ + rec_t* next_rec,/*!< in: pointer to the new head of the + free record list */ + ulint need) /*!< in: number of bytes allocated */ +{ + ulint garbage; + +#ifdef UNIV_DEBUG + const rec_t* old_rec = page_header_get_ptr(page, PAGE_FREE); + ulint next_offs; + + ut_ad(old_rec); + next_offs = rec_get_next_offs(old_rec, page_is_comp(page)); + ut_ad(next_rec == (next_offs ? page + next_offs : NULL)); +#endif + + page_header_set_ptr(page, page_zip, PAGE_FREE, next_rec); + + garbage = page_header_get_field(page, PAGE_GARBAGE); + ut_ad(garbage >= need); + + page_header_set_field(page, page_zip, PAGE_GARBAGE, garbage - need); +} + +/*************************************************************//** +Calculates free space if a page is emptied. +@return free space */ +UNIV_INLINE +ulint +page_get_free_space_of_empty( +/*=========================*/ + ulint comp) /*!< in: nonzero=compact page layout */ +{ + if (comp) { + return((ulint)(srv_page_size + - PAGE_NEW_SUPREMUM_END + - PAGE_DIR + - 2 * PAGE_DIR_SLOT_SIZE)); + } + + return((ulint)(srv_page_size + - PAGE_OLD_SUPREMUM_END + - PAGE_DIR + - 2 * PAGE_DIR_SLOT_SIZE)); +} + +/************************************************************//** +Each user record on a page, and also the deleted user records in the heap +takes its size plus the fraction of the dir cell size / +PAGE_DIR_SLOT_MIN_N_OWNED bytes for it. If the sum of these exceeds the +value of page_get_free_space_of_empty, the insert is impossible, otherwise +it is allowed. This function returns the maximum combined size of records +which can be inserted on top of the record heap. +@return maximum combined size for inserted records */ +UNIV_INLINE +ulint +page_get_max_insert_size( +/*=====================*/ + const page_t* page, /*!< in: index page */ + ulint n_recs) /*!< in: number of records */ +{ + ulint occupied; + ulint free_space; + + if (page_is_comp(page)) { + occupied = page_header_get_field(page, PAGE_HEAP_TOP) + - PAGE_NEW_SUPREMUM_END + + page_dir_calc_reserved_space( + n_recs + page_dir_get_n_heap(page) - 2); + + free_space = page_get_free_space_of_empty(TRUE); + } else { + occupied = page_header_get_field(page, PAGE_HEAP_TOP) + - PAGE_OLD_SUPREMUM_END + + page_dir_calc_reserved_space( + n_recs + page_dir_get_n_heap(page) - 2); + + free_space = page_get_free_space_of_empty(FALSE); + } + + /* Above the 'n_recs +' part reserves directory space for the new + inserted records; the '- 2' excludes page infimum and supremum + records */ + + if (occupied > free_space) { + + return(0); + } + + return(free_space - occupied); +} + +/************************************************************//** +Returns the maximum combined size of records which can be inserted on top +of the record heap if a page is first reorganized. +@return maximum combined size for inserted records */ +UNIV_INLINE +ulint +page_get_max_insert_size_after_reorganize( +/*======================================*/ + const page_t* page, /*!< in: index page */ + ulint n_recs) /*!< in: number of records */ +{ + ulint occupied; + ulint free_space; + + occupied = page_get_data_size(page) + + page_dir_calc_reserved_space(n_recs + page_get_n_recs(page)); + + free_space = page_get_free_space_of_empty(page_is_comp(page)); + + if (occupied > free_space) { + + return(0); + } + + return(free_space - occupied); +} + +/************************************************************//** +Puts a record to free list. */ +UNIV_INLINE +void +page_mem_free( +/*==========*/ + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip, /*!< in/out: compressed page, + or NULL */ + rec_t* rec, /*!< in: pointer to the + (origin of) record */ + const dict_index_t* index, /*!< in: index of rec */ + const rec_offs* offsets) /*!< in: array returned by + rec_get_offsets() */ +{ + rec_t* free; + ulint garbage; + + ut_ad(rec_offs_validate(rec, index, offsets)); + free = page_header_get_ptr(page, PAGE_FREE); + + if (srv_immediate_scrub_data_uncompressed) { + /* scrub record */ + memset(rec, 0, rec_offs_data_size(offsets)); + } + + page_rec_set_next(rec, free); + page_header_set_ptr(page, page_zip, PAGE_FREE, rec); + + garbage = page_header_get_field(page, PAGE_GARBAGE); + + page_header_set_field(page, page_zip, PAGE_GARBAGE, + garbage + rec_offs_size(offsets)); + + if (page_zip) { + page_zip_dir_delete(page_zip, rec, index, offsets, free); + } else { + page_header_set_field(page, page_zip, PAGE_N_RECS, + ulint(page_get_n_recs(page)) - 1); + } +} + +#endif /* !UNIV_INNOCHECKSUM */ + +#ifdef UNIV_MATERIALIZE +#undef UNIV_INLINE +#define UNIV_INLINE UNIV_INLINE_ORIGINAL +#endif + +#endif diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h index f411fd0eee9..146cd055348 100644 --- a/storage/innobase/include/page0zip.h +++ b/storage/innobase/include/page0zip.h @@ -547,7 +547,7 @@ page_zip_reset_stat_per_index(); # define UNIV_INLINE UNIV_INLINE_ORIGINAL #endif -#include "page0zip.ic" +#include "page0zip.inl" #endif /* !UNIV_INNOCHECKSUM */ #endif /* page0zip_h */ diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic deleted file mode 100644 index 5a3b500e2c8..00000000000 --- a/storage/innobase/include/page0zip.ic +++ /dev/null @@ -1,447 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2012, Facebook Inc. -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/page0zip.ic -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" -#include "srv0srv.h" - -/* The format of compressed pages is as follows. - -The header and trailer of the uncompressed pages, excluding the page -directory in the trailer, are copied as is to the header and trailer -of the compressed page. - -At the end of the compressed page, there is a dense page directory -pointing to every user record contained on the page, including deleted -records on the free list. The dense directory is indexed in the -collation order, i.e., in the order in which the record list is -linked on the uncompressed page. The infimum and supremum records are -excluded. The two most significant bits of the entries are allocated -for the delete-mark and an n_owned flag indicating the last record in -a chain of records pointed to from the sparse page directory on the -uncompressed page. - -The data between PAGE_ZIP_START and the last page directory entry will -be written in compressed format, starting at offset PAGE_DATA. -Infimum and supremum records are not stored. We exclude the -REC_N_NEW_EXTRA_BYTES in every record header. These can be recovered -from the dense page directory stored at the end of the compressed -page. - -The fields node_ptr (in non-leaf B-tree nodes; level>0), trx_id and -roll_ptr (in leaf B-tree nodes; level=0), and BLOB pointers of -externally stored columns are stored separately, in ascending order of -heap_no and column index, starting backwards from the dense page -directory. - -The compressed data stream may be followed by a modification log -covering the compressed portion of the page, as follows. - -MODIFICATION LOG ENTRY FORMAT -- write record: - - (heap_no - 1) << 1 (1..2 bytes) - - extra bytes backwards - - data bytes -- clear record: - - (heap_no - 1) << 1 | 1 (1..2 bytes) - -The integer values are stored in a variable-length format: -- 0xxxxxxx: 0..127 -- 1xxxxxxx xxxxxxxx: 0..32767 - -The end of the modification log is marked by a 0 byte. - -In summary, the compressed page looks like this: - -(1) Uncompressed page header (PAGE_DATA bytes) -(2) Compressed index information -(3) Compressed page data -(4) Page modification log (page_zip->m_start..page_zip->m_end) -(5) Empty zero-filled space -(6) BLOB pointers (on leaf pages) - - BTR_EXTERN_FIELD_REF_SIZE for each externally stored column - - in descending collation order -(7) Uncompressed columns of user records, n_dense * uncompressed_size bytes, - - indexed by heap_no - - DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN for leaf pages of clustered indexes - - REC_NODE_PTR_SIZE for non-leaf pages - - 0 otherwise -(8) dense page directory, stored backwards - - n_dense = n_heap - 2 - - existing records in ascending collation order - - deleted records (free list) in link order -*/ - -/**********************************************************************//** -Determine the size of a compressed page in bytes. -@return size in bytes */ -UNIV_INLINE -ulint -page_zip_get_size( -/*==============*/ - const page_zip_des_t* page_zip) /*!< in: compressed page */ -{ - ulint size; - - if (!page_zip->ssize) { - return(0); - } - - size = (UNIV_ZIP_SIZE_MIN >> 1) << page_zip->ssize; - - ut_ad(size >= UNIV_ZIP_SIZE_MIN); - ut_ad(size <= UNIV_PAGE_SIZE); - - return(size); -} -/**********************************************************************//** -Set the size of a compressed page in bytes. */ -UNIV_INLINE -void -page_zip_set_size( -/*==============*/ - page_zip_des_t* page_zip, /*!< in/out: compressed page */ - ulint size) /*!< in: size in bytes */ -{ - if (size) { - unsigned ssize; - - ut_ad(ut_is_2pow(size)); - - for (ssize = 1; size > (512U << ssize); ssize++) { - } - - page_zip->ssize = ssize; - } else { - page_zip->ssize = 0; - } - - ut_ad(page_zip_get_size(page_zip) == size); -} - -/** Determine if a record is so big that it needs to be stored externally. -@param[in] rec_size length of the record in bytes -@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) -{ - /* 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()); - -#if UNIV_PAGE_SIZE_MAX > COMPRESSED_REC_MAX_DATA_SIZE - if (comp ? rec_size >= COMPRESSED_REC_MAX_DATA_SIZE : - rec_size >= REDUNDANT_REC_MAX_DATA_SIZE) { - return(TRUE); - } -#endif - - if (page_size.is_compressed()) { - ut_ad(comp); - /* On a compressed page, there is a two-byte entry in - the dense page directory for every record. But there - is no record header. There should be enough room for - one record on an empty leaf page. Subtract 1 byte for - 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()) - || rec_size >= page_get_free_space_of_empty(TRUE) / 2); - } - - return(rec_size >= page_get_free_space_of_empty(comp) / 2); -} - -#ifdef UNIV_DEBUG -/**********************************************************************//** -Validate a compressed page descriptor. -@return TRUE if ok */ -UNIV_INLINE -ibool -page_zip_simple_validate( -/*=====================*/ - const page_zip_des_t* page_zip)/*!< in: compressed page descriptor */ -{ - ut_ad(page_zip); - ut_ad(page_zip->data); - ut_ad(page_zip->ssize <= PAGE_ZIP_SSIZE_MAX); - ut_ad(page_zip_get_size(page_zip) - > PAGE_DATA + PAGE_ZIP_DIR_SLOT_SIZE); - ut_ad(page_zip->m_start <= page_zip->m_end); - ut_ad(page_zip->m_end < page_zip_get_size(page_zip)); - ut_ad(page_zip->n_blobs - < page_zip_get_size(page_zip) / BTR_EXTERN_FIELD_REF_SIZE); - return(TRUE); -} -#endif /* UNIV_DEBUG */ - -/**********************************************************************//** -Determine if the length of the page trailer. -@return length of the page trailer, in bytes, not including the -terminating zero byte of the modification log */ -UNIV_INLINE -ibool -page_zip_get_trailer_len( -/*=====================*/ - const page_zip_des_t* page_zip,/*!< in: compressed page */ - ibool is_clust)/*!< in: TRUE if clustered index */ -{ - ulint uncompressed_size; - - ut_ad(page_zip_simple_validate(page_zip)); - MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); - - if (!page_is_leaf(page_zip->data)) { - uncompressed_size = PAGE_ZIP_DIR_SLOT_SIZE - + REC_NODE_PTR_SIZE; - ut_ad(!page_zip->n_blobs); - } else if (is_clust) { - uncompressed_size = PAGE_ZIP_DIR_SLOT_SIZE - + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN; - } else { - uncompressed_size = PAGE_ZIP_DIR_SLOT_SIZE; - ut_ad(!page_zip->n_blobs); - } - - return((page_dir_get_n_heap(page_zip->data) - 2) - * uncompressed_size - + page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE); -} - -/**********************************************************************//** -Determine how big record can be inserted without recompressing the page. -@return a positive number indicating the maximum size of a record -whose insertion is guaranteed to succeed, or zero or negative */ -UNIV_INLINE -lint -page_zip_max_ins_size( -/*==================*/ - const page_zip_des_t* page_zip,/*!< in: compressed page */ - ibool is_clust)/*!< in: TRUE if clustered index */ -{ - ulint trailer_len; - - trailer_len = page_zip_get_trailer_len(page_zip, is_clust); - - /* When a record is created, a pointer may be added to - the dense directory. - Likewise, space for the columns that will not be - compressed will be allocated from the page trailer. - Also the BLOB pointers will be allocated from there, but - we may as well count them in the length of the record. */ - - trailer_len += PAGE_ZIP_DIR_SLOT_SIZE; - - return(lint(page_zip_get_size(page_zip) - - trailer_len - page_zip->m_end - - (REC_N_NEW_EXTRA_BYTES - 2))); -} - -/**********************************************************************//** -Determine if enough space is available in the modification log. -@return TRUE if enough space is available */ -UNIV_INLINE -ibool -page_zip_available( -/*===============*/ - const page_zip_des_t* page_zip,/*!< in: compressed page */ - ibool is_clust,/*!< in: TRUE if clustered index */ - ulint length, /*!< in: combined size of the record */ - ulint create) /*!< in: nonzero=add the record to - the heap */ -{ - ulint trailer_len; - - ut_ad(length > REC_N_NEW_EXTRA_BYTES); - - trailer_len = page_zip_get_trailer_len(page_zip, is_clust); - - /* Subtract the fixed extra bytes and add the maximum - space needed for identifying the record (encoded heap_no). */ - length -= REC_N_NEW_EXTRA_BYTES - 2; - - if (create > 0) { - /* When a record is created, a pointer may be added to - the dense directory. - Likewise, space for the columns that will not be - compressed will be allocated from the page trailer. - Also the BLOB pointers will be allocated from there, but - we may as well count them in the length of the record. */ - - trailer_len += PAGE_ZIP_DIR_SLOT_SIZE; - } - - return(length + trailer_len + page_zip->m_end - < page_zip_get_size(page_zip)); -} - -/**********************************************************************//** -Initialize a compressed page descriptor. */ -UNIV_INLINE -void -page_zip_des_init( -/*==============*/ - page_zip_des_t* page_zip) /*!< in/out: compressed page - descriptor */ -{ - memset(page_zip, 0, sizeof *page_zip); -} - -/**********************************************************************//** -Write a log record of writing to the uncompressed header portion of a page. */ -void -page_zip_write_header_log( -/*======================*/ - const byte* data,/*!< in: data on the uncompressed page */ - ulint length, /*!< in: length of the data */ - mtr_t* mtr); /*!< in: mini-transaction */ - -/**********************************************************************//** -Write data to the uncompressed header portion of a page. The data must -already have been written to the uncompressed page. -However, the data portion of the uncompressed page may differ from -the compressed page when a record is being inserted in -page_cur_insert_rec_zip(). */ -UNIV_INLINE -void -page_zip_write_header( -/*==================*/ - page_zip_des_t* page_zip,/*!< in/out: compressed page */ - const byte* str, /*!< in: address on the uncompressed page */ - ulint length, /*!< in: length of the data */ - mtr_t* mtr) /*!< in: mini-transaction, or NULL */ -{ - ulint pos; - - ut_ad(page_zip_simple_validate(page_zip)); - MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); - - pos = page_offset(str); - - ut_ad(pos < PAGE_DATA); - - memcpy(page_zip->data + pos, str, length); - - /* The following would fail in page_cur_insert_rec_zip(). */ - /* ut_ad(page_zip_validate(page_zip, str - pos)); */ - - if (mtr) { - page_zip_write_header_log(str, length, mtr); - } -} - -/**********************************************************************//** -Write a log record of compressing an index page without the data on the page. */ -UNIV_INLINE -void -page_zip_compress_write_log_no_data( -/*================================*/ - ulint level, /*!< in: compression level */ - const page_t* page, /*!< in: page that is compressed */ - dict_index_t* index, /*!< in: index */ - mtr_t* mtr) /*!< in: mtr */ -{ - byte* log_ptr = mlog_open_and_write_index( - mtr, page, index, MLOG_ZIP_PAGE_COMPRESS_NO_DATA, 1); - - if (log_ptr) { - mach_write_to_1(log_ptr, level); - mlog_close(mtr, log_ptr + 1); - } -} - -/**********************************************************************//** -Parses a log record of compressing an index page without the data. -@return end of log record or NULL */ -UNIV_INLINE -byte* -page_zip_parse_compress_no_data( -/*============================*/ - byte* ptr, /*!< in: buffer */ - byte* end_ptr, /*!< in: buffer end */ - page_t* page, /*!< in: uncompressed page */ - page_zip_des_t* page_zip, /*!< out: compressed page */ - dict_index_t* index) /*!< in: index */ -{ - ulint level; - if (end_ptr == ptr) { - return(NULL); - } - - level = mach_read_from_1(ptr); - - /* If page compression fails then there must be something wrong - because a compress log record is logged only if the compression - was successful. Crash in this case. */ - - if (page - && !page_zip_compress(page_zip, page, index, level, NULL, NULL)) { - ut_error; - } - - return(ptr + 1); -} - -/**********************************************************************//** -Reset the counters used for filling -INFORMATION_SCHEMA.innodb_cmp_per_index. */ -UNIV_INLINE -void -page_zip_reset_stat_per_index() -/*===========================*/ -{ - mutex_enter(&page_zip_stat_per_index_mutex); - - page_zip_stat_per_index.erase( - page_zip_stat_per_index.begin(), - page_zip_stat_per_index.end()); - - 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/page0zip.inl b/storage/innobase/include/page0zip.inl new file mode 100644 index 00000000000..5a3b500e2c8 --- /dev/null +++ b/storage/innobase/include/page0zip.inl @@ -0,0 +1,447 @@ +/***************************************************************************** + +Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, Facebook Inc. +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/page0zip.ic +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" +#include "srv0srv.h" + +/* The format of compressed pages is as follows. + +The header and trailer of the uncompressed pages, excluding the page +directory in the trailer, are copied as is to the header and trailer +of the compressed page. + +At the end of the compressed page, there is a dense page directory +pointing to every user record contained on the page, including deleted +records on the free list. The dense directory is indexed in the +collation order, i.e., in the order in which the record list is +linked on the uncompressed page. The infimum and supremum records are +excluded. The two most significant bits of the entries are allocated +for the delete-mark and an n_owned flag indicating the last record in +a chain of records pointed to from the sparse page directory on the +uncompressed page. + +The data between PAGE_ZIP_START and the last page directory entry will +be written in compressed format, starting at offset PAGE_DATA. +Infimum and supremum records are not stored. We exclude the +REC_N_NEW_EXTRA_BYTES in every record header. These can be recovered +from the dense page directory stored at the end of the compressed +page. + +The fields node_ptr (in non-leaf B-tree nodes; level>0), trx_id and +roll_ptr (in leaf B-tree nodes; level=0), and BLOB pointers of +externally stored columns are stored separately, in ascending order of +heap_no and column index, starting backwards from the dense page +directory. + +The compressed data stream may be followed by a modification log +covering the compressed portion of the page, as follows. + +MODIFICATION LOG ENTRY FORMAT +- write record: + - (heap_no - 1) << 1 (1..2 bytes) + - extra bytes backwards + - data bytes +- clear record: + - (heap_no - 1) << 1 | 1 (1..2 bytes) + +The integer values are stored in a variable-length format: +- 0xxxxxxx: 0..127 +- 1xxxxxxx xxxxxxxx: 0..32767 + +The end of the modification log is marked by a 0 byte. + +In summary, the compressed page looks like this: + +(1) Uncompressed page header (PAGE_DATA bytes) +(2) Compressed index information +(3) Compressed page data +(4) Page modification log (page_zip->m_start..page_zip->m_end) +(5) Empty zero-filled space +(6) BLOB pointers (on leaf pages) + - BTR_EXTERN_FIELD_REF_SIZE for each externally stored column + - in descending collation order +(7) Uncompressed columns of user records, n_dense * uncompressed_size bytes, + - indexed by heap_no + - DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN for leaf pages of clustered indexes + - REC_NODE_PTR_SIZE for non-leaf pages + - 0 otherwise +(8) dense page directory, stored backwards + - n_dense = n_heap - 2 + - existing records in ascending collation order + - deleted records (free list) in link order +*/ + +/**********************************************************************//** +Determine the size of a compressed page in bytes. +@return size in bytes */ +UNIV_INLINE +ulint +page_zip_get_size( +/*==============*/ + const page_zip_des_t* page_zip) /*!< in: compressed page */ +{ + ulint size; + + if (!page_zip->ssize) { + return(0); + } + + size = (UNIV_ZIP_SIZE_MIN >> 1) << page_zip->ssize; + + ut_ad(size >= UNIV_ZIP_SIZE_MIN); + ut_ad(size <= UNIV_PAGE_SIZE); + + return(size); +} +/**********************************************************************//** +Set the size of a compressed page in bytes. */ +UNIV_INLINE +void +page_zip_set_size( +/*==============*/ + page_zip_des_t* page_zip, /*!< in/out: compressed page */ + ulint size) /*!< in: size in bytes */ +{ + if (size) { + unsigned ssize; + + ut_ad(ut_is_2pow(size)); + + for (ssize = 1; size > (512U << ssize); ssize++) { + } + + page_zip->ssize = ssize; + } else { + page_zip->ssize = 0; + } + + ut_ad(page_zip_get_size(page_zip) == size); +} + +/** Determine if a record is so big that it needs to be stored externally. +@param[in] rec_size length of the record in bytes +@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) +{ + /* 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()); + +#if UNIV_PAGE_SIZE_MAX > COMPRESSED_REC_MAX_DATA_SIZE + if (comp ? rec_size >= COMPRESSED_REC_MAX_DATA_SIZE : + rec_size >= REDUNDANT_REC_MAX_DATA_SIZE) { + return(TRUE); + } +#endif + + if (page_size.is_compressed()) { + ut_ad(comp); + /* On a compressed page, there is a two-byte entry in + the dense page directory for every record. But there + is no record header. There should be enough room for + one record on an empty leaf page. Subtract 1 byte for + 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()) + || rec_size >= page_get_free_space_of_empty(TRUE) / 2); + } + + return(rec_size >= page_get_free_space_of_empty(comp) / 2); +} + +#ifdef UNIV_DEBUG +/**********************************************************************//** +Validate a compressed page descriptor. +@return TRUE if ok */ +UNIV_INLINE +ibool +page_zip_simple_validate( +/*=====================*/ + const page_zip_des_t* page_zip)/*!< in: compressed page descriptor */ +{ + ut_ad(page_zip); + ut_ad(page_zip->data); + ut_ad(page_zip->ssize <= PAGE_ZIP_SSIZE_MAX); + ut_ad(page_zip_get_size(page_zip) + > PAGE_DATA + PAGE_ZIP_DIR_SLOT_SIZE); + ut_ad(page_zip->m_start <= page_zip->m_end); + ut_ad(page_zip->m_end < page_zip_get_size(page_zip)); + ut_ad(page_zip->n_blobs + < page_zip_get_size(page_zip) / BTR_EXTERN_FIELD_REF_SIZE); + return(TRUE); +} +#endif /* UNIV_DEBUG */ + +/**********************************************************************//** +Determine if the length of the page trailer. +@return length of the page trailer, in bytes, not including the +terminating zero byte of the modification log */ +UNIV_INLINE +ibool +page_zip_get_trailer_len( +/*=====================*/ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + ibool is_clust)/*!< in: TRUE if clustered index */ +{ + ulint uncompressed_size; + + ut_ad(page_zip_simple_validate(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); + + if (!page_is_leaf(page_zip->data)) { + uncompressed_size = PAGE_ZIP_DIR_SLOT_SIZE + + REC_NODE_PTR_SIZE; + ut_ad(!page_zip->n_blobs); + } else if (is_clust) { + uncompressed_size = PAGE_ZIP_DIR_SLOT_SIZE + + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN; + } else { + uncompressed_size = PAGE_ZIP_DIR_SLOT_SIZE; + ut_ad(!page_zip->n_blobs); + } + + return((page_dir_get_n_heap(page_zip->data) - 2) + * uncompressed_size + + page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE); +} + +/**********************************************************************//** +Determine how big record can be inserted without recompressing the page. +@return a positive number indicating the maximum size of a record +whose insertion is guaranteed to succeed, or zero or negative */ +UNIV_INLINE +lint +page_zip_max_ins_size( +/*==================*/ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + ibool is_clust)/*!< in: TRUE if clustered index */ +{ + ulint trailer_len; + + trailer_len = page_zip_get_trailer_len(page_zip, is_clust); + + /* When a record is created, a pointer may be added to + the dense directory. + Likewise, space for the columns that will not be + compressed will be allocated from the page trailer. + Also the BLOB pointers will be allocated from there, but + we may as well count them in the length of the record. */ + + trailer_len += PAGE_ZIP_DIR_SLOT_SIZE; + + return(lint(page_zip_get_size(page_zip) + - trailer_len - page_zip->m_end + - (REC_N_NEW_EXTRA_BYTES - 2))); +} + +/**********************************************************************//** +Determine if enough space is available in the modification log. +@return TRUE if enough space is available */ +UNIV_INLINE +ibool +page_zip_available( +/*===============*/ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + ibool is_clust,/*!< in: TRUE if clustered index */ + ulint length, /*!< in: combined size of the record */ + ulint create) /*!< in: nonzero=add the record to + the heap */ +{ + ulint trailer_len; + + ut_ad(length > REC_N_NEW_EXTRA_BYTES); + + trailer_len = page_zip_get_trailer_len(page_zip, is_clust); + + /* Subtract the fixed extra bytes and add the maximum + space needed for identifying the record (encoded heap_no). */ + length -= REC_N_NEW_EXTRA_BYTES - 2; + + if (create > 0) { + /* When a record is created, a pointer may be added to + the dense directory. + Likewise, space for the columns that will not be + compressed will be allocated from the page trailer. + Also the BLOB pointers will be allocated from there, but + we may as well count them in the length of the record. */ + + trailer_len += PAGE_ZIP_DIR_SLOT_SIZE; + } + + return(length + trailer_len + page_zip->m_end + < page_zip_get_size(page_zip)); +} + +/**********************************************************************//** +Initialize a compressed page descriptor. */ +UNIV_INLINE +void +page_zip_des_init( +/*==============*/ + page_zip_des_t* page_zip) /*!< in/out: compressed page + descriptor */ +{ + memset(page_zip, 0, sizeof *page_zip); +} + +/**********************************************************************//** +Write a log record of writing to the uncompressed header portion of a page. */ +void +page_zip_write_header_log( +/*======================*/ + const byte* data,/*!< in: data on the uncompressed page */ + ulint length, /*!< in: length of the data */ + mtr_t* mtr); /*!< in: mini-transaction */ + +/**********************************************************************//** +Write data to the uncompressed header portion of a page. The data must +already have been written to the uncompressed page. +However, the data portion of the uncompressed page may differ from +the compressed page when a record is being inserted in +page_cur_insert_rec_zip(). */ +UNIV_INLINE +void +page_zip_write_header( +/*==================*/ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + const byte* str, /*!< in: address on the uncompressed page */ + ulint length, /*!< in: length of the data */ + mtr_t* mtr) /*!< in: mini-transaction, or NULL */ +{ + ulint pos; + + ut_ad(page_zip_simple_validate(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); + + pos = page_offset(str); + + ut_ad(pos < PAGE_DATA); + + memcpy(page_zip->data + pos, str, length); + + /* The following would fail in page_cur_insert_rec_zip(). */ + /* ut_ad(page_zip_validate(page_zip, str - pos)); */ + + if (mtr) { + page_zip_write_header_log(str, length, mtr); + } +} + +/**********************************************************************//** +Write a log record of compressing an index page without the data on the page. */ +UNIV_INLINE +void +page_zip_compress_write_log_no_data( +/*================================*/ + ulint level, /*!< in: compression level */ + const page_t* page, /*!< in: page that is compressed */ + dict_index_t* index, /*!< in: index */ + mtr_t* mtr) /*!< in: mtr */ +{ + byte* log_ptr = mlog_open_and_write_index( + mtr, page, index, MLOG_ZIP_PAGE_COMPRESS_NO_DATA, 1); + + if (log_ptr) { + mach_write_to_1(log_ptr, level); + mlog_close(mtr, log_ptr + 1); + } +} + +/**********************************************************************//** +Parses a log record of compressing an index page without the data. +@return end of log record or NULL */ +UNIV_INLINE +byte* +page_zip_parse_compress_no_data( +/*============================*/ + byte* ptr, /*!< in: buffer */ + byte* end_ptr, /*!< in: buffer end */ + page_t* page, /*!< in: uncompressed page */ + page_zip_des_t* page_zip, /*!< out: compressed page */ + dict_index_t* index) /*!< in: index */ +{ + ulint level; + if (end_ptr == ptr) { + return(NULL); + } + + level = mach_read_from_1(ptr); + + /* If page compression fails then there must be something wrong + because a compress log record is logged only if the compression + was successful. Crash in this case. */ + + if (page + && !page_zip_compress(page_zip, page, index, level, NULL, NULL)) { + ut_error; + } + + return(ptr + 1); +} + +/**********************************************************************//** +Reset the counters used for filling +INFORMATION_SCHEMA.innodb_cmp_per_index. */ +UNIV_INLINE +void +page_zip_reset_stat_per_index() +/*===========================*/ +{ + mutex_enter(&page_zip_stat_per_index_mutex); + + page_zip_stat_per_index.erase( + page_zip_stat_per_index.begin(), + page_zip_stat_per_index.end()); + + 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 2798a4d40fb..16c8ff78d10 100644 --- a/storage/innobase/include/que0que.h +++ b/storage/innobase/include/que0que.h @@ -449,6 +449,6 @@ struct que_fork_t{ /* Flag which is ORed to control structure statement node types */ #define QUE_NODE_CONTROL_STAT 1024 -#include "que0que.ic" +#include "que0que.inl" #endif diff --git a/storage/innobase/include/que0que.ic b/storage/innobase/include/que0que.ic deleted file mode 100644 index 1c3ac242bf2..00000000000 --- a/storage/innobase/include/que0que.ic +++ /dev/null @@ -1,293 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 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 -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/que0que.ic -Query graph - -Created 5/27/1996 Heikki Tuuri -*******************************************************/ - -/***********************************************************************//** -Gets the trx of a query thread. */ -UNIV_INLINE -trx_t* -thr_get_trx( -/*========*/ - que_thr_t* thr) /*!< in: query thread */ -{ - ut_ad(thr); - - return(thr->graph->trx); -} - -/***********************************************************************//** -Gets the first thr in a fork. */ -UNIV_INLINE -que_thr_t* -que_fork_get_first_thr( -/*===================*/ - que_fork_t* fork) /*!< in: query fork */ -{ - return(UT_LIST_GET_FIRST(fork->thrs)); -} - -/***********************************************************************//** -Gets the child node of the first thr in a fork. */ -UNIV_INLINE -que_node_t* -que_fork_get_child( -/*===============*/ - que_fork_t* fork) /*!< in: query fork */ -{ - que_thr_t* thr; - - thr = UT_LIST_GET_FIRST(fork->thrs); - - return(thr->child); -} - -/***********************************************************************//** -Gets the type of a graph node. */ -UNIV_INLINE -ulint -que_node_get_type( -/*==============*/ - const que_node_t* node) /*!< in: graph node */ -{ - return(reinterpret_cast(node)->type); -} - -/***********************************************************************//** -Gets pointer to the value dfield of a graph node. */ -UNIV_INLINE -dfield_t* -que_node_get_val( -/*=============*/ - que_node_t* node) /*!< in: graph node */ -{ - ut_ad(node); - - return(&(((que_common_t*) node)->val)); -} - -/***********************************************************************//** -Gets the value buffer size of a graph node. -@return val buffer size, not defined if val.data == NULL in node */ -UNIV_INLINE -ulint -que_node_get_val_buf_size( -/*======================*/ - que_node_t* node) /*!< in: graph node */ -{ - ut_ad(node); - - return(((que_common_t*) node)->val_buf_size); -} - -/***********************************************************************//** -Sets the value buffer size of a graph node. */ -UNIV_INLINE -void -que_node_set_val_buf_size( -/*======================*/ - que_node_t* node, /*!< in: graph node */ - ulint size) /*!< in: size */ -{ - ut_ad(node); - - ((que_common_t*) node)->val_buf_size = size; -} - -/***********************************************************************//** -Sets the parent of a graph node. */ -UNIV_INLINE -void -que_node_set_parent( -/*================*/ - que_node_t* node, /*!< in: graph node */ - que_node_t* parent) /*!< in: parent */ -{ - ut_ad(node); - - ((que_common_t*) node)->parent = parent; -} - -/***********************************************************************//** -Gets pointer to the value data type field of a graph node. */ -UNIV_INLINE -dtype_t* -que_node_get_data_type( -/*===================*/ - que_node_t* node) /*!< in: graph node */ -{ - ut_ad(node); - - return(dfield_get_type(&((que_common_t*) node)->val)); -} - -/*********************************************************************//** -Catenates a query graph node to a list of them, possible empty list. -@return one-way list of nodes */ -UNIV_INLINE -que_node_t* -que_node_list_add_last( -/*===================*/ - que_node_t* node_list, /*!< in: node list, or NULL */ - que_node_t* node) /*!< in: node */ -{ - que_common_t* cnode; - que_common_t* cnode2; - - cnode = (que_common_t*) node; - - cnode->brother = NULL; - - if (node_list == NULL) { - - return(node); - } - - cnode2 = (que_common_t*) node_list; - - while (cnode2->brother != NULL) { - cnode2 = (que_common_t*) cnode2->brother; - } - - cnode2->brother = node; - - return(node_list); -} - -/************************************************************************* -Removes a query graph node from the list.*/ -UNIV_INLINE -que_node_t* -que_node_list_get_last( -/*===================*/ - /* out: last node in list.*/ - que_node_t* node_list) /* in: node list */ -{ - que_common_t* node; - - ut_a(node_list != NULL); - - node = (que_common_t*) node_list; - - /* We need the last element */ - while (node->brother != NULL) { - node = (que_common_t*) node->brother; - } - - return(node); -} -/*********************************************************************//** -Gets the next list node in a list of query graph nodes. -@return next node in a list of nodes */ -UNIV_INLINE -que_node_t* -que_node_get_next( -/*==============*/ - que_node_t* node) /*!< in: node in a list */ -{ - return(((que_common_t*) node)->brother); -} - -/*********************************************************************//** -Gets a query graph node list length. -@return length, for NULL list 0 */ -UNIV_INLINE -ulint -que_node_list_get_len( -/*==================*/ - que_node_t* node_list) /*!< in: node list, or NULL */ -{ - const que_common_t* cnode; - ulint len; - - cnode = (const que_common_t*) node_list; - len = 0; - - while (cnode != NULL) { - len++; - cnode = (const que_common_t*) cnode->brother; - } - - return(len); -} - -/*********************************************************************//** -Gets the parent node of a query graph node. -@return parent node or NULL */ -UNIV_INLINE -que_node_t* -que_node_get_parent( -/*================*/ - que_node_t* node) /*!< in: node */ -{ - return(((que_common_t*) node)->parent); -} - -/**********************************************************************//** -Checks if graph, trx, or session is in a state where the query thread should -be stopped. -@return TRUE if should be stopped; NOTE that if the peek is made -without reserving the trx mutex, then another peek with the mutex -reserved is necessary before deciding the actual stopping */ -UNIV_INLINE -ibool -que_thr_peek_stop( -/*==============*/ - que_thr_t* thr) /*!< in: query thread */ -{ - trx_t* trx; - que_t* graph; - - graph = thr->graph; - trx = graph->trx; - - if (graph->state != QUE_FORK_ACTIVE - || trx->lock.que_state == TRX_QUE_LOCK_WAIT - || (trx->lock.que_state != TRX_QUE_ROLLING_BACK - && trx->lock.que_state != TRX_QUE_RUNNING)) { - - return(TRUE); - } - - return(FALSE); -} - -/***********************************************************************//** -Returns TRUE if the query graph is for a SELECT statement. -@return TRUE if a select */ -UNIV_INLINE -ibool -que_graph_is_select( -/*================*/ - que_t* graph) /*!< in: graph */ -{ - if (graph->fork_type == QUE_FORK_SELECT_SCROLL - || graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) { - - return(TRUE); - } - - return(FALSE); -} - diff --git a/storage/innobase/include/que0que.inl b/storage/innobase/include/que0que.inl new file mode 100644 index 00000000000..1c3ac242bf2 --- /dev/null +++ b/storage/innobase/include/que0que.inl @@ -0,0 +1,293 @@ +/***************************************************************************** + +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 +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/que0que.ic +Query graph + +Created 5/27/1996 Heikki Tuuri +*******************************************************/ + +/***********************************************************************//** +Gets the trx of a query thread. */ +UNIV_INLINE +trx_t* +thr_get_trx( +/*========*/ + que_thr_t* thr) /*!< in: query thread */ +{ + ut_ad(thr); + + return(thr->graph->trx); +} + +/***********************************************************************//** +Gets the first thr in a fork. */ +UNIV_INLINE +que_thr_t* +que_fork_get_first_thr( +/*===================*/ + que_fork_t* fork) /*!< in: query fork */ +{ + return(UT_LIST_GET_FIRST(fork->thrs)); +} + +/***********************************************************************//** +Gets the child node of the first thr in a fork. */ +UNIV_INLINE +que_node_t* +que_fork_get_child( +/*===============*/ + que_fork_t* fork) /*!< in: query fork */ +{ + que_thr_t* thr; + + thr = UT_LIST_GET_FIRST(fork->thrs); + + return(thr->child); +} + +/***********************************************************************//** +Gets the type of a graph node. */ +UNIV_INLINE +ulint +que_node_get_type( +/*==============*/ + const que_node_t* node) /*!< in: graph node */ +{ + return(reinterpret_cast(node)->type); +} + +/***********************************************************************//** +Gets pointer to the value dfield of a graph node. */ +UNIV_INLINE +dfield_t* +que_node_get_val( +/*=============*/ + que_node_t* node) /*!< in: graph node */ +{ + ut_ad(node); + + return(&(((que_common_t*) node)->val)); +} + +/***********************************************************************//** +Gets the value buffer size of a graph node. +@return val buffer size, not defined if val.data == NULL in node */ +UNIV_INLINE +ulint +que_node_get_val_buf_size( +/*======================*/ + que_node_t* node) /*!< in: graph node */ +{ + ut_ad(node); + + return(((que_common_t*) node)->val_buf_size); +} + +/***********************************************************************//** +Sets the value buffer size of a graph node. */ +UNIV_INLINE +void +que_node_set_val_buf_size( +/*======================*/ + que_node_t* node, /*!< in: graph node */ + ulint size) /*!< in: size */ +{ + ut_ad(node); + + ((que_common_t*) node)->val_buf_size = size; +} + +/***********************************************************************//** +Sets the parent of a graph node. */ +UNIV_INLINE +void +que_node_set_parent( +/*================*/ + que_node_t* node, /*!< in: graph node */ + que_node_t* parent) /*!< in: parent */ +{ + ut_ad(node); + + ((que_common_t*) node)->parent = parent; +} + +/***********************************************************************//** +Gets pointer to the value data type field of a graph node. */ +UNIV_INLINE +dtype_t* +que_node_get_data_type( +/*===================*/ + que_node_t* node) /*!< in: graph node */ +{ + ut_ad(node); + + return(dfield_get_type(&((que_common_t*) node)->val)); +} + +/*********************************************************************//** +Catenates a query graph node to a list of them, possible empty list. +@return one-way list of nodes */ +UNIV_INLINE +que_node_t* +que_node_list_add_last( +/*===================*/ + que_node_t* node_list, /*!< in: node list, or NULL */ + que_node_t* node) /*!< in: node */ +{ + que_common_t* cnode; + que_common_t* cnode2; + + cnode = (que_common_t*) node; + + cnode->brother = NULL; + + if (node_list == NULL) { + + return(node); + } + + cnode2 = (que_common_t*) node_list; + + while (cnode2->brother != NULL) { + cnode2 = (que_common_t*) cnode2->brother; + } + + cnode2->brother = node; + + return(node_list); +} + +/************************************************************************* +Removes a query graph node from the list.*/ +UNIV_INLINE +que_node_t* +que_node_list_get_last( +/*===================*/ + /* out: last node in list.*/ + que_node_t* node_list) /* in: node list */ +{ + que_common_t* node; + + ut_a(node_list != NULL); + + node = (que_common_t*) node_list; + + /* We need the last element */ + while (node->brother != NULL) { + node = (que_common_t*) node->brother; + } + + return(node); +} +/*********************************************************************//** +Gets the next list node in a list of query graph nodes. +@return next node in a list of nodes */ +UNIV_INLINE +que_node_t* +que_node_get_next( +/*==============*/ + que_node_t* node) /*!< in: node in a list */ +{ + return(((que_common_t*) node)->brother); +} + +/*********************************************************************//** +Gets a query graph node list length. +@return length, for NULL list 0 */ +UNIV_INLINE +ulint +que_node_list_get_len( +/*==================*/ + que_node_t* node_list) /*!< in: node list, or NULL */ +{ + const que_common_t* cnode; + ulint len; + + cnode = (const que_common_t*) node_list; + len = 0; + + while (cnode != NULL) { + len++; + cnode = (const que_common_t*) cnode->brother; + } + + return(len); +} + +/*********************************************************************//** +Gets the parent node of a query graph node. +@return parent node or NULL */ +UNIV_INLINE +que_node_t* +que_node_get_parent( +/*================*/ + que_node_t* node) /*!< in: node */ +{ + return(((que_common_t*) node)->parent); +} + +/**********************************************************************//** +Checks if graph, trx, or session is in a state where the query thread should +be stopped. +@return TRUE if should be stopped; NOTE that if the peek is made +without reserving the trx mutex, then another peek with the mutex +reserved is necessary before deciding the actual stopping */ +UNIV_INLINE +ibool +que_thr_peek_stop( +/*==============*/ + que_thr_t* thr) /*!< in: query thread */ +{ + trx_t* trx; + que_t* graph; + + graph = thr->graph; + trx = graph->trx; + + if (graph->state != QUE_FORK_ACTIVE + || trx->lock.que_state == TRX_QUE_LOCK_WAIT + || (trx->lock.que_state != TRX_QUE_ROLLING_BACK + && trx->lock.que_state != TRX_QUE_RUNNING)) { + + return(TRUE); + } + + return(FALSE); +} + +/***********************************************************************//** +Returns TRUE if the query graph is for a SELECT statement. +@return TRUE if a select */ +UNIV_INLINE +ibool +que_graph_is_select( +/*================*/ + que_t* graph) /*!< in: graph */ +{ + if (graph->fork_type == QUE_FORK_SELECT_SCROLL + || graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) { + + return(TRUE); + } + + return(FALSE); +} + diff --git a/storage/innobase/include/rem0cmp.h b/storage/innobase/include/rem0cmp.h index 65504d14416..43319e4c4d0 100644 --- a/storage/innobase/include/rem0cmp.h +++ b/storage/innobase/include/rem0cmp.h @@ -231,6 +231,6 @@ cmp_dfield_dfield_like_prefix( const dfield_t* dfield1, const dfield_t* dfield2); -#include "rem0cmp.ic" +#include "rem0cmp.inl" #endif diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic deleted file mode 100644 index 4230543615a..00000000000 --- a/storage/innobase/include/rem0cmp.ic +++ /dev/null @@ -1,108 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 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 -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/rem0cmp.ic -Comparison services for records - -Created 7/1/1994 Heikki Tuuri -************************************************************************/ - -#include -#include - -/** Compare two data fields. -@param[in] dfield1 data field; must have type field set -@param[in] dfield2 data field -@return the comparison result of dfield1 and dfield2 -@retval 0 if dfield1 is equal to dfield2 -@retval negative if dfield1 is less than dfield2 -@retval positive if dfield1 is greater than dfield2 */ -UNIV_INLINE -int -cmp_dfield_dfield( - const dfield_t* dfield1, - const dfield_t* dfield2) -{ - const dtype_t* type; - - ut_ad(dfield_check_typed(dfield1)); - - type = dfield_get_type(dfield1); - - return(cmp_data_data(type->mtype, type->prtype, - (const byte*) dfield_get_data(dfield1), - dfield_get_len(dfield1), - (const byte*) dfield_get_data(dfield2), - dfield_get_len(dfield2))); -} - -/** Compare two data fields. -@param[in] dfield1 data field -@param[in] dfield2 data field -@return the comparison result of dfield1 and dfield2 -@retval 0 if dfield1 is equal to dfield2, or a prefix of dfield1 -@retval negative if dfield1 is less than dfield2 -@retval positive if dfield1 is greater than dfield2 */ -UNIV_INLINE -int -cmp_dfield_dfield_like_prefix( - const dfield_t* dfield1, - const dfield_t* dfield2) -{ - const dtype_t* type; - - ut_ad(dfield_check_typed(dfield1)); - ut_ad(dfield_check_typed(dfield2)); - - type = dfield_get_type(dfield1); - -#ifdef UNIV_DEBUG - switch (type->prtype & DATA_MYSQL_TYPE_MASK) { - case MYSQL_TYPE_BIT: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_VARCHAR: - break; - default: - ut_error; - } -#endif /* UNIV_DEBUG */ - - uint cs_num = (uint) dtype_get_charset_coll(type->prtype); - - if (CHARSET_INFO* cs = get_charset(cs_num, MYF(MY_WME))) { - return(cs->coll->strnncoll( - cs, - static_cast( - dfield_get_data(dfield1)), - dfield_get_len(dfield1), - static_cast( - dfield_get_data(dfield2)), - dfield_get_len(dfield2), - 1)); - } - - ib::fatal() << "Unable to find charset-collation " << cs_num; - return(0); -} diff --git a/storage/innobase/include/rem0cmp.inl b/storage/innobase/include/rem0cmp.inl new file mode 100644 index 00000000000..4230543615a --- /dev/null +++ b/storage/innobase/include/rem0cmp.inl @@ -0,0 +1,108 @@ +/***************************************************************************** + +Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 +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/rem0cmp.ic +Comparison services for records + +Created 7/1/1994 Heikki Tuuri +************************************************************************/ + +#include +#include + +/** Compare two data fields. +@param[in] dfield1 data field; must have type field set +@param[in] dfield2 data field +@return the comparison result of dfield1 and dfield2 +@retval 0 if dfield1 is equal to dfield2 +@retval negative if dfield1 is less than dfield2 +@retval positive if dfield1 is greater than dfield2 */ +UNIV_INLINE +int +cmp_dfield_dfield( + const dfield_t* dfield1, + const dfield_t* dfield2) +{ + const dtype_t* type; + + ut_ad(dfield_check_typed(dfield1)); + + type = dfield_get_type(dfield1); + + return(cmp_data_data(type->mtype, type->prtype, + (const byte*) dfield_get_data(dfield1), + dfield_get_len(dfield1), + (const byte*) dfield_get_data(dfield2), + dfield_get_len(dfield2))); +} + +/** Compare two data fields. +@param[in] dfield1 data field +@param[in] dfield2 data field +@return the comparison result of dfield1 and dfield2 +@retval 0 if dfield1 is equal to dfield2, or a prefix of dfield1 +@retval negative if dfield1 is less than dfield2 +@retval positive if dfield1 is greater than dfield2 */ +UNIV_INLINE +int +cmp_dfield_dfield_like_prefix( + const dfield_t* dfield1, + const dfield_t* dfield2) +{ + const dtype_t* type; + + ut_ad(dfield_check_typed(dfield1)); + ut_ad(dfield_check_typed(dfield2)); + + type = dfield_get_type(dfield1); + +#ifdef UNIV_DEBUG + switch (type->prtype & DATA_MYSQL_TYPE_MASK) { + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_VARCHAR: + break; + default: + ut_error; + } +#endif /* UNIV_DEBUG */ + + uint cs_num = (uint) dtype_get_charset_coll(type->prtype); + + if (CHARSET_INFO* cs = get_charset(cs_num, MYF(MY_WME))) { + return(cs->coll->strnncoll( + cs, + static_cast( + dfield_get_data(dfield1)), + dfield_get_len(dfield1), + static_cast( + dfield_get_data(dfield2)), + dfield_get_len(dfield2), + 1)); + } + + ib::fatal() << "Unable to find charset-collation " << cs_num; + return(0); +} diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 81a09afa3d8..10317f04d3c 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -1177,7 +1177,7 @@ int wsrep_rec_get_foreign_key( ibool new_protocol); /* in: protocol > 1 */ #endif /* WITH_WSREP */ -#include "rem0rec.ic" +#include "rem0rec.inl" #endif /* !UNIV_INNOCHECKSUM */ #endif /* rem0rec_h */ diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic deleted file mode 100644 index f65bca8181d..00000000000 --- a/storage/innobase/include/rem0rec.ic +++ /dev/null @@ -1,1738 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. -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 -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/rem0rec.ic -Record manager - -Created 5/30/1994 Heikki Tuuri -*************************************************************************/ - -#include "mach0data.h" -#include "ut0byte.h" -#include "dict0dict.h" -#include "dict0boot.h" -#include "btr0types.h" - -/* Offsets of the bit-fields in an old-style record. NOTE! In the table the -most significant bytes and bits are written below less significant. - - (1) byte offset (2) bit usage within byte - downward from - origin -> 1 8 bits pointer to next record - 2 8 bits pointer to next record - 3 1 bit short flag - 7 bits number of fields - 4 3 bits number of fields - 5 bits heap number - 5 8 bits heap number - 6 4 bits n_owned - 4 bits info bits -*/ - -/* Offsets of the bit-fields in a new-style record. NOTE! In the table the -most significant bytes and bits are written below less significant. - - (1) byte offset (2) bit usage within byte - downward from - origin -> 1 8 bits relative offset of next record - 2 8 bits relative offset of next record - the relative offset is an unsigned 16-bit - integer: - (offset_of_next_record - - offset_of_this_record) mod 64Ki, - where mod is the modulo as a non-negative - number; - we can calculate the offset of the next - record with the formula: - relative_offset + offset_of_this_record - mod UNIV_PAGE_SIZE - 3 3 bits status: - 000=conventional record - 001=node pointer record (inside B-tree) - 010=infimum record - 011=supremum record - 1xx=reserved - 5 bits heap number - 4 8 bits heap number - 5 4 bits n_owned - 4 bits info bits -*/ - -/* We list the byte offsets from the origin of the record, the mask, -and the shift needed to obtain each bit-field of the record. */ - -#define REC_NEXT 2 -#define REC_NEXT_MASK 0xFFFFUL -#define REC_NEXT_SHIFT 0 - -#define REC_OLD_SHORT 3 /* This is single byte bit-field */ -#define REC_OLD_SHORT_MASK 0x1UL -#define REC_OLD_SHORT_SHIFT 0 - -#define REC_OLD_N_FIELDS 4 -#define REC_OLD_N_FIELDS_MASK 0x7FEUL -#define REC_OLD_N_FIELDS_SHIFT 1 - -#define REC_NEW_STATUS 3 /* This is single byte bit-field */ -#define REC_NEW_STATUS_MASK 0x7UL -#define REC_NEW_STATUS_SHIFT 0 - -#define REC_OLD_HEAP_NO 5 -#define REC_HEAP_NO_MASK 0xFFF8UL -#if 0 /* defined in rem0rec.h for use of page0zip.cc */ -#define REC_NEW_HEAP_NO 4 -#define REC_HEAP_NO_SHIFT 3 -#endif - -#define REC_OLD_N_OWNED 6 /* This is single byte bit-field */ -#define REC_NEW_N_OWNED 5 /* This is single byte bit-field */ -#define REC_N_OWNED_MASK 0xFUL -#define REC_N_OWNED_SHIFT 0 - -#define REC_OLD_INFO_BITS 6 /* This is single byte bit-field */ -#define REC_NEW_INFO_BITS 5 /* This is single byte bit-field */ -#define REC_INFO_BITS_MASK 0xF0UL -#define REC_INFO_BITS_SHIFT 0 - -#if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \ - ^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \ - ^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \ - ^ REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) \ - ^ REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) \ - ^ 0xFFFFFFFFUL -# error "sum of old-style masks != 0xFFFFFFFFUL" -#endif -#if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) \ - ^ REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) \ - ^ REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) \ - ^ REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) \ - ^ 0xFFFFFFUL -# error "sum of new-style masks != 0xFFFFFFUL" -#endif - -/***********************************************************//** -Sets the value of the ith field SQL null bit of an old-style record. */ -void -rec_set_nth_field_null_bit( -/*=======================*/ - rec_t* rec, /*!< in: record */ - ulint i, /*!< in: ith field */ - ibool val); /*!< in: value to set */ -/***********************************************************//** -Sets an old-style record field to SQL null. -The physical size of the field is not changed. */ -void -rec_set_nth_field_sql_null( -/*=======================*/ - rec_t* rec, /*!< in: record */ - ulint n); /*!< in: index of the field */ - -/******************************************************//** -Gets a bit field from within 1 byte. */ -UNIV_INLINE -ulint -rec_get_bit_field_1( -/*================*/ - const rec_t* rec, /*!< in: pointer to record origin */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - - return((mach_read_from_1(rec - offs) & mask) >> shift); -} - -/******************************************************//** -Sets a bit field within 1 byte. */ -UNIV_INLINE -void -rec_set_bit_field_1( -/*================*/ - rec_t* rec, /*!< in: pointer to record origin */ - ulint val, /*!< in: value to set */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - ut_ad(offs <= REC_N_OLD_EXTRA_BYTES); - ut_ad(mask); - ut_ad(mask <= 0xFFUL); - ut_ad(((mask >> shift) << shift) == mask); - ut_ad(((val << shift) & mask) == (val << shift)); - - mach_write_to_1(rec - offs, - (mach_read_from_1(rec - offs) & ~mask) - | (val << shift)); -} - -/******************************************************//** -Gets a bit field from within 2 bytes. */ -UNIV_INLINE -ulint -rec_get_bit_field_2( -/*================*/ - const rec_t* rec, /*!< in: pointer to record origin */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - - return((mach_read_from_2(rec - offs) & mask) >> shift); -} - -/******************************************************//** -Sets a bit field within 2 bytes. */ -UNIV_INLINE -void -rec_set_bit_field_2( -/*================*/ - rec_t* rec, /*!< in: pointer to record origin */ - ulint val, /*!< in: value to set */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - ut_ad(offs <= REC_N_OLD_EXTRA_BYTES); - ut_ad(mask > 0xFFUL); - ut_ad(mask <= 0xFFFFUL); - ut_ad((mask >> shift) & 1); - ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1))); - ut_ad(((mask >> shift) << shift) == mask); - ut_ad(((val << shift) & mask) == (val << shift)); - - mach_write_to_2(rec - offs, - (mach_read_from_2(rec - offs) & ~mask) - | (val << shift)); -} - -/******************************************************//** -The following function is used to get the pointer of the next chained record -on the same page. -@return pointer to the next chained record, or NULL if none */ -UNIV_INLINE -const rec_t* -rec_get_next_ptr_const( -/*===================*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - ulint field_value; - - ut_ad(REC_NEXT_MASK == 0xFFFFUL); - ut_ad(REC_NEXT_SHIFT == 0); - - field_value = mach_read_from_2(rec - REC_NEXT); - - if (field_value == 0) { - - return(NULL); - } - - if (comp) { -#if UNIV_PAGE_SIZE_MAX <= 32768 - /* Note that for 64 KiB pages, field_value can 'wrap around' - and the debug assertion is not valid */ - - /* In the following assertion, field_value is interpreted - as signed 16-bit integer in 2's complement arithmetics. - If all platforms defined int16_t in the standard headers, - the expression could be written simpler as - (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE - */ - ut_ad((field_value >= 32768 - ? field_value - 65536 - : field_value) - + ut_align_offset(rec, UNIV_PAGE_SIZE) - < UNIV_PAGE_SIZE); -#endif - /* There must be at least REC_N_NEW_EXTRA_BYTES + 1 - between each record. */ - ut_ad((field_value > REC_N_NEW_EXTRA_BYTES - && field_value < 32768) - || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES); - - return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE) - + ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); - } else { - ut_ad(field_value < UNIV_PAGE_SIZE); - - return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE) - + field_value); - } -} - -/******************************************************//** -The following function is used to get the pointer of the next chained record -on the same page. -@return pointer to the next chained record, or NULL if none */ -UNIV_INLINE -rec_t* -rec_get_next_ptr( -/*=============*/ - rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - return(const_cast(rec_get_next_ptr_const(rec, comp))); -} - -/******************************************************//** -The following function is used to get the offset of the next chained record -on the same page. -@return the page offset of the next chained record, or 0 if none */ -UNIV_INLINE -ulint -rec_get_next_offs( -/*==============*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - ulint field_value; -#if REC_NEXT_MASK != 0xFFFFUL -# error "REC_NEXT_MASK != 0xFFFFUL" -#endif -#if REC_NEXT_SHIFT -# error "REC_NEXT_SHIFT != 0" -#endif - - field_value = mach_read_from_2(rec - REC_NEXT); - - if (comp) { -#if UNIV_PAGE_SIZE_MAX <= 32768 - /* Note that for 64 KiB pages, field_value can 'wrap around' - and the debug assertion is not valid */ - - /* In the following assertion, field_value is interpreted - as signed 16-bit integer in 2's complement arithmetics. - If all platforms defined int16_t in the standard headers, - the expression could be written simpler as - (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE - */ - ut_ad((field_value >= 32768 - ? field_value - 65536 - : field_value) - + ut_align_offset(rec, UNIV_PAGE_SIZE) - < UNIV_PAGE_SIZE); -#endif - if (field_value == 0) { - - return(0); - } - - /* There must be at least REC_N_NEW_EXTRA_BYTES + 1 - between each record. */ - ut_ad((field_value > REC_N_NEW_EXTRA_BYTES - && field_value < 32768) - || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES); - - return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); - } else { - ut_ad(field_value < UNIV_PAGE_SIZE); - - return(field_value); - } -} - -/******************************************************//** -The following function is used to set the next record offset field -of an old-style record. */ -UNIV_INLINE -void -rec_set_next_offs_old( -/*==================*/ - rec_t* rec, /*!< in: old-style physical record */ - ulint next) /*!< in: offset of the next record */ -{ - ut_ad(srv_page_size > next); - compile_time_assert(REC_NEXT_MASK == 0xFFFFUL); - compile_time_assert(REC_NEXT_SHIFT == 0); - mach_write_to_2(rec - REC_NEXT, next); -} - -/******************************************************//** -The following function is used to set the next record offset field -of a new-style record. */ -UNIV_INLINE -void -rec_set_next_offs_new( -/*==================*/ - rec_t* rec, /*!< in/out: new-style physical record */ - ulint next) /*!< in: offset of the next record */ -{ - ulint field_value; - - ut_ad(srv_page_size > next); - - if (!next) { - field_value = 0; - } else { - /* The following two statements calculate - next - offset_of_rec mod 64Ki, where mod is the modulo - as a non-negative number */ - - field_value = (ulint) - ((lint) next - - (lint) ut_align_offset(rec, UNIV_PAGE_SIZE)); - field_value &= REC_NEXT_MASK; - } - - mach_write_to_2(rec - REC_NEXT, field_value); -} - -/******************************************************//** -The following function is used to get the number of fields -in an old-style record. -@return number of data fields */ -UNIV_INLINE -ulint -rec_get_n_fields_old( -/*=================*/ - const rec_t* rec) /*!< in: physical record */ -{ - ulint ret; - - ut_ad(rec); - - ret = rec_get_bit_field_2(rec, REC_OLD_N_FIELDS, - REC_OLD_N_FIELDS_MASK, - REC_OLD_N_FIELDS_SHIFT); - ut_ad(ret <= REC_MAX_N_FIELDS); - ut_ad(ret > 0); - - return(ret); -} - -/******************************************************//** -The following function is used to set the number of fields -in an old-style record. */ -UNIV_INLINE -void -rec_set_n_fields_old( -/*=================*/ - rec_t* rec, /*!< in: physical record */ - ulint n_fields) /*!< in: the number of fields */ -{ - ut_ad(rec); - ut_ad(n_fields <= REC_MAX_N_FIELDS); - ut_ad(n_fields > 0); - - rec_set_bit_field_2(rec, n_fields, REC_OLD_N_FIELDS, - REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT); -} - -/******************************************************//** -The following function retrieves the status bits of a new-style record. -@return status bits */ -UNIV_INLINE -ulint -rec_get_status( -/*===========*/ - const rec_t* rec) /*!< in: physical record */ -{ - ulint ret; - - ut_ad(rec); - - ret = rec_get_bit_field_1(rec, REC_NEW_STATUS, - REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT); - ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0); - - return(ret); -} - -/******************************************************//** -The following function is used to get the number of fields -in a record. -@return number of data fields */ -UNIV_INLINE -ulint -rec_get_n_fields( -/*=============*/ - const rec_t* rec, /*!< in: physical record */ - const dict_index_t* index) /*!< in: record descriptor */ -{ - ut_ad(rec); - ut_ad(index); - - if (!dict_table_is_comp(index->table)) { - return(rec_get_n_fields_old(rec)); - } - - switch (rec_get_status(rec)) { - case REC_STATUS_ORDINARY: - return(dict_index_get_n_fields(index)); - case REC_STATUS_NODE_PTR: - return(dict_index_get_n_unique_in_tree(index) + 1); - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - return(1); - default: - ut_error; - return(ULINT_UNDEFINED); - } -} - -/** Confirms the n_fields of the entry is sane with comparing the other -record in the same page specified -@param[in] index index -@param[in] rec record of the same page -@param[in] entry index entry -@return true if n_fields is sane */ -UNIV_INLINE -bool -rec_n_fields_is_sane( - dict_index_t* index, - const rec_t* rec, - const dtuple_t* entry) -{ - return(rec_get_n_fields(rec, index) - == dtuple_get_n_fields(entry) - /* a record for older SYS_INDEXES table - (missing merge_threshold column) is acceptable. */ - || (index->table->id == DICT_INDEXES_ID - && rec_get_n_fields(rec, index) - == dtuple_get_n_fields(entry) - 1)); -} - -/******************************************************//** -The following function is used to get the number of records owned by the -previous directory record. -@return number of owned records */ -UNIV_INLINE -ulint -rec_get_n_owned_old( -/*================*/ - const rec_t* rec) /*!< in: old-style physical record */ -{ - return(rec_get_bit_field_1(rec, REC_OLD_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT)); -} - -/******************************************************//** -The following function is used to set the number of owned records. */ -UNIV_INLINE -void -rec_set_n_owned_old( -/*================*/ - rec_t* rec, /*!< in: old-style physical record */ - ulint n_owned) /*!< in: the number of owned */ -{ - rec_set_bit_field_1(rec, n_owned, REC_OLD_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT); -} - -/******************************************************//** -The following function is used to get the number of records owned by the -previous directory record. -@return number of owned records */ -UNIV_INLINE -ulint -rec_get_n_owned_new( -/*================*/ - const rec_t* rec) /*!< in: new-style physical record */ -{ - return(rec_get_bit_field_1(rec, REC_NEW_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT)); -} - -/******************************************************//** -The following function is used to set the number of owned records. */ -UNIV_INLINE -void -rec_set_n_owned_new( -/*================*/ - rec_t* rec, /*!< in/out: new-style physical record */ - page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ - ulint n_owned)/*!< in: the number of owned */ -{ - rec_set_bit_field_1(rec, n_owned, REC_NEW_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT); - if (page_zip && rec_get_status(rec) != REC_STATUS_SUPREMUM) { - page_zip_rec_set_owned(page_zip, rec, n_owned); - } -} - -#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 */ -UNIV_INLINE -ulint -rec_get_info_bits( -/*==============*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - 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); -} - -/******************************************************//** -The following function is used to set the info bits of a record. */ -UNIV_INLINE -void -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); -} -/******************************************************//** -The following function is used to set the info bits of a record. */ -UNIV_INLINE -void -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); -} - -/******************************************************//** -The following function is used to set the status bits of a new-style record. */ -UNIV_INLINE -void -rec_set_status( -/*===========*/ - rec_t* rec, /*!< in/out: physical record */ - ulint bits) /*!< in: info bits */ -{ - rec_set_bit_field_1(rec, bits, REC_NEW_STATUS, - REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT); -} - -/******************************************************//** -The following function is used to retrieve the info and status -bits of a record. (Only compact records have status bits.) -@return info bits */ -UNIV_INLINE -ulint -rec_get_info_and_status_bits( -/*=========================*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - ulint bits; -#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ -& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) -# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" -#endif - if (comp) { - bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec); - } else { - bits = rec_get_info_bits(rec, FALSE); - ut_ad(!(bits & ~(REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT))); - } - return(bits); -} -/******************************************************//** -The following function is used to set the info and status -bits of a record. (Only compact records have status bits.) */ -UNIV_INLINE -void -rec_set_info_and_status_bits( -/*=========================*/ - rec_t* rec, /*!< in/out: physical record */ - ulint bits) /*!< in: info bits */ -{ -#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ -& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) -# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" -#endif - rec_set_status(rec, bits & REC_NEW_STATUS_MASK); - rec_set_info_bits_new(rec, bits & ~REC_NEW_STATUS_MASK); -} - -/******************************************************//** -The following function tells if record is delete marked. -@return nonzero if delete marked */ -UNIV_INLINE -ulint -rec_get_deleted_flag( -/*=================*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - if (comp) { - return(rec_get_bit_field_1(rec, REC_NEW_INFO_BITS, - REC_INFO_DELETED_FLAG, - REC_INFO_BITS_SHIFT)); - } else { - return(rec_get_bit_field_1(rec, REC_OLD_INFO_BITS, - REC_INFO_DELETED_FLAG, - REC_INFO_BITS_SHIFT)); - } -} - -/******************************************************//** -The following function is used to set the deleted bit. */ -UNIV_INLINE -void -rec_set_deleted_flag_old( -/*=====================*/ - rec_t* rec, /*!< in: old-style physical record */ - ulint flag) /*!< in: nonzero if delete marked */ -{ - ulint val; - - val = rec_get_info_bits(rec, FALSE); - - if (flag) { - val |= REC_INFO_DELETED_FLAG; - } else { - val &= ~REC_INFO_DELETED_FLAG; - } - - rec_set_info_bits_old(rec, val); -} - -/******************************************************//** -The following function is used to set the deleted bit. */ -UNIV_INLINE -void -rec_set_deleted_flag_new( -/*=====================*/ - rec_t* rec, /*!< in/out: new-style physical record */ - page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ - ulint flag) /*!< in: nonzero if delete marked */ -{ - ulint val; - - val = rec_get_info_bits(rec, TRUE); - - if (flag) { - val |= REC_INFO_DELETED_FLAG; - } else { - val &= ~REC_INFO_DELETED_FLAG; - } - - rec_set_info_bits_new(rec, val); - - if (page_zip) { - page_zip_rec_set_deleted(page_zip, rec, flag); - } -} - -/******************************************************//** -The following function tells if a new-style record is a node pointer. -@return TRUE if node pointer */ -UNIV_INLINE -ibool -rec_get_node_ptr_flag( -/*==================*/ - const rec_t* rec) /*!< in: physical record */ -{ - return(REC_STATUS_NODE_PTR == rec_get_status(rec)); -} - -/******************************************************//** -The following function is used to get the order number -of an old-style record in the heap of the index page. -@return heap order number */ -UNIV_INLINE -ulint -rec_get_heap_no_old( -/*================*/ - const rec_t* rec) /*!< in: physical record */ -{ - return(rec_get_bit_field_2(rec, REC_OLD_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT)); -} - -/******************************************************//** -The following function is used to set the heap number -field in an old-style record. */ -UNIV_INLINE -void -rec_set_heap_no_old( -/*================*/ - rec_t* rec, /*!< in: physical record */ - ulint heap_no)/*!< in: the heap number */ -{ - rec_set_bit_field_2(rec, heap_no, REC_OLD_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT); -} - -/******************************************************//** -The following function is used to get the order number -of a new-style record in the heap of the index page. -@return heap order number */ -UNIV_INLINE -ulint -rec_get_heap_no_new( -/*================*/ - const rec_t* rec) /*!< in: physical record */ -{ - return(rec_get_bit_field_2(rec, REC_NEW_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT)); -} - -/******************************************************//** -The following function is used to set the heap number -field in a new-style record. */ -UNIV_INLINE -void -rec_set_heap_no_new( -/*================*/ - rec_t* rec, /*!< in/out: physical record */ - ulint heap_no)/*!< in: the heap number */ -{ - rec_set_bit_field_2(rec, heap_no, REC_NEW_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT); -} - -/******************************************************//** -The following function is used to test whether the data offsets in the record -are stored in one-byte or two-byte format. -@return TRUE if 1-byte form */ -UNIV_INLINE -ibool -rec_get_1byte_offs_flag( -/*====================*/ - const rec_t* rec) /*!< in: physical record */ -{ -#if TRUE != 1 -#error "TRUE != 1" -#endif - - return(rec_get_bit_field_1(rec, REC_OLD_SHORT, REC_OLD_SHORT_MASK, - REC_OLD_SHORT_SHIFT)); -} - -/******************************************************//** -The following function is used to set the 1-byte offsets flag. */ -UNIV_INLINE -void -rec_set_1byte_offs_flag( -/*====================*/ - rec_t* rec, /*!< in: physical record */ - ibool flag) /*!< in: TRUE if 1byte form */ -{ -#if TRUE != 1 -#error "TRUE != 1" -#endif - ut_ad(flag <= TRUE); - - rec_set_bit_field_1(rec, flag, REC_OLD_SHORT, REC_OLD_SHORT_MASK, - REC_OLD_SHORT_SHIFT); -} - -/******************************************************//** -Returns the offset of nth field end if the record is stored in the 1-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. -@return offset of the start of the field, SQL null flag ORed */ -UNIV_INLINE -uint8_t -rec_1_get_field_end_info( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1))); -} - -/******************************************************//** -Returns the offset of nth field end if the record is stored in the 2-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. -@return offset of the start of the field, SQL null flag and extern -storage flag ORed */ -UNIV_INLINE -rec_offs -rec_2_get_field_end_info( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2))); -} - -/******************************************************//** -Returns nonzero if the field is stored off-page. -@retval 0 if the field is stored in-page -@retval REC_2BYTE_EXTERN_MASK if the field is stored externally */ -UNIV_INLINE -ulint -rec_2_is_field_extern( -/*==================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - return(rec_2_get_field_end_info(rec, n) & REC_2BYTE_EXTERN_MASK); -} - -/* Get the base address of offsets. The extra_size is stored at -this position, and following positions hold the end offsets of -the fields. */ -#define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE) - -/**********************************************************//** -The following function returns the number of allocated elements -for an array of offsets. -@return number of elements */ -UNIV_INLINE -ulint -rec_offs_get_n_alloc( -/*=================*/ - const rec_offs* offsets)/*!< in: array for rec_get_offsets() */ -{ - ulint n_alloc; - ut_ad(offsets); - n_alloc = offsets[0]; - ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - MEM_CHECK_ADDRESSABLE(offsets, n_alloc * sizeof *offsets); - return(n_alloc); -} - -/**********************************************************//** -The following function sets the number of allocated elements -for an array of offsets. */ -UNIV_INLINE -void -rec_offs_set_n_alloc( -/*=================*/ - rec_offs*offsets, /*!< out: array for rec_get_offsets(), - must be allocated */ - ulint n_alloc) /*!< in: number of elements */ -{ - ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - MEM_UNDEFINED(offsets, n_alloc * sizeof *offsets); - offsets[0] = static_cast(n_alloc); -} - -/**********************************************************//** -The following function returns the number of fields in a record. -@return number of fields */ -UNIV_INLINE -ulint -rec_offs_n_fields( -/*==============*/ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint n_fields; - ut_ad(offsets); - n_fields = offsets[1]; - ut_ad(n_fields > 0); - ut_ad(n_fields <= REC_MAX_N_FIELDS); - ut_ad(n_fields + REC_OFFS_HEADER_SIZE - <= rec_offs_get_n_alloc(offsets)); - return(n_fields); -} - -/************************************************************//** -Validates offsets returned by rec_get_offsets(). -@return TRUE if valid */ -UNIV_INLINE -ibool -rec_offs_validate( -/*==============*/ - const rec_t* rec, /*!< in: record or NULL */ - const dict_index_t* index, /*!< in: record descriptor or NULL */ - const rec_offs* offsets)/*!< in: array returned by - rec_get_offsets() */ -{ - ulint i = rec_offs_n_fields(offsets); - ulint last = ULINT_MAX; - bool comp = rec_offs_base(offsets)[0] & REC_OFFS_COMPACT; - - if (rec) { - ut_ad(!memcmp(&rec, &offsets[RECORD_OFFSET], sizeof(rec))); - if (!comp) { - ut_a(rec_get_n_fields_old(rec) >= i); - } - } - if (index) { - ulint max_n_fields; - ut_ad(!memcmp(&index, &offsets[INDEX_OFFSET], sizeof(index))); - max_n_fields = ut_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_ORDINARY: - break; - case REC_STATUS_NODE_PTR: - max_n_fields = dict_index_get_n_unique_in_tree( - index) + 1; - break; - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - max_n_fields = 1; - break; - default: - ut_error; - } - } - /* index->n_def == 0 for dummy indexes if !comp */ - ut_a(!comp || index->n_def); - ut_a(!index->n_def || i <= max_n_fields); - } - while (i--) { - rec_offs curr = get_value(rec_offs_base(offsets)[1 + i]); - ut_a(curr <= last); - last = curr; - } - return(TRUE); -} -#ifdef UNIV_DEBUG -/************************************************************//** -Updates debug data in offsets, in order to avoid bogus -rec_offs_validate() failures. */ -UNIV_INLINE -void -rec_offs_make_valid( -/*================*/ - const rec_t* rec, /*!< in: record */ - const dict_index_t* index, /*!< in: record descriptor */ - rec_offs* offsets)/*!< in: array returned by - rec_get_offsets() */ -{ - ut_ad(rec); - ut_ad(index); - ut_ad(offsets); - ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets)); - memcpy(&offsets[RECORD_OFFSET], &rec, sizeof(rec)); - memcpy(&offsets[INDEX_OFFSET], &index, sizeof(index)); -} -#endif /* UNIV_DEBUG */ - -/************************************************************//** -The following function is used to get an offset to the nth -data field in a record. -@return offset from the origin of rec */ -UNIV_INLINE -rec_offs -rec_get_nth_field_offs( -/*===================*/ - const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n, /*!< in: index of the field */ - ulint* len) /*!< out: length of the field; UNIV_SQL_NULL - if SQL null */ -{ - ut_ad(n < rec_offs_n_fields(offsets)); - - rec_offs offs = n == 0 ? 0 : get_value(rec_offs_base(offsets)[n]); - rec_offs next_offs = rec_offs_base(offsets)[1 + n]; - - if (get_type(next_offs) == SQL_NULL) { - *len = UNIV_SQL_NULL; - } else { - - *len = get_value(next_offs) - offs; - } - - return(offs); -} - -/******************************************************//** -Determine if the offsets are for a record in the new -compact format. -@return nonzero if compact format */ -UNIV_INLINE -ulint -rec_offs_comp( -/*==========*/ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - return(*rec_offs_base(offsets) & REC_OFFS_COMPACT); -} - -/******************************************************//** -Determine if the offsets are for a record containing -externally stored columns. -@return nonzero if externally stored */ -UNIV_INLINE -ulint -rec_offs_any_extern( -/*================*/ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - return(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL); -} - -/******************************************************//** -Determine if the offsets are for a record containing null BLOB pointers. -@return first field containing a null BLOB pointer, or NULL if none found */ -UNIV_INLINE -const byte* -rec_offs_any_null_extern( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - const rec_offs* offsets) /*!< in: rec_get_offsets(rec) */ -{ - ulint i; - ut_ad(rec_offs_validate(rec, NULL, offsets)); - - if (!rec_offs_any_extern(offsets)) { - return(NULL); - } - - for (i = 0; i < rec_offs_n_fields(offsets); i++) { - if (rec_offs_nth_extern(offsets, i)) { - ulint len; - const byte* field - = rec_get_nth_field(rec, offsets, i, &len); - - ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); - if (!memcmp(field + len - - BTR_EXTERN_FIELD_REF_SIZE, - field_ref_zero, - BTR_EXTERN_FIELD_REF_SIZE)) { - return(field); - } - } - } - - return(NULL); -} - -/******************************************************//** -Returns nonzero if the extern bit is set in nth field of rec. -@return nonzero if externally stored */ -UNIV_INLINE -ulint -rec_offs_nth_extern( -/*================*/ - const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n) /*!< in: nth field */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - ut_ad(n < rec_offs_n_fields(offsets)); - return get_type(rec_offs_base(offsets)[1 + n]) == STORED_OFFPAGE; -} - -/******************************************************//** -Returns nonzero if the SQL NULL bit is set in nth field of rec. -@return nonzero if SQL NULL */ -UNIV_INLINE -ulint -rec_offs_nth_sql_null( -/*==================*/ - const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n) /*!< in: nth field */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - ut_ad(n < rec_offs_n_fields(offsets)); - return get_type(rec_offs_base(offsets)[1 + n]) == SQL_NULL; -} - -/******************************************************//** -Gets the physical size of a field. -@return length of field */ -UNIV_INLINE -ulint -rec_offs_nth_size( -/*==============*/ - const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n) /*!< in: nth field */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - ut_ad(n < rec_offs_n_fields(offsets)); - if (!n) { - return get_value(rec_offs_base(offsets)[1 + n]); - } - return get_value((rec_offs_base(offsets)[1 + n])) - - get_value(rec_offs_base(offsets)[n]); -} - -/******************************************************//** -Returns the number of extern bits set in a record. -@return number of externally stored fields */ -UNIV_INLINE -ulint -rec_offs_n_extern( -/*==============*/ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint n = 0; - - if (rec_offs_any_extern(offsets)) { - ulint i; - - for (i = rec_offs_n_fields(offsets); i--; ) { - if (rec_offs_nth_extern(offsets, i)) { - n++; - } - } - } - - return(n); -} - -/******************************************************//** -Returns the offset of n - 1th field end if the record is stored in the 1-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. This function and the 2-byte counterpart are defined here because the -C-compiler was not able to sum negative and positive constant offsets, and -warned of constant arithmetic overflow within the compiler. -@return offset of the start of the PREVIOUS field, SQL null flag ORed */ -UNIV_INLINE -ulint -rec_1_get_prev_field_end_info( -/*==========================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n))); -} - -/******************************************************//** -Returns the offset of n - 1th field end if the record is stored in the 2-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. -@return offset of the start of the PREVIOUS field, SQL null flag ORed */ -UNIV_INLINE -ulint -rec_2_get_prev_field_end_info( -/*==========================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n))); -} - -/******************************************************//** -Sets the field end info for the nth field if the record is stored in the -1-byte format. */ -UNIV_INLINE -void -rec_1_set_field_end_info( -/*=====================*/ - rec_t* rec, /*!< in: record */ - ulint n, /*!< in: field index */ - ulint info) /*!< in: value to set */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1), info); -} - -/******************************************************//** -Sets the field end info for the nth field if the record is stored in the -2-byte format. */ -UNIV_INLINE -void -rec_2_set_field_end_info( -/*=====================*/ - rec_t* rec, /*!< in: record */ - ulint n, /*!< in: field index */ - ulint info) /*!< in: value to set */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2), info); -} - -/******************************************************//** -Returns the offset of nth field start if the record is stored in the 1-byte -offsets form. -@return offset of the start of the field */ -UNIV_INLINE -ulint -rec_1_get_field_start_offs( -/*=======================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - if (n == 0) { - - return(0); - } - - return(rec_1_get_prev_field_end_info(rec, n) - & ~REC_1BYTE_SQL_NULL_MASK); -} - -/******************************************************//** -Returns the offset of nth field start if the record is stored in the 2-byte -offsets form. -@return offset of the start of the field */ -UNIV_INLINE -ulint -rec_2_get_field_start_offs( -/*=======================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - if (n == 0) { - - return(0); - } - - return(rec_2_get_prev_field_end_info(rec, n) - & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK)); -} - -/******************************************************//** -The following function is used to read the offset of the start of a data field -in the record. The start of an SQL null field is the end offset of the -previous non-null field, or 0, if none exists. If n is the number of the last -field + 1, then the end offset of the last field is returned. -@return offset of the start of the field */ -UNIV_INLINE -ulint -rec_get_field_start_offs( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec); - ut_ad(n <= rec_get_n_fields_old(rec)); - - if (n == 0) { - - return(0); - } - - if (rec_get_1byte_offs_flag(rec)) { - - return(rec_1_get_field_start_offs(rec, n)); - } - - return(rec_2_get_field_start_offs(rec, n)); -} - -/************************************************************//** -Gets the physical size of an old-style field. -Also an SQL null may have a field of size > 0, -if the data type is of a fixed size. -@return field size in bytes */ -UNIV_INLINE -ulint -rec_get_nth_field_size( -/*===================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: index of the field */ -{ - ulint os; - ulint next_os; - - os = rec_get_field_start_offs(rec, n); - next_os = rec_get_field_start_offs(rec, n + 1); - - ut_ad(next_os - os < UNIV_PAGE_SIZE); - - return(next_os - os); -} - -/***********************************************************//** -This is used to modify the value of an already existing field in a record. -The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null. -For records in ROW_FORMAT=COMPACT (new-style records), len must not be -UNIV_SQL_NULL unless the field already is SQL null. */ -UNIV_INLINE -void -rec_set_nth_field( -/*==============*/ - rec_t* rec, /*!< in: record */ - const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n, /*!< in: index number of the field */ - const void* data, /*!< in: pointer to the data - if not SQL null */ - ulint len) /*!< in: length of the data or UNIV_SQL_NULL */ -{ - byte* data2; - ulint len2; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - - if (len == UNIV_SQL_NULL) { - if (!rec_offs_nth_sql_null(offsets, n)) { - ut_a(!rec_offs_comp(offsets)); - rec_set_nth_field_sql_null(rec, n); - } - - return; - } - - data2 = rec_get_nth_field(rec, offsets, n, &len2); - if (len2 == UNIV_SQL_NULL) { - ut_ad(!rec_offs_comp(offsets)); - rec_set_nth_field_null_bit(rec, n, FALSE); - ut_ad(len == rec_get_nth_field_size(rec, n)); - } else { - ut_ad(len2 == len); - } - - ut_memcpy(data2, data, len); -} - -/**********************************************************//** -The following function returns the data size of an old-style physical -record, that is the sum of field lengths. SQL null fields -are counted as length 0 fields. The value returned by the function -is the distance from record origin to record end in bytes. -@return size */ -UNIV_INLINE -ulint -rec_get_data_size_old( -/*==================*/ - const rec_t* rec) /*!< in: physical record */ -{ - ut_ad(rec); - - return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec))); -} - -/**********************************************************//** -The following function sets the number of fields in offsets. */ -UNIV_INLINE -void -rec_offs_set_n_fields( -/*==================*/ - rec_offs* offsets, /*!< in/out: array returned by - rec_get_offsets() */ - ulint n_fields) /*!< in: number of fields */ -{ - ut_ad(offsets); - ut_ad(n_fields > 0); - ut_ad(n_fields <= REC_MAX_N_FIELDS); - ut_ad(n_fields + REC_OFFS_HEADER_SIZE - <= rec_offs_get_n_alloc(offsets)); - offsets[1] = static_cast(n_fields); -} - -/**********************************************************//** -The following function returns the data size of a physical -record, that is the sum of field lengths. SQL null fields -are counted as length 0 fields. The value returned by the function -is the distance from record origin to record end in bytes. -@return size */ -UNIV_INLINE -ulint -rec_offs_data_size( -/*===============*/ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint size; - - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - size = get_value(rec_offs_base(offsets)[rec_offs_n_fields(offsets)]); - ut_ad(size < UNIV_PAGE_SIZE); - return(size); -} - -/**********************************************************//** -Returns the total size of record minus data size of record. The value -returned by the function is the distance from record start to record origin -in bytes. -@return size */ -UNIV_INLINE -ulint -rec_offs_extra_size( -/*================*/ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint size; - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - size = *rec_offs_base(offsets) & ~(REC_OFFS_COMPACT | REC_OFFS_EXTERNAL); - ut_ad(size < UNIV_PAGE_SIZE); - return(size); -} - -/**********************************************************//** -Returns the total size of a physical record. -@return size */ -UNIV_INLINE -ulint -rec_offs_size( -/*==========*/ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets)); -} - -#ifdef UNIV_DEBUG -/**********************************************************//** -Returns a pointer to the end of the record. -@return pointer to end */ -UNIV_INLINE -byte* -rec_get_end( -/*========*/ - const rec_t* rec, /*!< in: pointer to record */ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(rec, NULL, offsets)); - return(const_cast(rec + rec_offs_data_size(offsets))); -} - -/**********************************************************//** -Returns a pointer to the start of the record. -@return pointer to start */ -UNIV_INLINE -byte* -rec_get_start( -/*==========*/ - const rec_t* rec, /*!< in: pointer to record */ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(rec, NULL, offsets)); - return(const_cast(rec - rec_offs_extra_size(offsets))); -} -#endif /* UNIV_DEBUG */ - -/** Copy a physical record to a buffer. -@param[in] buf buffer -@param[in] rec physical record -@param[in] offsets array returned by rec_get_offsets() -@return pointer to the origin of the copy */ -UNIV_INLINE -rec_t* -rec_copy( - void* buf, - const rec_t* rec, - const rec_offs* offsets) -{ - ulint extra_len; - ulint data_len; - - ut_ad(rec != NULL); - ut_ad(buf != NULL); - ut_ad(rec_offs_validate(rec, NULL, offsets)); - ut_ad(rec_validate(rec, offsets)); - - extra_len = rec_offs_extra_size(offsets); - data_len = rec_offs_data_size(offsets); - - ut_memcpy(buf, rec - extra_len, extra_len + data_len); - - return((byte*) buf + extra_len); -} - -/**********************************************************//** -Returns the extra size of an old-style physical record if we know its -data size and number of fields. -@return extra size */ -UNIV_INLINE -ulint -rec_get_converted_extra_size( -/*=========================*/ - ulint data_size, /*!< in: data size */ - ulint n_fields, /*!< in: number of fields */ - ulint n_ext) /*!< in: number of externally stored columns */ -{ - if (!n_ext && data_size <= REC_1BYTE_OFFS_LIMIT) { - - return(REC_N_OLD_EXTRA_BYTES + n_fields); - } - - return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields); -} - -/**********************************************************//** -The following function returns the size of a data tuple when converted to -a physical record. -@return size */ -UNIV_INLINE -ulint -rec_get_converted_size( -/*===================*/ - dict_index_t* index, /*!< in: record descriptor */ - const dtuple_t* dtuple, /*!< in: data tuple */ - ulint n_ext) /*!< in: number of externally stored columns */ -{ - ulint data_size; - ulint extra_size; - - ut_ad(dtuple_check_typed(dtuple)); - - ut_ad(dict_index_is_ibuf(index) - - || dtuple_get_n_fields(dtuple) - == (((dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) - == REC_STATUS_NODE_PTR) - ? dict_index_get_n_unique_in_tree_nonleaf(index) + 1 - : dict_index_get_n_fields(index)) - - /* a record for older SYS_INDEXES table - (missing merge_threshold column) is acceptable. */ - || (index->table->id == DICT_INDEXES_ID - && dtuple_get_n_fields(dtuple) - == dict_index_get_n_fields(index) - 1)); - - if (dict_table_is_comp(index->table)) { - return(rec_get_converted_size_comp(index, - dtuple_get_info_bits(dtuple) - & REC_NEW_STATUS_MASK, - dtuple->fields, - dtuple->n_fields, NULL)); - } - - data_size = dtuple_get_data_size(dtuple, 0); - - /* If primary key is being updated then the new record inherits - externally stored fields from the delete-marked old record. - In that case, n_ext may be less value than - dtuple_get_n_ext(tuple). */ - ut_ad(n_ext <= dtuple_get_n_ext(dtuple)); - extra_size = rec_get_converted_extra_size( - data_size, dtuple_get_n_fields(dtuple), n_ext); - -#if 0 - /* This code is inactive since it may be the wrong place to add - in the size of node pointers used in parent pages AND it is not - currently needed since ha_innobase::max_supported_key_length() - ensures that the key size limit for each page size is well below - the actual limit ((free space on page / 4) - record overhead). - But those limits will need to be raised when InnoDB can - support multiple page sizes. At that time, we will need - to consider the node pointer on these universal btrees. */ - - if (dict_index_is_ibuf(index)) { - /* This is for the insert buffer B-tree. - All fields in the leaf tuple ascend to the - parent node plus the child page pointer. */ - - /* ibuf cannot contain externally stored fields */ - ut_ad(n_ext == 0); - - /* Add the data pointer and recompute extra_size - based on one more field. */ - data_size += REC_NODE_PTR_SIZE; - extra_size = rec_get_converted_extra_size( - data_size, - dtuple_get_n_fields(dtuple) + 1, - 0); - - /* Be sure dtuple->n_fields has this node ptr - accounted for. This function should correspond to - what rec_convert_dtuple_to_rec() needs in storage. - In optimistic insert or update-not-in-place, we will - have to ensure that if the record is converted to a - node pointer, it will not become too large.*/ - } -#endif - - return(data_size + extra_size); -} - -/** Fold a prefix of a physical record. -@param[in] rec index record -@param[in] offsets return value of rec_get_offsets() -@param[in] n_fields number of complete fields to fold -@param[in] n_bytes number of bytes to fold in the last field -@param[in] index_id index tree ID -@return the folded value */ -UNIV_INLINE -ulint -rec_fold( - const rec_t* rec, - const rec_offs* offsets, - ulint n_fields, - ulint n_bytes, - index_id_t tree_id) -{ - ulint i; - const byte* data; - ulint len; - ulint fold; - ulint n_fields_rec; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - ut_ad(rec_validate(rec, offsets)); - ut_ad(n_fields > 0 || n_bytes > 0); - - n_fields_rec = rec_offs_n_fields(offsets); - ut_ad(n_fields <= n_fields_rec); - ut_ad(n_fields < n_fields_rec || n_bytes == 0); - - if (n_fields > n_fields_rec) { - n_fields = n_fields_rec; - } - - if (n_fields == n_fields_rec) { - n_bytes = 0; - } - - fold = ut_fold_ull(tree_id); - - for (i = 0; i < n_fields; i++) { - data = rec_get_nth_field(rec, offsets, i, &len); - - if (len != UNIV_SQL_NULL) { - fold = ut_fold_ulint_pair(fold, - ut_fold_binary(data, len)); - } - } - - if (n_bytes > 0) { - data = rec_get_nth_field(rec, offsets, i, &len); - - if (len != UNIV_SQL_NULL) { - if (len > n_bytes) { - len = n_bytes; - } - - fold = ut_fold_ulint_pair(fold, - ut_fold_binary(data, len)); - } - } - - return(fold); -} diff --git a/storage/innobase/include/rem0rec.inl b/storage/innobase/include/rem0rec.inl new file mode 100644 index 00000000000..f65bca8181d --- /dev/null +++ b/storage/innobase/include/rem0rec.inl @@ -0,0 +1,1738 @@ +/***************************************************************************** + +Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. +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 +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/rem0rec.ic +Record manager + +Created 5/30/1994 Heikki Tuuri +*************************************************************************/ + +#include "mach0data.h" +#include "ut0byte.h" +#include "dict0dict.h" +#include "dict0boot.h" +#include "btr0types.h" + +/* Offsets of the bit-fields in an old-style record. NOTE! In the table the +most significant bytes and bits are written below less significant. + + (1) byte offset (2) bit usage within byte + downward from + origin -> 1 8 bits pointer to next record + 2 8 bits pointer to next record + 3 1 bit short flag + 7 bits number of fields + 4 3 bits number of fields + 5 bits heap number + 5 8 bits heap number + 6 4 bits n_owned + 4 bits info bits +*/ + +/* Offsets of the bit-fields in a new-style record. NOTE! In the table the +most significant bytes and bits are written below less significant. + + (1) byte offset (2) bit usage within byte + downward from + origin -> 1 8 bits relative offset of next record + 2 8 bits relative offset of next record + the relative offset is an unsigned 16-bit + integer: + (offset_of_next_record + - offset_of_this_record) mod 64Ki, + where mod is the modulo as a non-negative + number; + we can calculate the offset of the next + record with the formula: + relative_offset + offset_of_this_record + mod UNIV_PAGE_SIZE + 3 3 bits status: + 000=conventional record + 001=node pointer record (inside B-tree) + 010=infimum record + 011=supremum record + 1xx=reserved + 5 bits heap number + 4 8 bits heap number + 5 4 bits n_owned + 4 bits info bits +*/ + +/* We list the byte offsets from the origin of the record, the mask, +and the shift needed to obtain each bit-field of the record. */ + +#define REC_NEXT 2 +#define REC_NEXT_MASK 0xFFFFUL +#define REC_NEXT_SHIFT 0 + +#define REC_OLD_SHORT 3 /* This is single byte bit-field */ +#define REC_OLD_SHORT_MASK 0x1UL +#define REC_OLD_SHORT_SHIFT 0 + +#define REC_OLD_N_FIELDS 4 +#define REC_OLD_N_FIELDS_MASK 0x7FEUL +#define REC_OLD_N_FIELDS_SHIFT 1 + +#define REC_NEW_STATUS 3 /* This is single byte bit-field */ +#define REC_NEW_STATUS_MASK 0x7UL +#define REC_NEW_STATUS_SHIFT 0 + +#define REC_OLD_HEAP_NO 5 +#define REC_HEAP_NO_MASK 0xFFF8UL +#if 0 /* defined in rem0rec.h for use of page0zip.cc */ +#define REC_NEW_HEAP_NO 4 +#define REC_HEAP_NO_SHIFT 3 +#endif + +#define REC_OLD_N_OWNED 6 /* This is single byte bit-field */ +#define REC_NEW_N_OWNED 5 /* This is single byte bit-field */ +#define REC_N_OWNED_MASK 0xFUL +#define REC_N_OWNED_SHIFT 0 + +#define REC_OLD_INFO_BITS 6 /* This is single byte bit-field */ +#define REC_NEW_INFO_BITS 5 /* This is single byte bit-field */ +#define REC_INFO_BITS_MASK 0xF0UL +#define REC_INFO_BITS_SHIFT 0 + +#if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \ + ^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \ + ^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \ + ^ REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) \ + ^ REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) \ + ^ 0xFFFFFFFFUL +# error "sum of old-style masks != 0xFFFFFFFFUL" +#endif +#if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) \ + ^ REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) \ + ^ REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) \ + ^ REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) \ + ^ 0xFFFFFFUL +# error "sum of new-style masks != 0xFFFFFFUL" +#endif + +/***********************************************************//** +Sets the value of the ith field SQL null bit of an old-style record. */ +void +rec_set_nth_field_null_bit( +/*=======================*/ + rec_t* rec, /*!< in: record */ + ulint i, /*!< in: ith field */ + ibool val); /*!< in: value to set */ +/***********************************************************//** +Sets an old-style record field to SQL null. +The physical size of the field is not changed. */ +void +rec_set_nth_field_sql_null( +/*=======================*/ + rec_t* rec, /*!< in: record */ + ulint n); /*!< in: index of the field */ + +/******************************************************//** +Gets a bit field from within 1 byte. */ +UNIV_INLINE +ulint +rec_get_bit_field_1( +/*================*/ + const rec_t* rec, /*!< in: pointer to record origin */ + ulint offs, /*!< in: offset from the origin down */ + ulint mask, /*!< in: mask used to filter bits */ + ulint shift) /*!< in: shift right applied after masking */ +{ + ut_ad(rec); + + return((mach_read_from_1(rec - offs) & mask) >> shift); +} + +/******************************************************//** +Sets a bit field within 1 byte. */ +UNIV_INLINE +void +rec_set_bit_field_1( +/*================*/ + rec_t* rec, /*!< in: pointer to record origin */ + ulint val, /*!< in: value to set */ + ulint offs, /*!< in: offset from the origin down */ + ulint mask, /*!< in: mask used to filter bits */ + ulint shift) /*!< in: shift right applied after masking */ +{ + ut_ad(rec); + ut_ad(offs <= REC_N_OLD_EXTRA_BYTES); + ut_ad(mask); + ut_ad(mask <= 0xFFUL); + ut_ad(((mask >> shift) << shift) == mask); + ut_ad(((val << shift) & mask) == (val << shift)); + + mach_write_to_1(rec - offs, + (mach_read_from_1(rec - offs) & ~mask) + | (val << shift)); +} + +/******************************************************//** +Gets a bit field from within 2 bytes. */ +UNIV_INLINE +ulint +rec_get_bit_field_2( +/*================*/ + const rec_t* rec, /*!< in: pointer to record origin */ + ulint offs, /*!< in: offset from the origin down */ + ulint mask, /*!< in: mask used to filter bits */ + ulint shift) /*!< in: shift right applied after masking */ +{ + ut_ad(rec); + + return((mach_read_from_2(rec - offs) & mask) >> shift); +} + +/******************************************************//** +Sets a bit field within 2 bytes. */ +UNIV_INLINE +void +rec_set_bit_field_2( +/*================*/ + rec_t* rec, /*!< in: pointer to record origin */ + ulint val, /*!< in: value to set */ + ulint offs, /*!< in: offset from the origin down */ + ulint mask, /*!< in: mask used to filter bits */ + ulint shift) /*!< in: shift right applied after masking */ +{ + ut_ad(rec); + ut_ad(offs <= REC_N_OLD_EXTRA_BYTES); + ut_ad(mask > 0xFFUL); + ut_ad(mask <= 0xFFFFUL); + ut_ad((mask >> shift) & 1); + ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1))); + ut_ad(((mask >> shift) << shift) == mask); + ut_ad(((val << shift) & mask) == (val << shift)); + + mach_write_to_2(rec - offs, + (mach_read_from_2(rec - offs) & ~mask) + | (val << shift)); +} + +/******************************************************//** +The following function is used to get the pointer of the next chained record +on the same page. +@return pointer to the next chained record, or NULL if none */ +UNIV_INLINE +const rec_t* +rec_get_next_ptr_const( +/*===================*/ + const rec_t* rec, /*!< in: physical record */ + ulint comp) /*!< in: nonzero=compact page format */ +{ + ulint field_value; + + ut_ad(REC_NEXT_MASK == 0xFFFFUL); + ut_ad(REC_NEXT_SHIFT == 0); + + field_value = mach_read_from_2(rec - REC_NEXT); + + if (field_value == 0) { + + return(NULL); + } + + if (comp) { +#if UNIV_PAGE_SIZE_MAX <= 32768 + /* Note that for 64 KiB pages, field_value can 'wrap around' + and the debug assertion is not valid */ + + /* In the following assertion, field_value is interpreted + as signed 16-bit integer in 2's complement arithmetics. + If all platforms defined int16_t in the standard headers, + the expression could be written simpler as + (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE + */ + ut_ad((field_value >= 32768 + ? field_value - 65536 + : field_value) + + ut_align_offset(rec, UNIV_PAGE_SIZE) + < UNIV_PAGE_SIZE); +#endif + /* There must be at least REC_N_NEW_EXTRA_BYTES + 1 + between each record. */ + ut_ad((field_value > REC_N_NEW_EXTRA_BYTES + && field_value < 32768) + || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES); + + return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE) + + ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); + } else { + ut_ad(field_value < UNIV_PAGE_SIZE); + + return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE) + + field_value); + } +} + +/******************************************************//** +The following function is used to get the pointer of the next chained record +on the same page. +@return pointer to the next chained record, or NULL if none */ +UNIV_INLINE +rec_t* +rec_get_next_ptr( +/*=============*/ + rec_t* rec, /*!< in: physical record */ + ulint comp) /*!< in: nonzero=compact page format */ +{ + return(const_cast(rec_get_next_ptr_const(rec, comp))); +} + +/******************************************************//** +The following function is used to get the offset of the next chained record +on the same page. +@return the page offset of the next chained record, or 0 if none */ +UNIV_INLINE +ulint +rec_get_next_offs( +/*==============*/ + const rec_t* rec, /*!< in: physical record */ + ulint comp) /*!< in: nonzero=compact page format */ +{ + ulint field_value; +#if REC_NEXT_MASK != 0xFFFFUL +# error "REC_NEXT_MASK != 0xFFFFUL" +#endif +#if REC_NEXT_SHIFT +# error "REC_NEXT_SHIFT != 0" +#endif + + field_value = mach_read_from_2(rec - REC_NEXT); + + if (comp) { +#if UNIV_PAGE_SIZE_MAX <= 32768 + /* Note that for 64 KiB pages, field_value can 'wrap around' + and the debug assertion is not valid */ + + /* In the following assertion, field_value is interpreted + as signed 16-bit integer in 2's complement arithmetics. + If all platforms defined int16_t in the standard headers, + the expression could be written simpler as + (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE + */ + ut_ad((field_value >= 32768 + ? field_value - 65536 + : field_value) + + ut_align_offset(rec, UNIV_PAGE_SIZE) + < UNIV_PAGE_SIZE); +#endif + if (field_value == 0) { + + return(0); + } + + /* There must be at least REC_N_NEW_EXTRA_BYTES + 1 + between each record. */ + ut_ad((field_value > REC_N_NEW_EXTRA_BYTES + && field_value < 32768) + || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES); + + return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); + } else { + ut_ad(field_value < UNIV_PAGE_SIZE); + + return(field_value); + } +} + +/******************************************************//** +The following function is used to set the next record offset field +of an old-style record. */ +UNIV_INLINE +void +rec_set_next_offs_old( +/*==================*/ + rec_t* rec, /*!< in: old-style physical record */ + ulint next) /*!< in: offset of the next record */ +{ + ut_ad(srv_page_size > next); + compile_time_assert(REC_NEXT_MASK == 0xFFFFUL); + compile_time_assert(REC_NEXT_SHIFT == 0); + mach_write_to_2(rec - REC_NEXT, next); +} + +/******************************************************//** +The following function is used to set the next record offset field +of a new-style record. */ +UNIV_INLINE +void +rec_set_next_offs_new( +/*==================*/ + rec_t* rec, /*!< in/out: new-style physical record */ + ulint next) /*!< in: offset of the next record */ +{ + ulint field_value; + + ut_ad(srv_page_size > next); + + if (!next) { + field_value = 0; + } else { + /* The following two statements calculate + next - offset_of_rec mod 64Ki, where mod is the modulo + as a non-negative number */ + + field_value = (ulint) + ((lint) next + - (lint) ut_align_offset(rec, UNIV_PAGE_SIZE)); + field_value &= REC_NEXT_MASK; + } + + mach_write_to_2(rec - REC_NEXT, field_value); +} + +/******************************************************//** +The following function is used to get the number of fields +in an old-style record. +@return number of data fields */ +UNIV_INLINE +ulint +rec_get_n_fields_old( +/*=================*/ + const rec_t* rec) /*!< in: physical record */ +{ + ulint ret; + + ut_ad(rec); + + ret = rec_get_bit_field_2(rec, REC_OLD_N_FIELDS, + REC_OLD_N_FIELDS_MASK, + REC_OLD_N_FIELDS_SHIFT); + ut_ad(ret <= REC_MAX_N_FIELDS); + ut_ad(ret > 0); + + return(ret); +} + +/******************************************************//** +The following function is used to set the number of fields +in an old-style record. */ +UNIV_INLINE +void +rec_set_n_fields_old( +/*=================*/ + rec_t* rec, /*!< in: physical record */ + ulint n_fields) /*!< in: the number of fields */ +{ + ut_ad(rec); + ut_ad(n_fields <= REC_MAX_N_FIELDS); + ut_ad(n_fields > 0); + + rec_set_bit_field_2(rec, n_fields, REC_OLD_N_FIELDS, + REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT); +} + +/******************************************************//** +The following function retrieves the status bits of a new-style record. +@return status bits */ +UNIV_INLINE +ulint +rec_get_status( +/*===========*/ + const rec_t* rec) /*!< in: physical record */ +{ + ulint ret; + + ut_ad(rec); + + ret = rec_get_bit_field_1(rec, REC_NEW_STATUS, + REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT); + ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0); + + return(ret); +} + +/******************************************************//** +The following function is used to get the number of fields +in a record. +@return number of data fields */ +UNIV_INLINE +ulint +rec_get_n_fields( +/*=============*/ + const rec_t* rec, /*!< in: physical record */ + const dict_index_t* index) /*!< in: record descriptor */ +{ + ut_ad(rec); + ut_ad(index); + + if (!dict_table_is_comp(index->table)) { + return(rec_get_n_fields_old(rec)); + } + + switch (rec_get_status(rec)) { + case REC_STATUS_ORDINARY: + return(dict_index_get_n_fields(index)); + case REC_STATUS_NODE_PTR: + return(dict_index_get_n_unique_in_tree(index) + 1); + case REC_STATUS_INFIMUM: + case REC_STATUS_SUPREMUM: + return(1); + default: + ut_error; + return(ULINT_UNDEFINED); + } +} + +/** Confirms the n_fields of the entry is sane with comparing the other +record in the same page specified +@param[in] index index +@param[in] rec record of the same page +@param[in] entry index entry +@return true if n_fields is sane */ +UNIV_INLINE +bool +rec_n_fields_is_sane( + dict_index_t* index, + const rec_t* rec, + const dtuple_t* entry) +{ + return(rec_get_n_fields(rec, index) + == dtuple_get_n_fields(entry) + /* a record for older SYS_INDEXES table + (missing merge_threshold column) is acceptable. */ + || (index->table->id == DICT_INDEXES_ID + && rec_get_n_fields(rec, index) + == dtuple_get_n_fields(entry) - 1)); +} + +/******************************************************//** +The following function is used to get the number of records owned by the +previous directory record. +@return number of owned records */ +UNIV_INLINE +ulint +rec_get_n_owned_old( +/*================*/ + const rec_t* rec) /*!< in: old-style physical record */ +{ + return(rec_get_bit_field_1(rec, REC_OLD_N_OWNED, + REC_N_OWNED_MASK, REC_N_OWNED_SHIFT)); +} + +/******************************************************//** +The following function is used to set the number of owned records. */ +UNIV_INLINE +void +rec_set_n_owned_old( +/*================*/ + rec_t* rec, /*!< in: old-style physical record */ + ulint n_owned) /*!< in: the number of owned */ +{ + rec_set_bit_field_1(rec, n_owned, REC_OLD_N_OWNED, + REC_N_OWNED_MASK, REC_N_OWNED_SHIFT); +} + +/******************************************************//** +The following function is used to get the number of records owned by the +previous directory record. +@return number of owned records */ +UNIV_INLINE +ulint +rec_get_n_owned_new( +/*================*/ + const rec_t* rec) /*!< in: new-style physical record */ +{ + return(rec_get_bit_field_1(rec, REC_NEW_N_OWNED, + REC_N_OWNED_MASK, REC_N_OWNED_SHIFT)); +} + +/******************************************************//** +The following function is used to set the number of owned records. */ +UNIV_INLINE +void +rec_set_n_owned_new( +/*================*/ + rec_t* rec, /*!< in/out: new-style physical record */ + page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ + ulint n_owned)/*!< in: the number of owned */ +{ + rec_set_bit_field_1(rec, n_owned, REC_NEW_N_OWNED, + REC_N_OWNED_MASK, REC_N_OWNED_SHIFT); + if (page_zip && rec_get_status(rec) != REC_STATUS_SUPREMUM) { + page_zip_rec_set_owned(page_zip, rec, n_owned); + } +} + +#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 */ +UNIV_INLINE +ulint +rec_get_info_bits( +/*==============*/ + const rec_t* rec, /*!< in: physical record */ + ulint comp) /*!< in: nonzero=compact page format */ +{ + 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); +} + +/******************************************************//** +The following function is used to set the info bits of a record. */ +UNIV_INLINE +void +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); +} +/******************************************************//** +The following function is used to set the info bits of a record. */ +UNIV_INLINE +void +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); +} + +/******************************************************//** +The following function is used to set the status bits of a new-style record. */ +UNIV_INLINE +void +rec_set_status( +/*===========*/ + rec_t* rec, /*!< in/out: physical record */ + ulint bits) /*!< in: info bits */ +{ + rec_set_bit_field_1(rec, bits, REC_NEW_STATUS, + REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT); +} + +/******************************************************//** +The following function is used to retrieve the info and status +bits of a record. (Only compact records have status bits.) +@return info bits */ +UNIV_INLINE +ulint +rec_get_info_and_status_bits( +/*=========================*/ + const rec_t* rec, /*!< in: physical record */ + ulint comp) /*!< in: nonzero=compact page format */ +{ + ulint bits; +#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ +& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) +# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" +#endif + if (comp) { + bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec); + } else { + bits = rec_get_info_bits(rec, FALSE); + ut_ad(!(bits & ~(REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT))); + } + return(bits); +} +/******************************************************//** +The following function is used to set the info and status +bits of a record. (Only compact records have status bits.) */ +UNIV_INLINE +void +rec_set_info_and_status_bits( +/*=========================*/ + rec_t* rec, /*!< in/out: physical record */ + ulint bits) /*!< in: info bits */ +{ +#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ +& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) +# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" +#endif + rec_set_status(rec, bits & REC_NEW_STATUS_MASK); + rec_set_info_bits_new(rec, bits & ~REC_NEW_STATUS_MASK); +} + +/******************************************************//** +The following function tells if record is delete marked. +@return nonzero if delete marked */ +UNIV_INLINE +ulint +rec_get_deleted_flag( +/*=================*/ + const rec_t* rec, /*!< in: physical record */ + ulint comp) /*!< in: nonzero=compact page format */ +{ + if (comp) { + return(rec_get_bit_field_1(rec, REC_NEW_INFO_BITS, + REC_INFO_DELETED_FLAG, + REC_INFO_BITS_SHIFT)); + } else { + return(rec_get_bit_field_1(rec, REC_OLD_INFO_BITS, + REC_INFO_DELETED_FLAG, + REC_INFO_BITS_SHIFT)); + } +} + +/******************************************************//** +The following function is used to set the deleted bit. */ +UNIV_INLINE +void +rec_set_deleted_flag_old( +/*=====================*/ + rec_t* rec, /*!< in: old-style physical record */ + ulint flag) /*!< in: nonzero if delete marked */ +{ + ulint val; + + val = rec_get_info_bits(rec, FALSE); + + if (flag) { + val |= REC_INFO_DELETED_FLAG; + } else { + val &= ~REC_INFO_DELETED_FLAG; + } + + rec_set_info_bits_old(rec, val); +} + +/******************************************************//** +The following function is used to set the deleted bit. */ +UNIV_INLINE +void +rec_set_deleted_flag_new( +/*=====================*/ + rec_t* rec, /*!< in/out: new-style physical record */ + page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ + ulint flag) /*!< in: nonzero if delete marked */ +{ + ulint val; + + val = rec_get_info_bits(rec, TRUE); + + if (flag) { + val |= REC_INFO_DELETED_FLAG; + } else { + val &= ~REC_INFO_DELETED_FLAG; + } + + rec_set_info_bits_new(rec, val); + + if (page_zip) { + page_zip_rec_set_deleted(page_zip, rec, flag); + } +} + +/******************************************************//** +The following function tells if a new-style record is a node pointer. +@return TRUE if node pointer */ +UNIV_INLINE +ibool +rec_get_node_ptr_flag( +/*==================*/ + const rec_t* rec) /*!< in: physical record */ +{ + return(REC_STATUS_NODE_PTR == rec_get_status(rec)); +} + +/******************************************************//** +The following function is used to get the order number +of an old-style record in the heap of the index page. +@return heap order number */ +UNIV_INLINE +ulint +rec_get_heap_no_old( +/*================*/ + const rec_t* rec) /*!< in: physical record */ +{ + return(rec_get_bit_field_2(rec, REC_OLD_HEAP_NO, + REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT)); +} + +/******************************************************//** +The following function is used to set the heap number +field in an old-style record. */ +UNIV_INLINE +void +rec_set_heap_no_old( +/*================*/ + rec_t* rec, /*!< in: physical record */ + ulint heap_no)/*!< in: the heap number */ +{ + rec_set_bit_field_2(rec, heap_no, REC_OLD_HEAP_NO, + REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT); +} + +/******************************************************//** +The following function is used to get the order number +of a new-style record in the heap of the index page. +@return heap order number */ +UNIV_INLINE +ulint +rec_get_heap_no_new( +/*================*/ + const rec_t* rec) /*!< in: physical record */ +{ + return(rec_get_bit_field_2(rec, REC_NEW_HEAP_NO, + REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT)); +} + +/******************************************************//** +The following function is used to set the heap number +field in a new-style record. */ +UNIV_INLINE +void +rec_set_heap_no_new( +/*================*/ + rec_t* rec, /*!< in/out: physical record */ + ulint heap_no)/*!< in: the heap number */ +{ + rec_set_bit_field_2(rec, heap_no, REC_NEW_HEAP_NO, + REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT); +} + +/******************************************************//** +The following function is used to test whether the data offsets in the record +are stored in one-byte or two-byte format. +@return TRUE if 1-byte form */ +UNIV_INLINE +ibool +rec_get_1byte_offs_flag( +/*====================*/ + const rec_t* rec) /*!< in: physical record */ +{ +#if TRUE != 1 +#error "TRUE != 1" +#endif + + return(rec_get_bit_field_1(rec, REC_OLD_SHORT, REC_OLD_SHORT_MASK, + REC_OLD_SHORT_SHIFT)); +} + +/******************************************************//** +The following function is used to set the 1-byte offsets flag. */ +UNIV_INLINE +void +rec_set_1byte_offs_flag( +/*====================*/ + rec_t* rec, /*!< in: physical record */ + ibool flag) /*!< in: TRUE if 1byte form */ +{ +#if TRUE != 1 +#error "TRUE != 1" +#endif + ut_ad(flag <= TRUE); + + rec_set_bit_field_1(rec, flag, REC_OLD_SHORT, REC_OLD_SHORT_MASK, + REC_OLD_SHORT_SHIFT); +} + +/******************************************************//** +Returns the offset of nth field end if the record is stored in the 1-byte +offsets form. If the field is SQL null, the flag is ORed in the returned +value. +@return offset of the start of the field, SQL null flag ORed */ +UNIV_INLINE +uint8_t +rec_1_get_field_end_info( +/*=====================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + ut_ad(rec_get_1byte_offs_flag(rec)); + ut_ad(n < rec_get_n_fields_old(rec)); + + return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1))); +} + +/******************************************************//** +Returns the offset of nth field end if the record is stored in the 2-byte +offsets form. If the field is SQL null, the flag is ORed in the returned +value. +@return offset of the start of the field, SQL null flag and extern +storage flag ORed */ +UNIV_INLINE +rec_offs +rec_2_get_field_end_info( +/*=====================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + ut_ad(!rec_get_1byte_offs_flag(rec)); + ut_ad(n < rec_get_n_fields_old(rec)); + + return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2))); +} + +/******************************************************//** +Returns nonzero if the field is stored off-page. +@retval 0 if the field is stored in-page +@retval REC_2BYTE_EXTERN_MASK if the field is stored externally */ +UNIV_INLINE +ulint +rec_2_is_field_extern( +/*==================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + return(rec_2_get_field_end_info(rec, n) & REC_2BYTE_EXTERN_MASK); +} + +/* Get the base address of offsets. The extra_size is stored at +this position, and following positions hold the end offsets of +the fields. */ +#define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE) + +/**********************************************************//** +The following function returns the number of allocated elements +for an array of offsets. +@return number of elements */ +UNIV_INLINE +ulint +rec_offs_get_n_alloc( +/*=================*/ + const rec_offs* offsets)/*!< in: array for rec_get_offsets() */ +{ + ulint n_alloc; + ut_ad(offsets); + n_alloc = offsets[0]; + ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); + MEM_CHECK_ADDRESSABLE(offsets, n_alloc * sizeof *offsets); + return(n_alloc); +} + +/**********************************************************//** +The following function sets the number of allocated elements +for an array of offsets. */ +UNIV_INLINE +void +rec_offs_set_n_alloc( +/*=================*/ + rec_offs*offsets, /*!< out: array for rec_get_offsets(), + must be allocated */ + ulint n_alloc) /*!< in: number of elements */ +{ + ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); + MEM_UNDEFINED(offsets, n_alloc * sizeof *offsets); + offsets[0] = static_cast(n_alloc); +} + +/**********************************************************//** +The following function returns the number of fields in a record. +@return number of fields */ +UNIV_INLINE +ulint +rec_offs_n_fields( +/*==============*/ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ulint n_fields; + ut_ad(offsets); + n_fields = offsets[1]; + ut_ad(n_fields > 0); + ut_ad(n_fields <= REC_MAX_N_FIELDS); + ut_ad(n_fields + REC_OFFS_HEADER_SIZE + <= rec_offs_get_n_alloc(offsets)); + return(n_fields); +} + +/************************************************************//** +Validates offsets returned by rec_get_offsets(). +@return TRUE if valid */ +UNIV_INLINE +ibool +rec_offs_validate( +/*==============*/ + const rec_t* rec, /*!< in: record or NULL */ + const dict_index_t* index, /*!< in: record descriptor or NULL */ + const rec_offs* offsets)/*!< in: array returned by + rec_get_offsets() */ +{ + ulint i = rec_offs_n_fields(offsets); + ulint last = ULINT_MAX; + bool comp = rec_offs_base(offsets)[0] & REC_OFFS_COMPACT; + + if (rec) { + ut_ad(!memcmp(&rec, &offsets[RECORD_OFFSET], sizeof(rec))); + if (!comp) { + ut_a(rec_get_n_fields_old(rec) >= i); + } + } + if (index) { + ulint max_n_fields; + ut_ad(!memcmp(&index, &offsets[INDEX_OFFSET], sizeof(index))); + max_n_fields = ut_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_ORDINARY: + break; + case REC_STATUS_NODE_PTR: + max_n_fields = dict_index_get_n_unique_in_tree( + index) + 1; + break; + case REC_STATUS_INFIMUM: + case REC_STATUS_SUPREMUM: + max_n_fields = 1; + break; + default: + ut_error; + } + } + /* index->n_def == 0 for dummy indexes if !comp */ + ut_a(!comp || index->n_def); + ut_a(!index->n_def || i <= max_n_fields); + } + while (i--) { + rec_offs curr = get_value(rec_offs_base(offsets)[1 + i]); + ut_a(curr <= last); + last = curr; + } + return(TRUE); +} +#ifdef UNIV_DEBUG +/************************************************************//** +Updates debug data in offsets, in order to avoid bogus +rec_offs_validate() failures. */ +UNIV_INLINE +void +rec_offs_make_valid( +/*================*/ + const rec_t* rec, /*!< in: record */ + const dict_index_t* index, /*!< in: record descriptor */ + rec_offs* offsets)/*!< in: array returned by + rec_get_offsets() */ +{ + ut_ad(rec); + ut_ad(index); + ut_ad(offsets); + ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets)); + memcpy(&offsets[RECORD_OFFSET], &rec, sizeof(rec)); + memcpy(&offsets[INDEX_OFFSET], &index, sizeof(index)); +} +#endif /* UNIV_DEBUG */ + +/************************************************************//** +The following function is used to get an offset to the nth +data field in a record. +@return offset from the origin of rec */ +UNIV_INLINE +rec_offs +rec_get_nth_field_offs( +/*===================*/ + const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ + ulint n, /*!< in: index of the field */ + ulint* len) /*!< out: length of the field; UNIV_SQL_NULL + if SQL null */ +{ + ut_ad(n < rec_offs_n_fields(offsets)); + + rec_offs offs = n == 0 ? 0 : get_value(rec_offs_base(offsets)[n]); + rec_offs next_offs = rec_offs_base(offsets)[1 + n]; + + if (get_type(next_offs) == SQL_NULL) { + *len = UNIV_SQL_NULL; + } else { + + *len = get_value(next_offs) - offs; + } + + return(offs); +} + +/******************************************************//** +Determine if the offsets are for a record in the new +compact format. +@return nonzero if compact format */ +UNIV_INLINE +ulint +rec_offs_comp( +/*==========*/ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + return(*rec_offs_base(offsets) & REC_OFFS_COMPACT); +} + +/******************************************************//** +Determine if the offsets are for a record containing +externally stored columns. +@return nonzero if externally stored */ +UNIV_INLINE +ulint +rec_offs_any_extern( +/*================*/ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + return(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL); +} + +/******************************************************//** +Determine if the offsets are for a record containing null BLOB pointers. +@return first field containing a null BLOB pointer, or NULL if none found */ +UNIV_INLINE +const byte* +rec_offs_any_null_extern( +/*=====================*/ + const rec_t* rec, /*!< in: record */ + const rec_offs* offsets) /*!< in: rec_get_offsets(rec) */ +{ + ulint i; + ut_ad(rec_offs_validate(rec, NULL, offsets)); + + if (!rec_offs_any_extern(offsets)) { + return(NULL); + } + + for (i = 0; i < rec_offs_n_fields(offsets); i++) { + if (rec_offs_nth_extern(offsets, i)) { + ulint len; + const byte* field + = rec_get_nth_field(rec, offsets, i, &len); + + ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); + if (!memcmp(field + len + - BTR_EXTERN_FIELD_REF_SIZE, + field_ref_zero, + BTR_EXTERN_FIELD_REF_SIZE)) { + return(field); + } + } + } + + return(NULL); +} + +/******************************************************//** +Returns nonzero if the extern bit is set in nth field of rec. +@return nonzero if externally stored */ +UNIV_INLINE +ulint +rec_offs_nth_extern( +/*================*/ + const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ + ulint n) /*!< in: nth field */ +{ + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + ut_ad(n < rec_offs_n_fields(offsets)); + return get_type(rec_offs_base(offsets)[1 + n]) == STORED_OFFPAGE; +} + +/******************************************************//** +Returns nonzero if the SQL NULL bit is set in nth field of rec. +@return nonzero if SQL NULL */ +UNIV_INLINE +ulint +rec_offs_nth_sql_null( +/*==================*/ + const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ + ulint n) /*!< in: nth field */ +{ + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + ut_ad(n < rec_offs_n_fields(offsets)); + return get_type(rec_offs_base(offsets)[1 + n]) == SQL_NULL; +} + +/******************************************************//** +Gets the physical size of a field. +@return length of field */ +UNIV_INLINE +ulint +rec_offs_nth_size( +/*==============*/ + const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ + ulint n) /*!< in: nth field */ +{ + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + ut_ad(n < rec_offs_n_fields(offsets)); + if (!n) { + return get_value(rec_offs_base(offsets)[1 + n]); + } + return get_value((rec_offs_base(offsets)[1 + n])) + - get_value(rec_offs_base(offsets)[n]); +} + +/******************************************************//** +Returns the number of extern bits set in a record. +@return number of externally stored fields */ +UNIV_INLINE +ulint +rec_offs_n_extern( +/*==============*/ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ulint n = 0; + + if (rec_offs_any_extern(offsets)) { + ulint i; + + for (i = rec_offs_n_fields(offsets); i--; ) { + if (rec_offs_nth_extern(offsets, i)) { + n++; + } + } + } + + return(n); +} + +/******************************************************//** +Returns the offset of n - 1th field end if the record is stored in the 1-byte +offsets form. If the field is SQL null, the flag is ORed in the returned +value. This function and the 2-byte counterpart are defined here because the +C-compiler was not able to sum negative and positive constant offsets, and +warned of constant arithmetic overflow within the compiler. +@return offset of the start of the PREVIOUS field, SQL null flag ORed */ +UNIV_INLINE +ulint +rec_1_get_prev_field_end_info( +/*==========================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + ut_ad(rec_get_1byte_offs_flag(rec)); + ut_ad(n <= rec_get_n_fields_old(rec)); + + return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n))); +} + +/******************************************************//** +Returns the offset of n - 1th field end if the record is stored in the 2-byte +offsets form. If the field is SQL null, the flag is ORed in the returned +value. +@return offset of the start of the PREVIOUS field, SQL null flag ORed */ +UNIV_INLINE +ulint +rec_2_get_prev_field_end_info( +/*==========================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + ut_ad(!rec_get_1byte_offs_flag(rec)); + ut_ad(n <= rec_get_n_fields_old(rec)); + + return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n))); +} + +/******************************************************//** +Sets the field end info for the nth field if the record is stored in the +1-byte format. */ +UNIV_INLINE +void +rec_1_set_field_end_info( +/*=====================*/ + rec_t* rec, /*!< in: record */ + ulint n, /*!< in: field index */ + ulint info) /*!< in: value to set */ +{ + ut_ad(rec_get_1byte_offs_flag(rec)); + ut_ad(n < rec_get_n_fields_old(rec)); + + mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1), info); +} + +/******************************************************//** +Sets the field end info for the nth field if the record is stored in the +2-byte format. */ +UNIV_INLINE +void +rec_2_set_field_end_info( +/*=====================*/ + rec_t* rec, /*!< in: record */ + ulint n, /*!< in: field index */ + ulint info) /*!< in: value to set */ +{ + ut_ad(!rec_get_1byte_offs_flag(rec)); + ut_ad(n < rec_get_n_fields_old(rec)); + + mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2), info); +} + +/******************************************************//** +Returns the offset of nth field start if the record is stored in the 1-byte +offsets form. +@return offset of the start of the field */ +UNIV_INLINE +ulint +rec_1_get_field_start_offs( +/*=======================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + ut_ad(rec_get_1byte_offs_flag(rec)); + ut_ad(n <= rec_get_n_fields_old(rec)); + + if (n == 0) { + + return(0); + } + + return(rec_1_get_prev_field_end_info(rec, n) + & ~REC_1BYTE_SQL_NULL_MASK); +} + +/******************************************************//** +Returns the offset of nth field start if the record is stored in the 2-byte +offsets form. +@return offset of the start of the field */ +UNIV_INLINE +ulint +rec_2_get_field_start_offs( +/*=======================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + ut_ad(!rec_get_1byte_offs_flag(rec)); + ut_ad(n <= rec_get_n_fields_old(rec)); + + if (n == 0) { + + return(0); + } + + return(rec_2_get_prev_field_end_info(rec, n) + & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK)); +} + +/******************************************************//** +The following function is used to read the offset of the start of a data field +in the record. The start of an SQL null field is the end offset of the +previous non-null field, or 0, if none exists. If n is the number of the last +field + 1, then the end offset of the last field is returned. +@return offset of the start of the field */ +UNIV_INLINE +ulint +rec_get_field_start_offs( +/*=====================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: field index */ +{ + ut_ad(rec); + ut_ad(n <= rec_get_n_fields_old(rec)); + + if (n == 0) { + + return(0); + } + + if (rec_get_1byte_offs_flag(rec)) { + + return(rec_1_get_field_start_offs(rec, n)); + } + + return(rec_2_get_field_start_offs(rec, n)); +} + +/************************************************************//** +Gets the physical size of an old-style field. +Also an SQL null may have a field of size > 0, +if the data type is of a fixed size. +@return field size in bytes */ +UNIV_INLINE +ulint +rec_get_nth_field_size( +/*===================*/ + const rec_t* rec, /*!< in: record */ + ulint n) /*!< in: index of the field */ +{ + ulint os; + ulint next_os; + + os = rec_get_field_start_offs(rec, n); + next_os = rec_get_field_start_offs(rec, n + 1); + + ut_ad(next_os - os < UNIV_PAGE_SIZE); + + return(next_os - os); +} + +/***********************************************************//** +This is used to modify the value of an already existing field in a record. +The previous value must have exactly the same size as the new value. If len +is UNIV_SQL_NULL then the field is treated as an SQL null. +For records in ROW_FORMAT=COMPACT (new-style records), len must not be +UNIV_SQL_NULL unless the field already is SQL null. */ +UNIV_INLINE +void +rec_set_nth_field( +/*==============*/ + rec_t* rec, /*!< in: record */ + const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ + ulint n, /*!< in: index number of the field */ + const void* data, /*!< in: pointer to the data + if not SQL null */ + ulint len) /*!< in: length of the data or UNIV_SQL_NULL */ +{ + byte* data2; + ulint len2; + + ut_ad(rec_offs_validate(rec, NULL, offsets)); + + if (len == UNIV_SQL_NULL) { + if (!rec_offs_nth_sql_null(offsets, n)) { + ut_a(!rec_offs_comp(offsets)); + rec_set_nth_field_sql_null(rec, n); + } + + return; + } + + data2 = rec_get_nth_field(rec, offsets, n, &len2); + if (len2 == UNIV_SQL_NULL) { + ut_ad(!rec_offs_comp(offsets)); + rec_set_nth_field_null_bit(rec, n, FALSE); + ut_ad(len == rec_get_nth_field_size(rec, n)); + } else { + ut_ad(len2 == len); + } + + ut_memcpy(data2, data, len); +} + +/**********************************************************//** +The following function returns the data size of an old-style physical +record, that is the sum of field lengths. SQL null fields +are counted as length 0 fields. The value returned by the function +is the distance from record origin to record end in bytes. +@return size */ +UNIV_INLINE +ulint +rec_get_data_size_old( +/*==================*/ + const rec_t* rec) /*!< in: physical record */ +{ + ut_ad(rec); + + return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec))); +} + +/**********************************************************//** +The following function sets the number of fields in offsets. */ +UNIV_INLINE +void +rec_offs_set_n_fields( +/*==================*/ + rec_offs* offsets, /*!< in/out: array returned by + rec_get_offsets() */ + ulint n_fields) /*!< in: number of fields */ +{ + ut_ad(offsets); + ut_ad(n_fields > 0); + ut_ad(n_fields <= REC_MAX_N_FIELDS); + ut_ad(n_fields + REC_OFFS_HEADER_SIZE + <= rec_offs_get_n_alloc(offsets)); + offsets[1] = static_cast(n_fields); +} + +/**********************************************************//** +The following function returns the data size of a physical +record, that is the sum of field lengths. SQL null fields +are counted as length 0 fields. The value returned by the function +is the distance from record origin to record end in bytes. +@return size */ +UNIV_INLINE +ulint +rec_offs_data_size( +/*===============*/ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ulint size; + + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + size = get_value(rec_offs_base(offsets)[rec_offs_n_fields(offsets)]); + ut_ad(size < UNIV_PAGE_SIZE); + return(size); +} + +/**********************************************************//** +Returns the total size of record minus data size of record. The value +returned by the function is the distance from record start to record origin +in bytes. +@return size */ +UNIV_INLINE +ulint +rec_offs_extra_size( +/*================*/ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ulint size; + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + size = *rec_offs_base(offsets) & ~(REC_OFFS_COMPACT | REC_OFFS_EXTERNAL); + ut_ad(size < UNIV_PAGE_SIZE); + return(size); +} + +/**********************************************************//** +Returns the total size of a physical record. +@return size */ +UNIV_INLINE +ulint +rec_offs_size( +/*==========*/ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets)); +} + +#ifdef UNIV_DEBUG +/**********************************************************//** +Returns a pointer to the end of the record. +@return pointer to end */ +UNIV_INLINE +byte* +rec_get_end( +/*========*/ + const rec_t* rec, /*!< in: pointer to record */ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ut_ad(rec_offs_validate(rec, NULL, offsets)); + return(const_cast(rec + rec_offs_data_size(offsets))); +} + +/**********************************************************//** +Returns a pointer to the start of the record. +@return pointer to start */ +UNIV_INLINE +byte* +rec_get_start( +/*==========*/ + const rec_t* rec, /*!< in: pointer to record */ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + ut_ad(rec_offs_validate(rec, NULL, offsets)); + return(const_cast(rec - rec_offs_extra_size(offsets))); +} +#endif /* UNIV_DEBUG */ + +/** Copy a physical record to a buffer. +@param[in] buf buffer +@param[in] rec physical record +@param[in] offsets array returned by rec_get_offsets() +@return pointer to the origin of the copy */ +UNIV_INLINE +rec_t* +rec_copy( + void* buf, + const rec_t* rec, + const rec_offs* offsets) +{ + ulint extra_len; + ulint data_len; + + ut_ad(rec != NULL); + ut_ad(buf != NULL); + ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(rec_validate(rec, offsets)); + + extra_len = rec_offs_extra_size(offsets); + data_len = rec_offs_data_size(offsets); + + ut_memcpy(buf, rec - extra_len, extra_len + data_len); + + return((byte*) buf + extra_len); +} + +/**********************************************************//** +Returns the extra size of an old-style physical record if we know its +data size and number of fields. +@return extra size */ +UNIV_INLINE +ulint +rec_get_converted_extra_size( +/*=========================*/ + ulint data_size, /*!< in: data size */ + ulint n_fields, /*!< in: number of fields */ + ulint n_ext) /*!< in: number of externally stored columns */ +{ + if (!n_ext && data_size <= REC_1BYTE_OFFS_LIMIT) { + + return(REC_N_OLD_EXTRA_BYTES + n_fields); + } + + return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields); +} + +/**********************************************************//** +The following function returns the size of a data tuple when converted to +a physical record. +@return size */ +UNIV_INLINE +ulint +rec_get_converted_size( +/*===================*/ + dict_index_t* index, /*!< in: record descriptor */ + const dtuple_t* dtuple, /*!< in: data tuple */ + ulint n_ext) /*!< in: number of externally stored columns */ +{ + ulint data_size; + ulint extra_size; + + ut_ad(dtuple_check_typed(dtuple)); + + ut_ad(dict_index_is_ibuf(index) + + || dtuple_get_n_fields(dtuple) + == (((dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) + == REC_STATUS_NODE_PTR) + ? dict_index_get_n_unique_in_tree_nonleaf(index) + 1 + : dict_index_get_n_fields(index)) + + /* a record for older SYS_INDEXES table + (missing merge_threshold column) is acceptable. */ + || (index->table->id == DICT_INDEXES_ID + && dtuple_get_n_fields(dtuple) + == dict_index_get_n_fields(index) - 1)); + + if (dict_table_is_comp(index->table)) { + return(rec_get_converted_size_comp(index, + dtuple_get_info_bits(dtuple) + & REC_NEW_STATUS_MASK, + dtuple->fields, + dtuple->n_fields, NULL)); + } + + data_size = dtuple_get_data_size(dtuple, 0); + + /* If primary key is being updated then the new record inherits + externally stored fields from the delete-marked old record. + In that case, n_ext may be less value than + dtuple_get_n_ext(tuple). */ + ut_ad(n_ext <= dtuple_get_n_ext(dtuple)); + extra_size = rec_get_converted_extra_size( + data_size, dtuple_get_n_fields(dtuple), n_ext); + +#if 0 + /* This code is inactive since it may be the wrong place to add + in the size of node pointers used in parent pages AND it is not + currently needed since ha_innobase::max_supported_key_length() + ensures that the key size limit for each page size is well below + the actual limit ((free space on page / 4) - record overhead). + But those limits will need to be raised when InnoDB can + support multiple page sizes. At that time, we will need + to consider the node pointer on these universal btrees. */ + + if (dict_index_is_ibuf(index)) { + /* This is for the insert buffer B-tree. + All fields in the leaf tuple ascend to the + parent node plus the child page pointer. */ + + /* ibuf cannot contain externally stored fields */ + ut_ad(n_ext == 0); + + /* Add the data pointer and recompute extra_size + based on one more field. */ + data_size += REC_NODE_PTR_SIZE; + extra_size = rec_get_converted_extra_size( + data_size, + dtuple_get_n_fields(dtuple) + 1, + 0); + + /* Be sure dtuple->n_fields has this node ptr + accounted for. This function should correspond to + what rec_convert_dtuple_to_rec() needs in storage. + In optimistic insert or update-not-in-place, we will + have to ensure that if the record is converted to a + node pointer, it will not become too large.*/ + } +#endif + + return(data_size + extra_size); +} + +/** Fold a prefix of a physical record. +@param[in] rec index record +@param[in] offsets return value of rec_get_offsets() +@param[in] n_fields number of complete fields to fold +@param[in] n_bytes number of bytes to fold in the last field +@param[in] index_id index tree ID +@return the folded value */ +UNIV_INLINE +ulint +rec_fold( + const rec_t* rec, + const rec_offs* offsets, + ulint n_fields, + ulint n_bytes, + index_id_t tree_id) +{ + ulint i; + const byte* data; + ulint len; + ulint fold; + ulint n_fields_rec; + + ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(rec_validate(rec, offsets)); + ut_ad(n_fields > 0 || n_bytes > 0); + + n_fields_rec = rec_offs_n_fields(offsets); + ut_ad(n_fields <= n_fields_rec); + ut_ad(n_fields < n_fields_rec || n_bytes == 0); + + if (n_fields > n_fields_rec) { + n_fields = n_fields_rec; + } + + if (n_fields == n_fields_rec) { + n_bytes = 0; + } + + fold = ut_fold_ull(tree_id); + + for (i = 0; i < n_fields; i++) { + data = rec_get_nth_field(rec, offsets, i, &len); + + if (len != UNIV_SQL_NULL) { + fold = ut_fold_ulint_pair(fold, + ut_fold_binary(data, len)); + } + } + + if (n_bytes > 0) { + data = rec_get_nth_field(rec, offsets, i, &len); + + if (len != UNIV_SQL_NULL) { + if (len > n_bytes) { + len = n_bytes; + } + + fold = ut_fold_ulint_pair(fold, + ut_fold_binary(data, len)); + } + } + + return(fold); +} diff --git a/storage/innobase/include/row0ext.h b/storage/innobase/include/row0ext.h index 11a6bfa4667..b3665e665dc 100644 --- a/storage/innobase/include/row0ext.h +++ b/storage/innobase/include/row0ext.h @@ -97,6 +97,6 @@ struct row_ext_t{ ulint len[1]; /*!< prefix lengths; 0 if not cached */ }; -#include "row0ext.ic" +#include "row0ext.inl" #endif diff --git a/storage/innobase/include/row0ext.ic b/storage/innobase/include/row0ext.ic deleted file mode 100644 index 913b51b34d2..00000000000 --- a/storage/innobase/include/row0ext.ic +++ /dev/null @@ -1,87 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2006, 2009, 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/row0ext.ic -Caching of externally stored column prefixes - -Created September 2006 Marko Makela -*******************************************************/ - -#include "rem0types.h" -#include "btr0types.h" - -/********************************************************************//** -Looks up a column prefix of an externally stored column. -@return column prefix, or NULL if the column is not stored externally, -or pointer to field_ref_zero if the BLOB pointer is unset */ -UNIV_INLINE -const byte* -row_ext_lookup_ith( -/*===============*/ - const row_ext_t* ext, /*!< in/out: column prefix cache */ - ulint i, /*!< in: index of ext->ext[] */ - ulint* len) /*!< out: length of prefix, in bytes, - at most ext->max_len */ -{ - ut_ad(ext); - ut_ad(len); - ut_ad(i < ext->n_ext); - - *len = ext->len[i]; - - ut_ad(*len <= ext->max_len); - ut_ad(ext->max_len > 0); - - if (*len == 0) { - /* The BLOB could not be fetched to the cache. */ - return(field_ref_zero); - } else { - return(ext->buf + i * ext->max_len); - } -} - -/********************************************************************//** -Looks up a column prefix of an externally stored column. -@return column prefix, or NULL if the column is not stored externally, -or pointer to field_ref_zero if the BLOB pointer is unset */ -UNIV_INLINE -const byte* -row_ext_lookup( -/*===========*/ - const row_ext_t* ext, /*!< in: column prefix cache */ - ulint col, /*!< in: column number in the InnoDB - table object, as reported by - dict_col_get_no(); NOT relative to the - records in the clustered index */ - ulint* len) /*!< out: length of prefix, in bytes, - at most ext->max_len */ -{ - ulint i; - - ut_ad(ext); - ut_ad(len); - - for (i = 0; i < ext->n_ext; i++) { - if (col == ext->ext[i]) { - return(row_ext_lookup_ith(ext, i, len)); - } - } - - return(NULL); -} diff --git a/storage/innobase/include/row0ext.inl b/storage/innobase/include/row0ext.inl new file mode 100644 index 00000000000..913b51b34d2 --- /dev/null +++ b/storage/innobase/include/row0ext.inl @@ -0,0 +1,87 @@ +/***************************************************************************** + +Copyright (c) 2006, 2009, 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/row0ext.ic +Caching of externally stored column prefixes + +Created September 2006 Marko Makela +*******************************************************/ + +#include "rem0types.h" +#include "btr0types.h" + +/********************************************************************//** +Looks up a column prefix of an externally stored column. +@return column prefix, or NULL if the column is not stored externally, +or pointer to field_ref_zero if the BLOB pointer is unset */ +UNIV_INLINE +const byte* +row_ext_lookup_ith( +/*===============*/ + const row_ext_t* ext, /*!< in/out: column prefix cache */ + ulint i, /*!< in: index of ext->ext[] */ + ulint* len) /*!< out: length of prefix, in bytes, + at most ext->max_len */ +{ + ut_ad(ext); + ut_ad(len); + ut_ad(i < ext->n_ext); + + *len = ext->len[i]; + + ut_ad(*len <= ext->max_len); + ut_ad(ext->max_len > 0); + + if (*len == 0) { + /* The BLOB could not be fetched to the cache. */ + return(field_ref_zero); + } else { + return(ext->buf + i * ext->max_len); + } +} + +/********************************************************************//** +Looks up a column prefix of an externally stored column. +@return column prefix, or NULL if the column is not stored externally, +or pointer to field_ref_zero if the BLOB pointer is unset */ +UNIV_INLINE +const byte* +row_ext_lookup( +/*===========*/ + const row_ext_t* ext, /*!< in: column prefix cache */ + ulint col, /*!< in: column number in the InnoDB + table object, as reported by + dict_col_get_no(); NOT relative to the + records in the clustered index */ + ulint* len) /*!< out: length of prefix, in bytes, + at most ext->max_len */ +{ + ulint i; + + ut_ad(ext); + ut_ad(len); + + for (i = 0; i < ext->n_ext; i++) { + if (col == ext->ext[i]) { + return(row_ext_lookup_ith(ext, i, len)); + } + } + + return(NULL); +} diff --git a/storage/innobase/include/row0log.h b/storage/innobase/include/row0log.h index 1e46d65e427..2ec00909a4c 100644 --- a/storage/innobase/include/row0log.h +++ b/storage/innobase/include/row0log.h @@ -252,6 +252,6 @@ row_log_estimate_work( const dict_index_t* index); #endif /* HAVE_PSI_STAGE_INTERFACE */ -#include "row0log.ic" +#include "row0log.inl" #endif /* row0log.h */ diff --git a/storage/innobase/include/row0log.ic b/storage/innobase/include/row0log.ic deleted file mode 100644 index 44d17bbcdf1..00000000000 --- a/storage/innobase/include/row0log.ic +++ /dev/null @@ -1,84 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 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 -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/row0log.ic -Modification log for online index creation and online table rebuild - -Created 2012-10-18 Marko Makela -*******************************************************/ - -#include "dict0dict.h" - -/******************************************************//** -Free the row log for an index on which online creation was aborted. */ -UNIV_INLINE -void -row_log_abort_sec( -/*===============*/ - dict_index_t* index) /*!< in/out: index (x-latched) */ -{ - ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X)); - - ut_ad(!dict_index_is_clust(index)); - dict_index_set_online_status(index, ONLINE_INDEX_ABORTED); - row_log_free(index->online_log); - index->online_log = NULL; -} - -/******************************************************//** -Try to log an operation to a secondary index that is -(or was) being created. -@retval true if the operation was logged or can be ignored -@retval false if online index creation is not taking place */ -UNIV_INLINE -bool -row_log_online_op_try( -/*==================*/ - dict_index_t* index, /*!< in/out: index, S or X latched */ - const dtuple_t* tuple, /*!< in: index tuple */ - trx_id_t trx_id) /*!< in: transaction ID for insert, - or 0 for delete */ -{ - - ut_ad(rw_lock_own_flagged( - dict_index_get_lock(index), - RW_LOCK_FLAG_S | RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); - - switch (dict_index_get_online_status(index)) { - case ONLINE_INDEX_COMPLETE: - /* This is a normal index. Do not log anything. - The caller must perform the operation on the - index tree directly. */ - return(false); - case ONLINE_INDEX_CREATION: - /* The index is being created online. Log the - operation. */ - row_log_online_op(index, tuple, trx_id); - break; - case ONLINE_INDEX_ABORTED: - case ONLINE_INDEX_ABORTED_DROPPED: - /* The index was created online, but the operation was - aborted. Do not log the operation and tell the caller - to skip the operation. */ - break; - } - - return(true); -} diff --git a/storage/innobase/include/row0log.inl b/storage/innobase/include/row0log.inl new file mode 100644 index 00000000000..44d17bbcdf1 --- /dev/null +++ b/storage/innobase/include/row0log.inl @@ -0,0 +1,84 @@ +/***************************************************************************** + +Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 +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/row0log.ic +Modification log for online index creation and online table rebuild + +Created 2012-10-18 Marko Makela +*******************************************************/ + +#include "dict0dict.h" + +/******************************************************//** +Free the row log for an index on which online creation was aborted. */ +UNIV_INLINE +void +row_log_abort_sec( +/*===============*/ + dict_index_t* index) /*!< in/out: index (x-latched) */ +{ + ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X)); + + ut_ad(!dict_index_is_clust(index)); + dict_index_set_online_status(index, ONLINE_INDEX_ABORTED); + row_log_free(index->online_log); + index->online_log = NULL; +} + +/******************************************************//** +Try to log an operation to a secondary index that is +(or was) being created. +@retval true if the operation was logged or can be ignored +@retval false if online index creation is not taking place */ +UNIV_INLINE +bool +row_log_online_op_try( +/*==================*/ + dict_index_t* index, /*!< in/out: index, S or X latched */ + const dtuple_t* tuple, /*!< in: index tuple */ + trx_id_t trx_id) /*!< in: transaction ID for insert, + or 0 for delete */ +{ + + ut_ad(rw_lock_own_flagged( + dict_index_get_lock(index), + RW_LOCK_FLAG_S | RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); + + switch (dict_index_get_online_status(index)) { + case ONLINE_INDEX_COMPLETE: + /* This is a normal index. Do not log anything. + The caller must perform the operation on the + index tree directly. */ + return(false); + case ONLINE_INDEX_CREATION: + /* The index is being created online. Log the + operation. */ + row_log_online_op(index, tuple, trx_id); + break; + case ONLINE_INDEX_ABORTED: + case ONLINE_INDEX_ABORTED_DROPPED: + /* The index was created online, but the operation was + aborted. Do not log the operation and tell the caller + to skip the operation. */ + break; + } + + return(true); +} diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h index 1c7e40ac690..1886ef855a4 100644 --- a/storage/innobase/include/row0row.h +++ b/storage/innobase/include/row0row.h @@ -409,6 +409,6 @@ row_mtr_start(mtr_t* mtr, dict_index_t* index, bool pessimistic) log_free_check(); } -#include "row0row.ic" +#include "row0row.inl" #endif diff --git a/storage/innobase/include/row0row.ic b/storage/innobase/include/row0row.ic deleted file mode 100644 index a3dd51aaac2..00000000000 --- a/storage/innobase/include/row0row.ic +++ /dev/null @@ -1,224 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 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/row0row.ic -General row routines - -Created 4/20/1996 Heikki Tuuri -*******************************************************/ - -#include "dict0dict.h" -#include "rem0rec.h" -#include "trx0undo.h" - -/*********************************************************************//** -Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of -a clustered index record. -@return offset of DATA_TRX_ID */ -UNIV_INLINE -ulint -row_get_trx_id_offset( -/*==================*/ - const dict_index_t* index, /*!< in: clustered index */ - const rec_offs* 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); - - ut_ad(len == DATA_TRX_ID_LEN); - - return(offset); -} - -/*********************************************************************//** -Reads the trx id field from a clustered index record. -@return value of the field */ -UNIV_INLINE -trx_id_t -row_get_rec_trx_id( -/*===============*/ - const rec_t* rec, /*!< in: record */ - const dict_index_t* index, /*!< in: clustered index */ - const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ -{ - ulint offset; - - ut_ad(dict_index_is_clust(index)); - ut_ad(rec_offs_validate(rec, index, offsets)); - - offset = index->trx_id_offset; - - if (!offset) { - offset = row_get_trx_id_offset(index, offsets); - } - - return(trx_read_trx_id(rec + offset)); -} - -/*********************************************************************//** -Reads the roll pointer field from a clustered index record. -@return value of the field */ -UNIV_INLINE -roll_ptr_t -row_get_rec_roll_ptr( -/*=================*/ - const rec_t* rec, /*!< in: record */ - const dict_index_t* index, /*!< in: clustered index */ - const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ -{ - ulint offset; - - ut_ad(dict_index_is_clust(index)); - ut_ad(rec_offs_validate(rec, index, offsets)); - - offset = index->trx_id_offset; - - if (!offset) { - offset = row_get_trx_id_offset(index, offsets); - } - - return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN)); -} - -/*****************************************************************//** -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. -@return index entry which should be inserted or purged, or NULL if the -externally stored columns in the clustered index record are -unavailable and ext != NULL */ -UNIV_INLINE -dtuple_t* -row_build_index_entry( -/*==================*/ - const dtuple_t* row, /*!< in: row which should be - inserted or purged */ - const row_ext_t* ext, /*!< in: externally stored column - prefixes, or NULL */ - dict_index_t* index, /*!< in: index on the table */ - mem_heap_t* heap) /*!< in: memory heap from which - the memory for the index entry - is allocated */ -{ - dtuple_t* entry; - - ut_ad(dtuple_check_typed(row)); - entry = row_build_index_entry_low(row, ext, index, heap, - ROW_BUILD_NORMAL); - ut_ad(!entry || dtuple_check_typed(entry)); - return(entry); -} - -/*******************************************************************//** -Builds from a secondary index record a row reference with which we can -search the clustered index record. */ -UNIV_INLINE -void -row_build_row_ref_fast( -/*===================*/ - dtuple_t* ref, /*!< in/out: typed data tuple where the - reference is built */ - const ulint* map, /*!< in: array of field numbers in rec - telling how ref should be built from - the fields of rec */ - const rec_t* rec, /*!< in: record in the index; must be - preserved while ref is used, as we do - not copy field values to heap */ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - dfield_t* dfield; - const byte* field; - ulint len; - ulint ref_len; - ulint field_no; - ulint i; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - ut_ad(!rec_offs_any_extern(offsets)); - ref_len = dtuple_get_n_fields(ref); - - for (i = 0; i < ref_len; i++) { - dfield = dtuple_get_nth_field(ref, i); - - field_no = *(map + i); - - if (field_no != ULINT_UNDEFINED) { - - field = rec_get_nth_field(rec, offsets, - field_no, &len); - dfield_set_data(dfield, field, len); - } - } -} - -/** Parse the integer data from specified data, which could be -DATA_INT, DATA_FLOAT or DATA_DOUBLE. If the value is less than 0 -and the type is not unsigned then we reset the value to 0 -@param[in] data data to read -@param[in] len length of data -@param[in] mtype mtype of data -@param[in] unsigned_type if the data is unsigned -@return the integer value from the data */ -ib_uint64_t -row_parse_int( - const byte* data, - ulint len, - ulint mtype, - bool unsigned_type) -{ - ib_uint64_t value = 0; - - switch (mtype) { - case DATA_INT: - - ut_a(len <= sizeof value); - value = mach_read_int_type(data, len, unsigned_type); - break; - - case DATA_FLOAT: - - ut_a(len == sizeof(float)); - value = static_cast(mach_float_read(data)); - break; - - case DATA_DOUBLE: - - ut_a(len == sizeof(double)); - value = static_cast(mach_double_read(data)); - break; - - default: - ut_error; - - } - - if (!unsigned_type && static_cast(value) < 0) { - value = 0; - } - - return(value); -} - diff --git a/storage/innobase/include/row0row.inl b/storage/innobase/include/row0row.inl new file mode 100644 index 00000000000..a3dd51aaac2 --- /dev/null +++ b/storage/innobase/include/row0row.inl @@ -0,0 +1,224 @@ +/***************************************************************************** + +Copyright (c) 1996, 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/row0row.ic +General row routines + +Created 4/20/1996 Heikki Tuuri +*******************************************************/ + +#include "dict0dict.h" +#include "rem0rec.h" +#include "trx0undo.h" + +/*********************************************************************//** +Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of +a clustered index record. +@return offset of DATA_TRX_ID */ +UNIV_INLINE +ulint +row_get_trx_id_offset( +/*==================*/ + const dict_index_t* index, /*!< in: clustered index */ + const rec_offs* 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); + + ut_ad(len == DATA_TRX_ID_LEN); + + return(offset); +} + +/*********************************************************************//** +Reads the trx id field from a clustered index record. +@return value of the field */ +UNIV_INLINE +trx_id_t +row_get_rec_trx_id( +/*===============*/ + const rec_t* rec, /*!< in: record */ + const dict_index_t* index, /*!< in: clustered index */ + const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ +{ + ulint offset; + + ut_ad(dict_index_is_clust(index)); + ut_ad(rec_offs_validate(rec, index, offsets)); + + offset = index->trx_id_offset; + + if (!offset) { + offset = row_get_trx_id_offset(index, offsets); + } + + return(trx_read_trx_id(rec + offset)); +} + +/*********************************************************************//** +Reads the roll pointer field from a clustered index record. +@return value of the field */ +UNIV_INLINE +roll_ptr_t +row_get_rec_roll_ptr( +/*=================*/ + const rec_t* rec, /*!< in: record */ + const dict_index_t* index, /*!< in: clustered index */ + const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ +{ + ulint offset; + + ut_ad(dict_index_is_clust(index)); + ut_ad(rec_offs_validate(rec, index, offsets)); + + offset = index->trx_id_offset; + + if (!offset) { + offset = row_get_trx_id_offset(index, offsets); + } + + return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN)); +} + +/*****************************************************************//** +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. +@return index entry which should be inserted or purged, or NULL if the +externally stored columns in the clustered index record are +unavailable and ext != NULL */ +UNIV_INLINE +dtuple_t* +row_build_index_entry( +/*==================*/ + const dtuple_t* row, /*!< in: row which should be + inserted or purged */ + const row_ext_t* ext, /*!< in: externally stored column + prefixes, or NULL */ + dict_index_t* index, /*!< in: index on the table */ + mem_heap_t* heap) /*!< in: memory heap from which + the memory for the index entry + is allocated */ +{ + dtuple_t* entry; + + ut_ad(dtuple_check_typed(row)); + entry = row_build_index_entry_low(row, ext, index, heap, + ROW_BUILD_NORMAL); + ut_ad(!entry || dtuple_check_typed(entry)); + return(entry); +} + +/*******************************************************************//** +Builds from a secondary index record a row reference with which we can +search the clustered index record. */ +UNIV_INLINE +void +row_build_row_ref_fast( +/*===================*/ + dtuple_t* ref, /*!< in/out: typed data tuple where the + reference is built */ + const ulint* map, /*!< in: array of field numbers in rec + telling how ref should be built from + the fields of rec */ + const rec_t* rec, /*!< in: record in the index; must be + preserved while ref is used, as we do + not copy field values to heap */ + const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +{ + dfield_t* dfield; + const byte* field; + ulint len; + ulint ref_len; + ulint field_no; + ulint i; + + ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_offs_any_extern(offsets)); + ref_len = dtuple_get_n_fields(ref); + + for (i = 0; i < ref_len; i++) { + dfield = dtuple_get_nth_field(ref, i); + + field_no = *(map + i); + + if (field_no != ULINT_UNDEFINED) { + + field = rec_get_nth_field(rec, offsets, + field_no, &len); + dfield_set_data(dfield, field, len); + } + } +} + +/** Parse the integer data from specified data, which could be +DATA_INT, DATA_FLOAT or DATA_DOUBLE. If the value is less than 0 +and the type is not unsigned then we reset the value to 0 +@param[in] data data to read +@param[in] len length of data +@param[in] mtype mtype of data +@param[in] unsigned_type if the data is unsigned +@return the integer value from the data */ +ib_uint64_t +row_parse_int( + const byte* data, + ulint len, + ulint mtype, + bool unsigned_type) +{ + ib_uint64_t value = 0; + + switch (mtype) { + case DATA_INT: + + ut_a(len <= sizeof value); + value = mach_read_int_type(data, len, unsigned_type); + break; + + case DATA_FLOAT: + + ut_a(len == sizeof(float)); + value = static_cast(mach_float_read(data)); + break; + + case DATA_DOUBLE: + + ut_a(len == sizeof(double)); + value = static_cast(mach_double_read(data)); + break; + + default: + ut_error; + + } + + if (!unsigned_type && static_cast(value) < 0) { + value = 0; + } + + return(value); +} + diff --git a/storage/innobase/include/row0sel.h b/storage/innobase/include/row0sel.h index d9c08243a91..9b629d28b50 100644 --- a/storage/innobase/include/row0sel.h +++ b/storage/innobase/include/row0sel.h @@ -478,6 +478,6 @@ row_sel_field_store_in_mysql_format_func( const byte* data, /*!< in: data to store */ ulint len); /*!< in: length of the data */ -#include "row0sel.ic" +#include "row0sel.inl" #endif diff --git a/storage/innobase/include/row0sel.ic b/storage/innobase/include/row0sel.ic deleted file mode 100644 index 7880605ca8f..00000000000 --- a/storage/innobase/include/row0sel.ic +++ /dev/null @@ -1,138 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1997, 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/row0sel.ic -Select - -Created 12/19/1997 Heikki Tuuri -*******************************************************/ - -#include "que0que.h" - -/*********************************************************************//** -Gets the plan node for the nth table in a join. -@return plan node */ -UNIV_INLINE -plan_t* -sel_node_get_nth_plan( -/*==================*/ - sel_node_t* node, /*!< in: select node */ - ulint i) /*!< in: get ith plan node */ -{ - ut_ad(i < node->n_tables); - - return(node->plans + i); -} - -/*********************************************************************//** -Resets the cursor defined by sel_node to the SEL_NODE_OPEN state, which means -that it will start fetching from the start of the result set again, regardless -of where it was before, and it will set intention locks on the tables. */ -UNIV_INLINE -void -sel_node_reset_cursor( -/*==================*/ - sel_node_t* node) /*!< in: select node */ -{ - node->state = SEL_NODE_OPEN; -} - -/**********************************************************************//** -Performs an execution step of an open or close cursor statement node. -@return query thread to run next or NULL */ -UNIV_INLINE -que_thr_t* -open_step( -/*======*/ - que_thr_t* thr) /*!< in: query thread */ -{ - sel_node_t* sel_node; - open_node_t* node; - ulint err; - - ut_ad(thr); - - node = (open_node_t*) thr->run_node; - ut_ad(que_node_get_type(node) == QUE_NODE_OPEN); - - sel_node = node->cursor_def; - - err = DB_SUCCESS; - - if (node->op_type == ROW_SEL_OPEN_CURSOR) { - - /* if (sel_node->state == SEL_NODE_CLOSED) { */ - - sel_node_reset_cursor(sel_node); - /* } else { - err = DB_ERROR; - } */ - } else { - if (sel_node->state != SEL_NODE_CLOSED) { - - sel_node->state = SEL_NODE_CLOSED; - } else { - err = DB_ERROR; - } - } - - if (err != DB_SUCCESS) { - /* SQL error detected */ - fprintf(stderr, "SQL error %lu\n", (ulong) err); - - ut_error; - } - - thr->run_node = que_node_get_parent(node); - - return(thr); -} - - -/** Searches for rows in the database. This is used in the interface to -MySQL. This function opens a cursor, and also implements fetch next -and fetch prev. NOTE that if we do a search with a full key value -from a unique index (ROW_SEL_EXACT), then we will not store the cursor -position and fetch next or fetch prev must not be tried to the cursor! - -@param[out] buf buffer for the fetched row in MySQL format -@param[in] mode search mode PAGE_CUR_L -@param[in,out] prebuilt prebuilt struct for the table handler; - this contains the info to search_tuple, - index; if search tuple contains 0 field then - we position the cursor at start or the end of - index, depending on 'mode' -@param[in] match_mode 0 or ROW_SEL_EXACT or ROW_SEL_EXACT_PREFIX -@param[in] direction 0 or ROW_SEL_NEXT or ROW_SEL_PREV; - Note: if this is != 0, then prebuilt must has a - pcur with stored position! In opening of a - cursor 'direction' should be 0. -@return DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK, -DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */ -UNIV_INLINE -dberr_t -row_search_for_mysql( - byte* buf, - page_cur_mode_t mode, - row_prebuilt_t* prebuilt, - ulint match_mode, - ulint direction) -{ - return(row_search_mvcc(buf, mode, prebuilt, match_mode, direction)); -} diff --git a/storage/innobase/include/row0sel.inl b/storage/innobase/include/row0sel.inl new file mode 100644 index 00000000000..7880605ca8f --- /dev/null +++ b/storage/innobase/include/row0sel.inl @@ -0,0 +1,138 @@ +/***************************************************************************** + +Copyright (c) 1997, 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/row0sel.ic +Select + +Created 12/19/1997 Heikki Tuuri +*******************************************************/ + +#include "que0que.h" + +/*********************************************************************//** +Gets the plan node for the nth table in a join. +@return plan node */ +UNIV_INLINE +plan_t* +sel_node_get_nth_plan( +/*==================*/ + sel_node_t* node, /*!< in: select node */ + ulint i) /*!< in: get ith plan node */ +{ + ut_ad(i < node->n_tables); + + return(node->plans + i); +} + +/*********************************************************************//** +Resets the cursor defined by sel_node to the SEL_NODE_OPEN state, which means +that it will start fetching from the start of the result set again, regardless +of where it was before, and it will set intention locks on the tables. */ +UNIV_INLINE +void +sel_node_reset_cursor( +/*==================*/ + sel_node_t* node) /*!< in: select node */ +{ + node->state = SEL_NODE_OPEN; +} + +/**********************************************************************//** +Performs an execution step of an open or close cursor statement node. +@return query thread to run next or NULL */ +UNIV_INLINE +que_thr_t* +open_step( +/*======*/ + que_thr_t* thr) /*!< in: query thread */ +{ + sel_node_t* sel_node; + open_node_t* node; + ulint err; + + ut_ad(thr); + + node = (open_node_t*) thr->run_node; + ut_ad(que_node_get_type(node) == QUE_NODE_OPEN); + + sel_node = node->cursor_def; + + err = DB_SUCCESS; + + if (node->op_type == ROW_SEL_OPEN_CURSOR) { + + /* if (sel_node->state == SEL_NODE_CLOSED) { */ + + sel_node_reset_cursor(sel_node); + /* } else { + err = DB_ERROR; + } */ + } else { + if (sel_node->state != SEL_NODE_CLOSED) { + + sel_node->state = SEL_NODE_CLOSED; + } else { + err = DB_ERROR; + } + } + + if (err != DB_SUCCESS) { + /* SQL error detected */ + fprintf(stderr, "SQL error %lu\n", (ulong) err); + + ut_error; + } + + thr->run_node = que_node_get_parent(node); + + return(thr); +} + + +/** Searches for rows in the database. This is used in the interface to +MySQL. This function opens a cursor, and also implements fetch next +and fetch prev. NOTE that if we do a search with a full key value +from a unique index (ROW_SEL_EXACT), then we will not store the cursor +position and fetch next or fetch prev must not be tried to the cursor! + +@param[out] buf buffer for the fetched row in MySQL format +@param[in] mode search mode PAGE_CUR_L +@param[in,out] prebuilt prebuilt struct for the table handler; + this contains the info to search_tuple, + index; if search tuple contains 0 field then + we position the cursor at start or the end of + index, depending on 'mode' +@param[in] match_mode 0 or ROW_SEL_EXACT or ROW_SEL_EXACT_PREFIX +@param[in] direction 0 or ROW_SEL_NEXT or ROW_SEL_PREV; + Note: if this is != 0, then prebuilt must has a + pcur with stored position! In opening of a + cursor 'direction' should be 0. +@return DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK, +DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */ +UNIV_INLINE +dberr_t +row_search_for_mysql( + byte* buf, + page_cur_mode_t mode, + row_prebuilt_t* prebuilt, + ulint match_mode, + ulint direction) +{ + return(row_search_mvcc(buf, mode, prebuilt, match_mode, direction)); +} diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index b60770b01fb..e2440765382 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -583,6 +583,6 @@ struct upd_node_t{ changed in the update */ -#include "row0upd.ic" +#include "row0upd.inl" #endif diff --git a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic deleted file mode 100644 index 07e1c13d771..00000000000 --- a/storage/innobase/include/row0upd.ic +++ /dev/null @@ -1,198 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -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 -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/row0upd.ic -Update of a row - -Created 12/27/1996 Heikki Tuuri -*******************************************************/ - -#include "mtr0log.h" -#include "trx0trx.h" -#include "trx0undo.h" -#include "row0row.h" -#include "lock0lock.h" -#include "page0zip.h" - -/*********************************************************************//** -Creates an update vector object. -@return own: update vector object */ -UNIV_INLINE -upd_t* -upd_create( -/*=======*/ - ulint n, /*!< in: number of fields */ - mem_heap_t* heap) /*!< in: heap from which memory allocated */ -{ - upd_t* update; - - update = static_cast(mem_heap_zalloc( - heap, sizeof(upd_t) + sizeof(upd_field_t) * n)); - - update->n_fields = n; - update->fields = reinterpret_cast(&update[1]); - update->heap = heap; - - return(update); -} - -/*********************************************************************//** -Returns the number of fields in the update vector == number of columns -to be updated by an update vector. -@return number of fields */ -UNIV_INLINE -ulint -upd_get_n_fields( -/*=============*/ - const upd_t* update) /*!< in: update vector */ -{ - ut_ad(update); - - return(update->n_fields); -} - -#ifdef UNIV_DEBUG -/*********************************************************************//** -Returns the nth field of an update vector. -@return update vector field */ -UNIV_INLINE -upd_field_t* -upd_get_nth_field( -/*==============*/ - const upd_t* update, /*!< in: update vector */ - ulint n) /*!< in: field position in update vector */ -{ - ut_ad(update); - ut_ad(n < update->n_fields); - - return((upd_field_t*) update->fields + n); -} -#endif /* UNIV_DEBUG */ - -/*********************************************************************//** -Sets an index field number to be updated by an update vector field. */ -UNIV_INLINE -void -upd_field_set_field_no( -/*===================*/ - upd_field_t* upd_field, /*!< in: update vector field */ - ulint field_no, /*!< in: field number in a clustered - index */ - dict_index_t* index) /*!< in: index */ -{ - upd_field->field_no = unsigned(field_no); - upd_field->orig_len = 0; - dict_col_copy_type(dict_index_get_nth_col(index, field_no), - dfield_get_type(&upd_field->new_val)); -} - -/** set field number to a update vector field, marks this field is updated. -@param[in,out] upd_field update vector field -@param[in] field_no virtual column sequence num -@param[in] index index */ -UNIV_INLINE -void -upd_field_set_v_field_no( - upd_field_t* upd_field, - ulint field_no, - dict_index_t* index) -{ - ut_a(field_no < dict_table_get_n_v_cols(index->table)); - upd_field->field_no = unsigned(field_no); - upd_field->orig_len = 0; - - dict_col_copy_type(&dict_table_get_nth_v_col( - index->table, field_no)->m_col, - dfield_get_type(&upd_field->new_val)); -} - -/*********************************************************************//** -Returns a field of an update vector by field_no. -@return update vector field, or NULL */ -UNIV_INLINE -const upd_field_t* -upd_get_field_by_field_no( -/*======================*/ - const upd_t* update, /*!< in: update vector */ - ulint no, /*!< in: field_no */ - bool is_virtual) /*!< in: if it is virtual column */ -{ - ulint i; - for (i = 0; i < upd_get_n_fields(update); i++) { - const upd_field_t* uf = upd_get_nth_field(update, i); - - /* matches only if the field matches that of is_virtual */ - if ((!is_virtual) != (!upd_fld_is_virtual_col(uf))) { - continue; - } - - if (uf->field_no == no) { - - return(uf); - } - } - - return(NULL); -} - -/*********************************************************************//** -Updates the trx id and roll ptr field in a clustered index record when -a row is updated or marked deleted. */ -UNIV_INLINE -void -row_upd_rec_sys_fields( -/*===================*/ - rec_t* rec, /*!< in/out: record */ - page_zip_des_t* page_zip,/*!< in/out: compressed page whose - uncompressed part will be updated, or NULL */ - dict_index_t* index, /*!< in: clustered index */ - const rec_offs* offsets,/*!< in: rec_get_offsets(rec, index) */ - 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(rec_offs_validate(rec, index, offsets)); - - if (page_zip) { - ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); - page_zip_write_trx_id_and_roll_ptr(page_zip, rec, offsets, - pos, trx->id, roll_ptr); - } else { - ulint offset = index->trx_id_offset; - - if (!offset) { - offset = row_get_trx_id_offset(index, offsets); - } - -#if DATA_TRX_ID + 1 != DATA_ROLL_PTR -# error "DATA_TRX_ID + 1 != DATA_ROLL_PTR" -#endif - /* During IMPORT the trx id in the record can be in the - future, if the .ibd file is being imported from another - instance. During IMPORT roll_ptr will be 0. */ - ut_ad(roll_ptr == 0 - || lock_check_trx_id_sanity( - trx_read_trx_id(rec + offset), - rec, index, offsets)); - - trx_write_trx_id(rec + offset, trx->id); - trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr); - } -} diff --git a/storage/innobase/include/row0upd.inl b/storage/innobase/include/row0upd.inl new file mode 100644 index 00000000000..07e1c13d771 --- /dev/null +++ b/storage/innobase/include/row0upd.inl @@ -0,0 +1,198 @@ +/***************************************************************************** + +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +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 +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/row0upd.ic +Update of a row + +Created 12/27/1996 Heikki Tuuri +*******************************************************/ + +#include "mtr0log.h" +#include "trx0trx.h" +#include "trx0undo.h" +#include "row0row.h" +#include "lock0lock.h" +#include "page0zip.h" + +/*********************************************************************//** +Creates an update vector object. +@return own: update vector object */ +UNIV_INLINE +upd_t* +upd_create( +/*=======*/ + ulint n, /*!< in: number of fields */ + mem_heap_t* heap) /*!< in: heap from which memory allocated */ +{ + upd_t* update; + + update = static_cast(mem_heap_zalloc( + heap, sizeof(upd_t) + sizeof(upd_field_t) * n)); + + update->n_fields = n; + update->fields = reinterpret_cast(&update[1]); + update->heap = heap; + + return(update); +} + +/*********************************************************************//** +Returns the number of fields in the update vector == number of columns +to be updated by an update vector. +@return number of fields */ +UNIV_INLINE +ulint +upd_get_n_fields( +/*=============*/ + const upd_t* update) /*!< in: update vector */ +{ + ut_ad(update); + + return(update->n_fields); +} + +#ifdef UNIV_DEBUG +/*********************************************************************//** +Returns the nth field of an update vector. +@return update vector field */ +UNIV_INLINE +upd_field_t* +upd_get_nth_field( +/*==============*/ + const upd_t* update, /*!< in: update vector */ + ulint n) /*!< in: field position in update vector */ +{ + ut_ad(update); + ut_ad(n < update->n_fields); + + return((upd_field_t*) update->fields + n); +} +#endif /* UNIV_DEBUG */ + +/*********************************************************************//** +Sets an index field number to be updated by an update vector field. */ +UNIV_INLINE +void +upd_field_set_field_no( +/*===================*/ + upd_field_t* upd_field, /*!< in: update vector field */ + ulint field_no, /*!< in: field number in a clustered + index */ + dict_index_t* index) /*!< in: index */ +{ + upd_field->field_no = unsigned(field_no); + upd_field->orig_len = 0; + dict_col_copy_type(dict_index_get_nth_col(index, field_no), + dfield_get_type(&upd_field->new_val)); +} + +/** set field number to a update vector field, marks this field is updated. +@param[in,out] upd_field update vector field +@param[in] field_no virtual column sequence num +@param[in] index index */ +UNIV_INLINE +void +upd_field_set_v_field_no( + upd_field_t* upd_field, + ulint field_no, + dict_index_t* index) +{ + ut_a(field_no < dict_table_get_n_v_cols(index->table)); + upd_field->field_no = unsigned(field_no); + upd_field->orig_len = 0; + + dict_col_copy_type(&dict_table_get_nth_v_col( + index->table, field_no)->m_col, + dfield_get_type(&upd_field->new_val)); +} + +/*********************************************************************//** +Returns a field of an update vector by field_no. +@return update vector field, or NULL */ +UNIV_INLINE +const upd_field_t* +upd_get_field_by_field_no( +/*======================*/ + const upd_t* update, /*!< in: update vector */ + ulint no, /*!< in: field_no */ + bool is_virtual) /*!< in: if it is virtual column */ +{ + ulint i; + for (i = 0; i < upd_get_n_fields(update); i++) { + const upd_field_t* uf = upd_get_nth_field(update, i); + + /* matches only if the field matches that of is_virtual */ + if ((!is_virtual) != (!upd_fld_is_virtual_col(uf))) { + continue; + } + + if (uf->field_no == no) { + + return(uf); + } + } + + return(NULL); +} + +/*********************************************************************//** +Updates the trx id and roll ptr field in a clustered index record when +a row is updated or marked deleted. */ +UNIV_INLINE +void +row_upd_rec_sys_fields( +/*===================*/ + rec_t* rec, /*!< in/out: record */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose + uncompressed part will be updated, or NULL */ + dict_index_t* index, /*!< in: clustered index */ + const rec_offs* offsets,/*!< in: rec_get_offsets(rec, index) */ + 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(rec_offs_validate(rec, index, offsets)); + + if (page_zip) { + ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); + page_zip_write_trx_id_and_roll_ptr(page_zip, rec, offsets, + pos, trx->id, roll_ptr); + } else { + ulint offset = index->trx_id_offset; + + if (!offset) { + offset = row_get_trx_id_offset(index, offsets); + } + +#if DATA_TRX_ID + 1 != DATA_ROLL_PTR +# error "DATA_TRX_ID + 1 != DATA_ROLL_PTR" +#endif + /* During IMPORT the trx id in the record can be in the + future, if the .ibd file is being imported from another + instance. During IMPORT roll_ptr will be 0. */ + ut_ad(roll_ptr == 0 + || lock_check_trx_id_sanity( + trx_read_trx_id(rec + offset), + rec, index, offsets)); + + trx_write_trx_id(rec + offset, trx->id); + trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr); + } +} diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index ccc70206ede..7d30ee111a6 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -902,6 +902,6 @@ void srv_mon_default_on(void); /*====================*/ -#include "srv0mon.ic" +#include "srv0mon.inl" #endif diff --git a/storage/innobase/include/srv0mon.ic b/storage/innobase/include/srv0mon.ic deleted file mode 100644 index 158345b2f8c..00000000000 --- a/storage/innobase/include/srv0mon.ic +++ /dev/null @@ -1,113 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2010, 2013, 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/srv0mon.ic -Server monitoring system - -Created 1/20/2010 Jimmy Yang -************************************************************************/ - -/*************************************************************//** -This function is used to calculate the maximum counter value -since the start of monitor counter -@return max counter value since start. */ -UNIV_INLINE -mon_type_t -srv_mon_calc_max_since_start( -/*=========================*/ - monitor_id_t monitor) /*!< in: monitor id */ -{ - if (MONITOR_MAX_VALUE_START(monitor) == MAX_RESERVED) { - - /* MONITOR_MAX_VALUE_START has not yet been - initialized, the max value since start is the - max count in MONITOR_MAX_VALUE */ - MONITOR_MAX_VALUE_START(monitor) = - MONITOR_MAX_VALUE(monitor); - - } else if (MONITOR_MAX_VALUE(monitor) != MAX_RESERVED - && (MONITOR_MAX_VALUE(monitor) - + MONITOR_VALUE_RESET(monitor) - > MONITOR_MAX_VALUE_START(monitor))) { - - /* If the max value since reset (as specified - in MONITOR_MAX_VALUE) plus the reset value is - larger than MONITOR_MAX_VALUE_START, reset - MONITOR_MAX_VALUE_START to this new max value */ - MONITOR_MAX_VALUE_START(monitor) = - MONITOR_MAX_VALUE(monitor) - + MONITOR_VALUE_RESET(monitor); - } - - return(MONITOR_MAX_VALUE_START(monitor)); -} - -/*************************************************************//** -This function is used to calculate the minimum counter value -since the start of monitor counter -@return min counter value since start. */ -UNIV_INLINE -mon_type_t -srv_mon_calc_min_since_start( -/*=========================*/ - monitor_id_t monitor) /*!< in: monitor id */ -{ - if (MONITOR_MIN_VALUE_START(monitor) == MIN_RESERVED) { - - /* MONITOR_MIN_VALUE_START has not yet been - initialized, the min value since start is the - min count in MONITOR_MIN_VALUE */ - MONITOR_MIN_VALUE_START(monitor) = - MONITOR_MIN_VALUE(monitor); - - } else if (MONITOR_MIN_VALUE(monitor) != MIN_RESERVED - && (MONITOR_MIN_VALUE(monitor) - + MONITOR_VALUE_RESET(monitor) - < MONITOR_MIN_VALUE_START(monitor))) { - - /* If the min value since reset (as specified - in MONITOR_MIN_VALUE) plus the reset value is - less than MONITOR_MIN_VALUE_START, reset - MONITOR_MIN_VALUE_START to this new min value */ - MONITOR_MIN_VALUE_START(monitor) = - MONITOR_MIN_VALUE(monitor) - + MONITOR_VALUE_RESET(monitor); - } - - return(MONITOR_MIN_VALUE_START(monitor)); -} - -/*************************************************************//** -This function resets all values of a monitor counter */ -UNIV_INLINE -void -srv_mon_reset_all( -/*==============*/ - monitor_id_t monitor) /*!< in: monitor id */ -{ - /* Do not reset all counter values if monitor is still on. */ - if (MONITOR_IS_ON(monitor)) { - fprintf(stderr, "InnoDB: Cannot reset all values for" - " monitor counter %s while it is on. Please" - " turn it off and retry.\n", - srv_mon_get_name(monitor)); - } else { - MONITOR_RESET_ALL(monitor); - } -} diff --git a/storage/innobase/include/srv0mon.inl b/storage/innobase/include/srv0mon.inl new file mode 100644 index 00000000000..158345b2f8c --- /dev/null +++ b/storage/innobase/include/srv0mon.inl @@ -0,0 +1,113 @@ +/***************************************************************************** + +Copyright (c) 2010, 2013, 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/srv0mon.ic +Server monitoring system + +Created 1/20/2010 Jimmy Yang +************************************************************************/ + +/*************************************************************//** +This function is used to calculate the maximum counter value +since the start of monitor counter +@return max counter value since start. */ +UNIV_INLINE +mon_type_t +srv_mon_calc_max_since_start( +/*=========================*/ + monitor_id_t monitor) /*!< in: monitor id */ +{ + if (MONITOR_MAX_VALUE_START(monitor) == MAX_RESERVED) { + + /* MONITOR_MAX_VALUE_START has not yet been + initialized, the max value since start is the + max count in MONITOR_MAX_VALUE */ + MONITOR_MAX_VALUE_START(monitor) = + MONITOR_MAX_VALUE(monitor); + + } else if (MONITOR_MAX_VALUE(monitor) != MAX_RESERVED + && (MONITOR_MAX_VALUE(monitor) + + MONITOR_VALUE_RESET(monitor) + > MONITOR_MAX_VALUE_START(monitor))) { + + /* If the max value since reset (as specified + in MONITOR_MAX_VALUE) plus the reset value is + larger than MONITOR_MAX_VALUE_START, reset + MONITOR_MAX_VALUE_START to this new max value */ + MONITOR_MAX_VALUE_START(monitor) = + MONITOR_MAX_VALUE(monitor) + + MONITOR_VALUE_RESET(monitor); + } + + return(MONITOR_MAX_VALUE_START(monitor)); +} + +/*************************************************************//** +This function is used to calculate the minimum counter value +since the start of monitor counter +@return min counter value since start. */ +UNIV_INLINE +mon_type_t +srv_mon_calc_min_since_start( +/*=========================*/ + monitor_id_t monitor) /*!< in: monitor id */ +{ + if (MONITOR_MIN_VALUE_START(monitor) == MIN_RESERVED) { + + /* MONITOR_MIN_VALUE_START has not yet been + initialized, the min value since start is the + min count in MONITOR_MIN_VALUE */ + MONITOR_MIN_VALUE_START(monitor) = + MONITOR_MIN_VALUE(monitor); + + } else if (MONITOR_MIN_VALUE(monitor) != MIN_RESERVED + && (MONITOR_MIN_VALUE(monitor) + + MONITOR_VALUE_RESET(monitor) + < MONITOR_MIN_VALUE_START(monitor))) { + + /* If the min value since reset (as specified + in MONITOR_MIN_VALUE) plus the reset value is + less than MONITOR_MIN_VALUE_START, reset + MONITOR_MIN_VALUE_START to this new min value */ + MONITOR_MIN_VALUE_START(monitor) = + MONITOR_MIN_VALUE(monitor) + + MONITOR_VALUE_RESET(monitor); + } + + return(MONITOR_MIN_VALUE_START(monitor)); +} + +/*************************************************************//** +This function resets all values of a monitor counter */ +UNIV_INLINE +void +srv_mon_reset_all( +/*==============*/ + monitor_id_t monitor) /*!< in: monitor id */ +{ + /* Do not reset all counter values if monitor is still on. */ + if (MONITOR_IS_ON(monitor)) { + fprintf(stderr, "InnoDB: Cannot reset all values for" + " monitor counter %s while it is on. Please" + " turn it off and retry.\n", + srv_mon_get_name(monitor)); + } else { + MONITOR_RESET_ALL(monitor); + } +} diff --git a/storage/innobase/include/sync0arr.h b/storage/innobase/include/sync0arr.h index 7a8366b933b..7a71f3a54c3 100644 --- a/storage/innobase/include/sync0arr.h +++ b/storage/innobase/include/sync0arr.h @@ -130,6 +130,6 @@ sync_array_get_nth_cell( sync_array_t* arr, /*!< in: sync array */ ulint n); /*!< in: index */ -#include "sync0arr.ic" +#include "sync0arr.inl" #endif /* sync0arr_h */ diff --git a/storage/innobase/include/sync0arr.ic b/storage/innobase/include/sync0arr.ic deleted file mode 100644 index 9163d5b6614..00000000000 --- a/storage/innobase/include/sync0arr.ic +++ /dev/null @@ -1,86 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 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/sync0arr.ic -The wait array for synchronization primitives - -Inline code - -Created 9/5/1995 Heikki Tuuri -*******************************************************/ - -extern ulint sync_array_size; -extern sync_array_t** sync_wait_array; - -#include "ut0counter.h" - -/**********************************************************************//** -Get an instance of the sync wait array. -@return an instance of the sync wait array. */ - -UNIV_INLINE -sync_array_t* -sync_array_get() -/*============*/ -{ - if (sync_array_size <= 1) { - return(sync_wait_array[0]); - } - - return(sync_wait_array[default_indexer_t<>::get_rnd_index() - % sync_array_size]); -} - -/******************************************************************//** -Get an instance of the sync wait array and reserve a wait array cell -in the instance for waiting for an object. The event of the cell is -reset to nonsignalled state. -If reserving cell of the instance fails, try to get another new -instance until we can reserve an empty cell of it. -@return the sync array reserved, never NULL. */ -UNIV_INLINE -sync_array_t* -sync_array_get_and_reserve_cell( -/*============================*/ - void* object, /*!< in: pointer to the object to wait for */ - ulint type, /*!< in: lock request type */ - const char* file, /*!< in: file where requested */ - unsigned line, /*!< in: line where requested */ - sync_cell_t** cell) /*!< out: the cell reserved, never NULL */ -{ - sync_array_t* sync_arr = NULL; - - *cell = NULL; - for (ulint i = 0; i < sync_array_size && *cell == NULL; ++i) { - /* Although the sync_array is get in a random way currently, - we still try at most sync_array_size times, in case any - of the sync_array we get is full */ - sync_arr = sync_array_get(); - *cell = sync_array_reserve_cell(sync_arr, object, type, - file, line); - } - - /* This won't be true every time, for the loop above may execute - more than srv_sync_array_size times to reserve a cell. - But an assertion here makes the code more solid. */ - ut_a(*cell != NULL); - - return(sync_arr); -} diff --git a/storage/innobase/include/sync0arr.inl b/storage/innobase/include/sync0arr.inl new file mode 100644 index 00000000000..9163d5b6614 --- /dev/null +++ b/storage/innobase/include/sync0arr.inl @@ -0,0 +1,86 @@ +/***************************************************************************** + +Copyright (c) 1995, 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/sync0arr.ic +The wait array for synchronization primitives + +Inline code + +Created 9/5/1995 Heikki Tuuri +*******************************************************/ + +extern ulint sync_array_size; +extern sync_array_t** sync_wait_array; + +#include "ut0counter.h" + +/**********************************************************************//** +Get an instance of the sync wait array. +@return an instance of the sync wait array. */ + +UNIV_INLINE +sync_array_t* +sync_array_get() +/*============*/ +{ + if (sync_array_size <= 1) { + return(sync_wait_array[0]); + } + + return(sync_wait_array[default_indexer_t<>::get_rnd_index() + % sync_array_size]); +} + +/******************************************************************//** +Get an instance of the sync wait array and reserve a wait array cell +in the instance for waiting for an object. The event of the cell is +reset to nonsignalled state. +If reserving cell of the instance fails, try to get another new +instance until we can reserve an empty cell of it. +@return the sync array reserved, never NULL. */ +UNIV_INLINE +sync_array_t* +sync_array_get_and_reserve_cell( +/*============================*/ + void* object, /*!< in: pointer to the object to wait for */ + ulint type, /*!< in: lock request type */ + const char* file, /*!< in: file where requested */ + unsigned line, /*!< in: line where requested */ + sync_cell_t** cell) /*!< out: the cell reserved, never NULL */ +{ + sync_array_t* sync_arr = NULL; + + *cell = NULL; + for (ulint i = 0; i < sync_array_size && *cell == NULL; ++i) { + /* Although the sync_array is get in a random way currently, + we still try at most sync_array_size times, in case any + of the sync_array we get is full */ + sync_arr = sync_array_get(); + *cell = sync_array_reserve_cell(sync_arr, object, type, + file, line); + } + + /* This won't be true every time, for the loop above may execute + more than srv_sync_array_size times to reserve a cell. + But an assertion here makes the code more solid. */ + ut_a(*cell != NULL); + + return(sync_arr); +} diff --git a/storage/innobase/include/sync0policy.h b/storage/innobase/include/sync0policy.h index c7c348bd489..2e4da181f96 100644 --- a/storage/innobase/include/sync0policy.h +++ b/storage/innobase/include/sync0policy.h @@ -535,6 +535,6 @@ private: latch_id_t m_id; }; -#include "sync0policy.ic" +#include "sync0policy.inl" #endif /* sync0policy_h */ diff --git a/storage/innobase/include/sync0policy.ic b/storage/innobase/include/sync0policy.ic deleted file mode 100644 index b86dee0a3b8..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 -std::string GenericPolicy::to_string() const -{ - return(sync_mutex_to_string(get_id(), sync_file_created_get(this))); -} - -template -std::string BlockMutexPolicy::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 -void MutexDebug::init(latch_id_t id) - UNIV_NOTHROW -{ - m_context.m_id = id; - - m_context.release(); - - m_magic_n = MUTEX_MAGIC_N; -} - -template -void MutexDebug::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 -void MutexDebug::locked( - const Mutex* mutex, - const char* name, - unsigned line) - UNIV_NOTHROW -{ - ut_ad(!is_owned()); - ut_ad(m_context.m_thread_id == os_thread_id_t(ULINT_UNDEFINED)); - - m_context.locked(mutex, name, line); - - sync_check_lock_granted(&m_context); -} - -template -void MutexDebug::release(const Mutex* mutex) - UNIV_NOTHROW -{ - ut_ad(is_owned()); - - m_context.release(); - - sync_check_unlock(&m_context); -} - -#endif /* UNIV_DEBUG */ diff --git a/storage/innobase/include/sync0policy.inl b/storage/innobase/include/sync0policy.inl new file mode 100644 index 00000000000..b86dee0a3b8 --- /dev/null +++ b/storage/innobase/include/sync0policy.inl @@ -0,0 +1,101 @@ +/***************************************************************************** + +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 +std::string GenericPolicy::to_string() const +{ + return(sync_mutex_to_string(get_id(), sync_file_created_get(this))); +} + +template +std::string BlockMutexPolicy::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 +void MutexDebug::init(latch_id_t id) + UNIV_NOTHROW +{ + m_context.m_id = id; + + m_context.release(); + + m_magic_n = MUTEX_MAGIC_N; +} + +template +void MutexDebug::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 +void MutexDebug::locked( + const Mutex* mutex, + const char* name, + unsigned line) + UNIV_NOTHROW +{ + ut_ad(!is_owned()); + ut_ad(m_context.m_thread_id == os_thread_id_t(ULINT_UNDEFINED)); + + m_context.locked(mutex, name, line); + + sync_check_lock_granted(&m_context); +} + +template +void MutexDebug::release(const Mutex* 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 855d4439280..4c90349a2e3 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -843,6 +843,6 @@ pfs_rw_lock_free_func( rw_lock_t* lock); /*!< in: rw-lock */ #endif /* UNIV_PFS_RWLOCK */ -#include "sync0rw.ic" +#include "sync0rw.inl" #endif /* sync0rw.h */ diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic deleted file mode 100644 index d0be5f0ece1..00000000000 --- a/storage/innobase/include/sync0rw.ic +++ /dev/null @@ -1,838 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. - -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - -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/sync0rw.ic -The read-write lock (for threads) - -Created 9/11/1995 Heikki Tuuri -*******************************************************/ - -#include "os0event.h" - -/******************************************************************//** -Lock an rw-lock in shared mode for the current thread. If the rw-lock is -locked in exclusive mode, or there is an exclusive lock request waiting, -the function spins a preset time (controlled by srv_n_spin_wait_rounds), -waiting for the lock before suspending the thread. */ -void -rw_lock_s_lock_spin( -/*================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass, /*!< in: pass value; != 0, if the lock will - be passed to another thread to unlock */ - const char* file_name,/*!< in: file name where lock requested */ - unsigned line); /*!< in: line where requested */ -#ifdef UNIV_DEBUG -/******************************************************************//** -Inserts the debug information for an rw-lock. */ -void -rw_lock_add_debug_info( -/*===================*/ - rw_lock_t* lock, /*!< in: rw-lock */ - ulint pass, /*!< in: pass value */ - ulint lock_type, /*!< in: lock type */ - const char* file_name, /*!< in: file where requested */ - unsigned line); /*!< in: line where requested */ -/******************************************************************//** -Removes a debug information struct for an rw-lock. */ -void -rw_lock_remove_debug_info( -/*======================*/ - rw_lock_t* lock, /*!< in: rw-lock */ - ulint pass, /*!< in: pass value */ - ulint lock_type); /*!< in: lock type */ -#endif /* UNIV_DEBUG */ - -/******************************************************************//** -Returns the write-status of the lock - this function made more sense -with the old rw_lock implementation. -@return RW_LOCK_NOT_LOCKED, RW_LOCK_X, RW_LOCK_X_WAIT, RW_LOCK_SX */ -UNIV_INLINE -ulint -rw_lock_get_writer( -/*===============*/ - const rw_lock_t* lock) /*!< in: rw-lock */ -{ - lint lock_word = lock->lock_word; - - ut_ad(lock_word <= X_LOCK_DECR); - if (lock_word > X_LOCK_HALF_DECR) { - /* return NOT_LOCKED in s-lock state, like the writer - member of the old lock implementation. */ - return(RW_LOCK_NOT_LOCKED); - } else if (lock_word > 0) { - /* sx-locked, no x-locks */ - return(RW_LOCK_SX); - } else if (lock_word == 0 - || lock_word == -X_LOCK_HALF_DECR - || lock_word <= -X_LOCK_DECR) { - /* x-lock with sx-lock is also treated as RW_LOCK_EX */ - return(RW_LOCK_X); - } else { - /* x-waiter with sx-lock is also treated as RW_LOCK_WAIT_EX - e.g. -X_LOCK_HALF_DECR < lock_word < 0 : without sx - -X_LOCK_DECR < lock_word < -X_LOCK_HALF_DECR : with sx */ - return(RW_LOCK_X_WAIT); - } -} - -/******************************************************************//** -Returns the number of readers (s-locks). -@return number of readers */ -UNIV_INLINE -ulint -rw_lock_get_reader_count( -/*=====================*/ - const rw_lock_t* lock) /*!< in: rw-lock */ -{ - lint lock_word = lock->lock_word; - ut_ad(lock_word <= X_LOCK_DECR); - - if (lock_word > X_LOCK_HALF_DECR) { - /* s-locked, no x-waiter */ - return(X_LOCK_DECR - lock_word); - } else if (lock_word > 0) { - /* s-locked, with sx-locks only */ - return(X_LOCK_HALF_DECR - lock_word); - } else if (lock_word == 0) { - /* x-locked */ - return(0); - } else if (lock_word > -X_LOCK_HALF_DECR) { - /* s-locked, with x-waiter */ - return((ulint)(-lock_word)); - } else if (lock_word == -X_LOCK_HALF_DECR) { - /* x-locked with sx-locks */ - return(0); - } else if (lock_word > -X_LOCK_DECR) { - /* s-locked, with x-waiter and sx-lock */ - return((ulint)(-(lock_word + X_LOCK_HALF_DECR))); - } - /* no s-locks */ - return(0); -} - -/******************************************************************//** -Returns the value of writer_count for the lock. Does not reserve the lock -mutex, so the caller must be sure it is not changed during the call. -@return value of writer_count */ -UNIV_INLINE -ulint -rw_lock_get_x_lock_count( -/*=====================*/ - const rw_lock_t* lock) /*!< in: rw-lock */ -{ - lint lock_copy = lock->lock_word; - ut_ad(lock_copy <= X_LOCK_DECR); - - if (lock_copy == 0 || lock_copy == -X_LOCK_HALF_DECR) { - /* "1 x-lock" or "1 x-lock + sx-locks" */ - return(1); - } else if (lock_copy > -X_LOCK_DECR) { - /* s-locks, one or more sx-locks if > 0, or x-waiter if < 0 */ - return(0); - } else if (lock_copy > -(X_LOCK_DECR + X_LOCK_HALF_DECR)) { - /* no s-lock, no sx-lock, 2 or more x-locks. - First 2 x-locks are set with -X_LOCK_DECR, - all other recursive x-locks are set with -1 */ - return(2 - (lock_copy + X_LOCK_DECR)); - } else { - /* no s-lock, 1 or more sx-lock, 2 or more x-locks. - First 2 x-locks are set with -(X_LOCK_DECR + X_LOCK_HALF_DECR), - all other recursive x-locks are set with -1 */ - return(2 - (lock_copy + X_LOCK_DECR + X_LOCK_HALF_DECR)); - } -} - -/******************************************************************//** -Returns the number of sx-lock for the lock. Does not reserve the lock -mutex, so the caller must be sure it is not changed during the call. -@return value of sx-lock count */ -UNIV_INLINE -ulint -rw_lock_get_sx_lock_count( -/*======================*/ - const rw_lock_t* lock) /*!< in: rw-lock */ -{ -#ifdef UNIV_DEBUG - lint lock_copy = lock->lock_word; - - ut_ad(lock_copy <= X_LOCK_DECR); - - while (lock_copy < 0) { - lock_copy += X_LOCK_DECR; - } - - if (lock_copy > 0 && lock_copy <= X_LOCK_HALF_DECR) { - return(lock->sx_recursive); - } - - return(0); -#else /* UNIV_DEBUG */ - return(lock->sx_recursive); -#endif /* UNIV_DEBUG */ -} - -/******************************************************************//** -Two different implementations for decrementing the lock_word of a rw_lock: -one for systems supporting atomic operations, one for others. This does -does not support recusive x-locks: they should be handled by the caller and -need not be atomic since they are performed by the current lock holder. -Returns true if the decrement was made, false if not. -@return true if decr occurs */ -UNIV_INLINE -bool -rw_lock_lock_word_decr( -/*===================*/ - rw_lock_t* lock, /*!< in/out: rw-lock */ - ulint amount, /*!< in: amount to decrement */ - lint threshold) /*!< in: threshold of judgement */ -{ - lint local_lock_word; - - local_lock_word = lock->lock_word; - while (local_lock_word > threshold) { - if (my_atomic_caslint(&lock->lock_word, - &local_lock_word, - local_lock_word - amount)) { - return(true); - } - } - return(false); -} - -/******************************************************************//** -Low-level function which tries to lock an rw-lock in s-mode. Performs no -spinning. -@return TRUE if success */ -UNIV_INLINE -ibool -rw_lock_s_lock_low( -/*===============*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass MY_ATTRIBUTE((unused)), - /*!< in: pass value; != 0, if the lock will be - passed to another thread to unlock */ - const char* file_name, /*!< in: file name where lock requested */ - unsigned line) /*!< in: line where requested */ -{ - if (!rw_lock_lock_word_decr(lock, 1, 0)) { - /* Locking did not succeed */ - return(FALSE); - } - - ut_d(rw_lock_add_debug_info(lock, pass, RW_LOCK_S, file_name, line)); - - /* These debugging values are not set safely: they may be incorrect - or even refer to a line that is invalid for the file name. */ - lock->last_s_file_name = file_name; - lock->last_s_line = line; - - return(TRUE); /* locking succeeded */ -} - -/******************************************************************//** -NOTE! Use the corresponding macro, not directly this function! Lock an -rw-lock in shared mode for the current thread. If the rw-lock is locked -in exclusive mode, or there is an exclusive lock request waiting, the -function spins a preset time (controlled by srv_n_spin_wait_rounds), waiting for -the lock, before suspending the thread. */ -UNIV_INLINE -void -rw_lock_s_lock_func( -/*================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass, /*!< in: pass value; != 0, if the lock will - be passed to another thread to unlock */ - const char* file_name,/*!< in: file name where lock requested */ - unsigned line) /*!< in: line where requested */ -{ - /* NOTE: As we do not know the thread ids for threads which have - s-locked a latch, and s-lockers will be served only after waiting - x-lock requests have been fulfilled, then if this thread already - owns an s-lock here, it may end up in a deadlock with another thread - which requests an x-lock here. Therefore, we will forbid recursive - s-locking of a latch: the following assert will warn the programmer - of the possibility of this kind of a deadlock. If we want to implement - safe recursive s-locking, we should keep in a list the thread ids of - the threads which have s-locked a latch. This would use some CPU - time. */ - - ut_ad(!rw_lock_own_flagged(lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - - if (!rw_lock_s_lock_low(lock, pass, file_name, line)) { - - /* Did not succeed, try spin wait */ - - rw_lock_s_lock_spin(lock, pass, file_name, line); - } -} - -/******************************************************************//** -NOTE! Use the corresponding macro, not directly this function! Lock an -rw-lock in exclusive mode for the current thread if the lock can be -obtained immediately. -@return TRUE if success */ -UNIV_INLINE -ibool -rw_lock_x_lock_func_nowait( -/*=======================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - const char* file_name,/*!< in: file name where lock requested */ - unsigned line) /*!< in: line where requested */ -{ - lint oldval = X_LOCK_DECR; - - if (my_atomic_caslint(&lock->lock_word, &oldval, 0)) { - lock->writer_thread = os_thread_get_curr_id(); - - } else if (os_thread_eq(lock->writer_thread, os_thread_get_curr_id())) { - /* Relock: this lock_word modification is safe since no other - threads can modify (lock, unlock, or reserve) lock_word while - there is an exclusive writer and this is the writer thread. */ - if (lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR) { - /* There are 1 x-locks */ - lock->lock_word -= X_LOCK_DECR; - } else if (lock->lock_word <= -X_LOCK_DECR) { - /* There are 2 or more x-locks */ - lock->lock_word--; - } else { - /* Failure */ - return(FALSE); - } - - /* Watch for too many recursive locks */ - ut_ad(lock->lock_word < 0); - - } else { - /* Failure */ - return(FALSE); - } - - ut_d(rw_lock_add_debug_info(lock, 0, RW_LOCK_X, file_name, line)); - - lock->last_x_file_name = file_name; - lock->last_x_line = line; - - ut_ad(rw_lock_validate(lock)); - - return(TRUE); -} - -/******************************************************************//** -Releases a shared mode lock. */ -UNIV_INLINE -void -rw_lock_s_unlock_func( -/*==================*/ -#ifdef UNIV_DEBUG - ulint pass, /*!< in: pass value; != 0, if the lock may have - been passed to another thread to unlock */ -#endif /* UNIV_DEBUG */ - rw_lock_t* lock) /*!< in/out: rw-lock */ -{ - ut_ad(lock->lock_word > -X_LOCK_DECR); - ut_ad(lock->lock_word != 0); - ut_ad(lock->lock_word < X_LOCK_DECR); - - ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_S)); - - /* Increment lock_word to indicate 1 less reader */ - lint lock_word = my_atomic_addlint(&lock->lock_word, 1) + 1; - if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) { - - /* wait_ex waiter exists. It may not be asleep, but we signal - anyway. We do not wake other waiters, because they can't - exist without wait_ex waiter and wait_ex waiter goes first.*/ - os_event_set(lock->wait_ex_event); - sync_array_object_signalled(); - - } - - ut_ad(rw_lock_validate(lock)); -} - -/******************************************************************//** -Releases an exclusive mode lock. */ -UNIV_INLINE -void -rw_lock_x_unlock_func( -/*==================*/ -#ifdef UNIV_DEBUG - ulint pass, /*!< in: pass value; != 0, if the lock may have - been passed to another thread to unlock */ -#endif /* UNIV_DEBUG */ - rw_lock_t* lock) /*!< in/out: rw-lock */ -{ - ut_ad(lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR - || lock->lock_word <= -X_LOCK_DECR); - - if (lock->lock_word == 0) { - /* Last caller in a possible recursive chain. */ - lock->writer_thread = 0; - } - - ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_X)); - - if (lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR) { - /* There is 1 x-lock */ - /* atomic increment is needed, because it is last */ - if (my_atomic_addlint(&lock->lock_word, X_LOCK_DECR) <= -X_LOCK_DECR) { - ut_error; - } - - /* 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 (lock->waiters) { - my_atomic_store32((int32*) &lock->waiters, 0); - os_event_set(lock->event); - sync_array_object_signalled(); - } - } else if (lock->lock_word == -X_LOCK_DECR - || lock->lock_word == -(X_LOCK_DECR + X_LOCK_HALF_DECR)) { - /* There are 2 x-locks */ - lock->lock_word += X_LOCK_DECR; - } else { - /* There are more than 2 x-locks. */ - ut_ad(lock->lock_word < -X_LOCK_DECR); - lock->lock_word += 1; - } - - ut_ad(rw_lock_validate(lock)); -} - -/******************************************************************//** -Releases a sx mode lock. */ -UNIV_INLINE -void -rw_lock_sx_unlock_func( -/*===================*/ -#ifdef UNIV_DEBUG - ulint pass, /*!< in: pass value; != 0, if the lock may have - been passed to another thread to unlock */ -#endif /* UNIV_DEBUG */ - rw_lock_t* lock) /*!< in/out: rw-lock */ -{ - ut_ad(rw_lock_get_sx_lock_count(lock)); - ut_ad(lock->sx_recursive > 0); - - --lock->sx_recursive; - - ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_SX)); - - if (lock->sx_recursive == 0) { - /* Last caller in a possible recursive chain. */ - if (lock->lock_word > 0) { - lock->writer_thread = 0; - - if (my_atomic_addlint(&lock->lock_word, X_LOCK_HALF_DECR) <= 0) { - ut_error; - } - /* 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 (lock->waiters) { - my_atomic_store32((int32*) &lock->waiters, 0); - os_event_set(lock->event); - sync_array_object_signalled(); - } - } else { - /* still has x-lock */ - ut_ad(lock->lock_word == -X_LOCK_HALF_DECR - || lock->lock_word <= -(X_LOCK_DECR - + X_LOCK_HALF_DECR)); - lock->lock_word += X_LOCK_HALF_DECR; - } - } - - ut_ad(rw_lock_validate(lock)); -} - -#ifdef UNIV_PFS_RWLOCK - -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_create_func(). -NOTE! Please use the corresponding macro rw_lock_create(), not directly -this function! */ -UNIV_INLINE -void -pfs_rw_lock_create_func( -/*====================*/ - mysql_pfs_key_t key, /*!< in: key registered with - performance schema */ - rw_lock_t* lock, /*!< in/out: pointer to memory */ -# ifdef UNIV_DEBUG - latch_level_t level, /*!< in: level */ -# endif /* UNIV_DEBUG */ - const char* cfile_name, /*!< in: file name where created */ - unsigned cline) /*!< in: file line where created */ -{ - ut_d(new(lock) rw_lock_t()); - - /* Initialize the rwlock for performance schema */ - lock->pfs_psi = PSI_RWLOCK_CALL(init_rwlock)(key, lock); - - /* The actual function to initialize an rwlock */ - rw_lock_create_func(lock, -#ifdef UNIV_DEBUG - level, -#endif /* UNIV_DEBUG */ - cfile_name, - cline); -} -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_x_lock_func() -NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly -this function! */ -UNIV_INLINE -void -pfs_rw_lock_x_lock_func( -/*====================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass, /*!< in: pass value; != 0, if the lock will - be passed to another thread to unlock */ - const char* file_name,/*!< in: file name where lock requested */ - unsigned line) /*!< in: line where requested */ -{ - if (lock->pfs_psi != NULL) { - PSI_rwlock_locker* locker; - PSI_rwlock_locker_state state; - - /* Record the acquisition of a read-write lock in exclusive - mode in performance schema */ -/* MySQL 5.7 New PSI */ -#define PSI_RWLOCK_EXCLUSIVELOCK PSI_RWLOCK_WRITELOCK - - locker = PSI_RWLOCK_CALL(start_rwlock_wrwait)( - &state, lock->pfs_psi, PSI_RWLOCK_EXCLUSIVELOCK, - file_name, static_cast(line)); - - rw_lock_x_lock_func( - lock, pass, file_name, static_cast(line)); - - if (locker != NULL) { - PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, 0); - } - } else { - rw_lock_x_lock_func(lock, pass, file_name, line); - } -} -/******************************************************************//** -Performance schema instrumented wrap function for -rw_lock_x_lock_func_nowait() -NOTE! Please use the corresponding macro rw_lock_x_lock_func(), -not directly this function! -@return TRUE if success */ -UNIV_INLINE -ibool -pfs_rw_lock_x_lock_func_nowait( -/*===========================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - const char* file_name,/*!< in: file name where lock - requested */ - unsigned line) /*!< in: line where requested */ -{ - ibool ret; - - if (lock->pfs_psi != NULL) { - PSI_rwlock_locker* locker; - PSI_rwlock_locker_state state; - - /* Record the acquisition of a read-write trylock in exclusive - mode in performance schema */ - -#define PSI_RWLOCK_TRYEXCLUSIVELOCK PSI_RWLOCK_TRYWRITELOCK - locker = PSI_RWLOCK_CALL(start_rwlock_wrwait)( - &state, lock->pfs_psi, PSI_RWLOCK_TRYEXCLUSIVELOCK, - file_name, static_cast(line)); - - ret = rw_lock_x_lock_func_nowait(lock, file_name, line); - - if (locker != NULL) { - PSI_RWLOCK_CALL(end_rwlock_wrwait)( - locker, static_cast(ret)); - } - } else { - ret = rw_lock_x_lock_func_nowait(lock, file_name, line); - } - - return(ret); -} -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_free_func() -NOTE! Please use the corresponding macro rw_lock_free(), not directly -this function! */ -UNIV_INLINE -void -pfs_rw_lock_free_func( -/*==================*/ - rw_lock_t* lock) /*!< in: pointer to rw-lock */ -{ - if (lock->pfs_psi != NULL) { - PSI_RWLOCK_CALL(destroy_rwlock)(lock->pfs_psi); - lock->pfs_psi = NULL; - } - - rw_lock_free_func(lock); -} -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_s_lock_func() -NOTE! Please use the corresponding macro rw_lock_s_lock(), not -directly this function! */ -UNIV_INLINE -void -pfs_rw_lock_s_lock_func( -/*====================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass, /*!< in: pass value; != 0, if the - lock will be passed to another - thread to unlock */ - const char* file_name,/*!< in: file name where lock - requested */ - unsigned line) /*!< in: line where requested */ -{ - if (lock->pfs_psi != NULL) { - PSI_rwlock_locker* locker; - PSI_rwlock_locker_state state; - -#define PSI_RWLOCK_SHAREDLOCK PSI_RWLOCK_READLOCK - /* Instrumented to inform we are aquiring a shared rwlock */ - locker = PSI_RWLOCK_CALL(start_rwlock_rdwait)( - &state, lock->pfs_psi, PSI_RWLOCK_SHAREDLOCK, - file_name, static_cast(line)); - - rw_lock_s_lock_func(lock, pass, file_name, line); - - if (locker != NULL) { - PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, 0); - } - } else { - rw_lock_s_lock_func(lock, pass, file_name, line); - } -} -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_sx_lock_func() -NOTE! Please use the corresponding macro rw_lock_sx_lock(), not -directly this function! */ -UNIV_INLINE -void -pfs_rw_lock_sx_lock_func( -/*====================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass, /*!< in: pass value; != 0, if the - lock will be passed to another - thread to unlock */ - const char* file_name,/*!< in: file name where lock - requested */ - unsigned line) /*!< in: line where requested */ -{ - if (lock->pfs_psi != NULL) { - PSI_rwlock_locker* locker; - PSI_rwlock_locker_state state; - -#define PSI_RWLOCK_SHAREDEXCLUSIVELOCK PSI_RWLOCK_WRITELOCK - /* Instrumented to inform we are aquiring a shared rwlock */ - locker = PSI_RWLOCK_CALL(start_rwlock_wrwait)( - &state, lock->pfs_psi, PSI_RWLOCK_SHAREDEXCLUSIVELOCK, - file_name, static_cast(line)); - - rw_lock_sx_lock_func(lock, pass, file_name, line); - - if (locker != NULL) { - PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, 0); - } - } else { - rw_lock_sx_lock_func(lock, pass, file_name, line); - } -} -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_s_lock_func() -NOTE! Please use the corresponding macro rw_lock_s_lock(), not -directly this function! -@return TRUE if success */ -UNIV_INLINE -ibool -pfs_rw_lock_s_lock_low( -/*===================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass, /*!< in: pass value; != 0, if the - lock will be passed to another - thread to unlock */ - const char* file_name, /*!< in: file name where lock requested */ - unsigned line) /*!< in: line where requested */ -{ - ibool ret; - - if (lock->pfs_psi != NULL) { - PSI_rwlock_locker* locker; - PSI_rwlock_locker_state state; - -#define PSI_RWLOCK_TRYSHAREDLOCK PSI_RWLOCK_TRYREADLOCK - /* Instrumented to inform we are aquiring a shared rwlock */ - locker = PSI_RWLOCK_CALL(start_rwlock_rdwait)( - &state, lock->pfs_psi, PSI_RWLOCK_TRYSHAREDLOCK, - file_name, static_cast(line)); - - ret = rw_lock_s_lock_low(lock, pass, file_name, line); - - if (locker != NULL) { - PSI_RWLOCK_CALL(end_rwlock_rdwait)( - locker, static_cast(ret)); - } - } else { - ret = rw_lock_s_lock_low(lock, pass, file_name, line); - } - - return(ret); -} -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_sx_lock_nowait() -NOTE! Please use the corresponding macro, not -directly this function! -@return TRUE if success */ -UNIV_INLINE -ibool -pfs_rw_lock_sx_lock_low( -/*====================*/ - rw_lock_t* lock, /*!< in: pointer to rw-lock */ - ulint pass, /*!< in: pass value; != 0, if the - lock will be passed to another - thread to unlock */ - const char* file_name, /*!< in: file name where lock requested */ - unsigned line) /*!< in: line where requested */ -{ - ibool ret; - - if (lock->pfs_psi != NULL) { - PSI_rwlock_locker* locker; - PSI_rwlock_locker_state state; - -#define PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK PSI_RWLOCK_TRYWRITELOCK - /* Instrumented to inform we are aquiring a shared - exclusive rwlock */ - locker = PSI_RWLOCK_CALL(start_rwlock_rdwait)( - &state, lock->pfs_psi, - PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK, - file_name, static_cast(line)); - - ret = rw_lock_sx_lock_low(lock, pass, file_name, line); - - if (locker != NULL) { - PSI_RWLOCK_CALL(end_rwlock_rdwait)( - locker, static_cast(ret)); - } - } else { - ret = rw_lock_sx_lock_low(lock, pass, file_name, line); - } - - return(ret); -} -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_x_unlock_func() -NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly -this function! */ -UNIV_INLINE -void -pfs_rw_lock_x_unlock_func( -/*======================*/ -#ifdef UNIV_DEBUG - ulint pass, /*!< in: pass value; != 0, if the - lock may have been passed to another - thread to unlock */ -#endif /* UNIV_DEBUG */ - rw_lock_t* lock) /*!< in/out: rw-lock */ -{ - /* Inform performance schema we are unlocking the lock */ - if (lock->pfs_psi != NULL) { - PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); - } - - rw_lock_x_unlock_func( -#ifdef UNIV_DEBUG - pass, -#endif /* UNIV_DEBUG */ - lock); -} - -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_sx_unlock_func() -NOTE! Please use the corresponding macro rw_lock_sx_unlock(), not directly -this function! */ -UNIV_INLINE -void -pfs_rw_lock_sx_unlock_func( -/*======================*/ -#ifdef UNIV_DEBUG - ulint pass, /*!< in: pass value; != 0, if the - lock may have been passed to another - thread to unlock */ -#endif /* UNIV_DEBUG */ - rw_lock_t* lock) /*!< in/out: rw-lock */ -{ - /* Inform performance schema we are unlocking the lock */ - if (lock->pfs_psi != NULL) { - PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); - } - - rw_lock_sx_unlock_func( -#ifdef UNIV_DEBUG - pass, -#endif /* UNIV_DEBUG */ - lock); -} - -/******************************************************************//** -Performance schema instrumented wrap function for rw_lock_s_unlock_func() -NOTE! Please use the corresponding macro pfs_rw_lock_s_unlock(), not -directly this function! */ -UNIV_INLINE -void -pfs_rw_lock_s_unlock_func( -/*======================*/ -#ifdef UNIV_DEBUG - ulint pass, /*!< in: pass value; != 0, if the - lock may have been passed to another - thread to unlock */ -#endif /* UNIV_DEBUG */ - rw_lock_t* lock) /*!< in/out: rw-lock */ -{ - /* Inform performance schema we are unlocking the lock */ - if (lock->pfs_psi != NULL) { - PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); - } - - rw_lock_s_unlock_func( -#ifdef UNIV_DEBUG - pass, -#endif /* UNIV_DEBUG */ - lock); - -} -#endif /* UNIV_PFS_RWLOCK */ diff --git a/storage/innobase/include/sync0rw.inl b/storage/innobase/include/sync0rw.inl new file mode 100644 index 00000000000..d0be5f0ece1 --- /dev/null +++ b/storage/innobase/include/sync0rw.inl @@ -0,0 +1,838 @@ +/***************************************************************************** + +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2008, Google Inc. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. + +Portions of this file contain modifications contributed and copyrighted by +Google, Inc. Those modifications are gratefully acknowledged and are described +briefly in the InnoDB documentation. The contributions by Google are +incorporated with their permission, and subject to the conditions contained in +the file COPYING.Google. + +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/sync0rw.ic +The read-write lock (for threads) + +Created 9/11/1995 Heikki Tuuri +*******************************************************/ + +#include "os0event.h" + +/******************************************************************//** +Lock an rw-lock in shared mode for the current thread. If the rw-lock is +locked in exclusive mode, or there is an exclusive lock request waiting, +the function spins a preset time (controlled by srv_n_spin_wait_rounds), +waiting for the lock before suspending the thread. */ +void +rw_lock_s_lock_spin( +/*================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass, /*!< in: pass value; != 0, if the lock will + be passed to another thread to unlock */ + const char* file_name,/*!< in: file name where lock requested */ + unsigned line); /*!< in: line where requested */ +#ifdef UNIV_DEBUG +/******************************************************************//** +Inserts the debug information for an rw-lock. */ +void +rw_lock_add_debug_info( +/*===================*/ + rw_lock_t* lock, /*!< in: rw-lock */ + ulint pass, /*!< in: pass value */ + ulint lock_type, /*!< in: lock type */ + const char* file_name, /*!< in: file where requested */ + unsigned line); /*!< in: line where requested */ +/******************************************************************//** +Removes a debug information struct for an rw-lock. */ +void +rw_lock_remove_debug_info( +/*======================*/ + rw_lock_t* lock, /*!< in: rw-lock */ + ulint pass, /*!< in: pass value */ + ulint lock_type); /*!< in: lock type */ +#endif /* UNIV_DEBUG */ + +/******************************************************************//** +Returns the write-status of the lock - this function made more sense +with the old rw_lock implementation. +@return RW_LOCK_NOT_LOCKED, RW_LOCK_X, RW_LOCK_X_WAIT, RW_LOCK_SX */ +UNIV_INLINE +ulint +rw_lock_get_writer( +/*===============*/ + const rw_lock_t* lock) /*!< in: rw-lock */ +{ + lint lock_word = lock->lock_word; + + ut_ad(lock_word <= X_LOCK_DECR); + if (lock_word > X_LOCK_HALF_DECR) { + /* return NOT_LOCKED in s-lock state, like the writer + member of the old lock implementation. */ + return(RW_LOCK_NOT_LOCKED); + } else if (lock_word > 0) { + /* sx-locked, no x-locks */ + return(RW_LOCK_SX); + } else if (lock_word == 0 + || lock_word == -X_LOCK_HALF_DECR + || lock_word <= -X_LOCK_DECR) { + /* x-lock with sx-lock is also treated as RW_LOCK_EX */ + return(RW_LOCK_X); + } else { + /* x-waiter with sx-lock is also treated as RW_LOCK_WAIT_EX + e.g. -X_LOCK_HALF_DECR < lock_word < 0 : without sx + -X_LOCK_DECR < lock_word < -X_LOCK_HALF_DECR : with sx */ + return(RW_LOCK_X_WAIT); + } +} + +/******************************************************************//** +Returns the number of readers (s-locks). +@return number of readers */ +UNIV_INLINE +ulint +rw_lock_get_reader_count( +/*=====================*/ + const rw_lock_t* lock) /*!< in: rw-lock */ +{ + lint lock_word = lock->lock_word; + ut_ad(lock_word <= X_LOCK_DECR); + + if (lock_word > X_LOCK_HALF_DECR) { + /* s-locked, no x-waiter */ + return(X_LOCK_DECR - lock_word); + } else if (lock_word > 0) { + /* s-locked, with sx-locks only */ + return(X_LOCK_HALF_DECR - lock_word); + } else if (lock_word == 0) { + /* x-locked */ + return(0); + } else if (lock_word > -X_LOCK_HALF_DECR) { + /* s-locked, with x-waiter */ + return((ulint)(-lock_word)); + } else if (lock_word == -X_LOCK_HALF_DECR) { + /* x-locked with sx-locks */ + return(0); + } else if (lock_word > -X_LOCK_DECR) { + /* s-locked, with x-waiter and sx-lock */ + return((ulint)(-(lock_word + X_LOCK_HALF_DECR))); + } + /* no s-locks */ + return(0); +} + +/******************************************************************//** +Returns the value of writer_count for the lock. Does not reserve the lock +mutex, so the caller must be sure it is not changed during the call. +@return value of writer_count */ +UNIV_INLINE +ulint +rw_lock_get_x_lock_count( +/*=====================*/ + const rw_lock_t* lock) /*!< in: rw-lock */ +{ + lint lock_copy = lock->lock_word; + ut_ad(lock_copy <= X_LOCK_DECR); + + if (lock_copy == 0 || lock_copy == -X_LOCK_HALF_DECR) { + /* "1 x-lock" or "1 x-lock + sx-locks" */ + return(1); + } else if (lock_copy > -X_LOCK_DECR) { + /* s-locks, one or more sx-locks if > 0, or x-waiter if < 0 */ + return(0); + } else if (lock_copy > -(X_LOCK_DECR + X_LOCK_HALF_DECR)) { + /* no s-lock, no sx-lock, 2 or more x-locks. + First 2 x-locks are set with -X_LOCK_DECR, + all other recursive x-locks are set with -1 */ + return(2 - (lock_copy + X_LOCK_DECR)); + } else { + /* no s-lock, 1 or more sx-lock, 2 or more x-locks. + First 2 x-locks are set with -(X_LOCK_DECR + X_LOCK_HALF_DECR), + all other recursive x-locks are set with -1 */ + return(2 - (lock_copy + X_LOCK_DECR + X_LOCK_HALF_DECR)); + } +} + +/******************************************************************//** +Returns the number of sx-lock for the lock. Does not reserve the lock +mutex, so the caller must be sure it is not changed during the call. +@return value of sx-lock count */ +UNIV_INLINE +ulint +rw_lock_get_sx_lock_count( +/*======================*/ + const rw_lock_t* lock) /*!< in: rw-lock */ +{ +#ifdef UNIV_DEBUG + lint lock_copy = lock->lock_word; + + ut_ad(lock_copy <= X_LOCK_DECR); + + while (lock_copy < 0) { + lock_copy += X_LOCK_DECR; + } + + if (lock_copy > 0 && lock_copy <= X_LOCK_HALF_DECR) { + return(lock->sx_recursive); + } + + return(0); +#else /* UNIV_DEBUG */ + return(lock->sx_recursive); +#endif /* UNIV_DEBUG */ +} + +/******************************************************************//** +Two different implementations for decrementing the lock_word of a rw_lock: +one for systems supporting atomic operations, one for others. This does +does not support recusive x-locks: they should be handled by the caller and +need not be atomic since they are performed by the current lock holder. +Returns true if the decrement was made, false if not. +@return true if decr occurs */ +UNIV_INLINE +bool +rw_lock_lock_word_decr( +/*===================*/ + rw_lock_t* lock, /*!< in/out: rw-lock */ + ulint amount, /*!< in: amount to decrement */ + lint threshold) /*!< in: threshold of judgement */ +{ + lint local_lock_word; + + local_lock_word = lock->lock_word; + while (local_lock_word > threshold) { + if (my_atomic_caslint(&lock->lock_word, + &local_lock_word, + local_lock_word - amount)) { + return(true); + } + } + return(false); +} + +/******************************************************************//** +Low-level function which tries to lock an rw-lock in s-mode. Performs no +spinning. +@return TRUE if success */ +UNIV_INLINE +ibool +rw_lock_s_lock_low( +/*===============*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass MY_ATTRIBUTE((unused)), + /*!< in: pass value; != 0, if the lock will be + passed to another thread to unlock */ + const char* file_name, /*!< in: file name where lock requested */ + unsigned line) /*!< in: line where requested */ +{ + if (!rw_lock_lock_word_decr(lock, 1, 0)) { + /* Locking did not succeed */ + return(FALSE); + } + + ut_d(rw_lock_add_debug_info(lock, pass, RW_LOCK_S, file_name, line)); + + /* These debugging values are not set safely: they may be incorrect + or even refer to a line that is invalid for the file name. */ + lock->last_s_file_name = file_name; + lock->last_s_line = line; + + return(TRUE); /* locking succeeded */ +} + +/******************************************************************//** +NOTE! Use the corresponding macro, not directly this function! Lock an +rw-lock in shared mode for the current thread. If the rw-lock is locked +in exclusive mode, or there is an exclusive lock request waiting, the +function spins a preset time (controlled by srv_n_spin_wait_rounds), waiting for +the lock, before suspending the thread. */ +UNIV_INLINE +void +rw_lock_s_lock_func( +/*================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass, /*!< in: pass value; != 0, if the lock will + be passed to another thread to unlock */ + const char* file_name,/*!< in: file name where lock requested */ + unsigned line) /*!< in: line where requested */ +{ + /* NOTE: As we do not know the thread ids for threads which have + s-locked a latch, and s-lockers will be served only after waiting + x-lock requests have been fulfilled, then if this thread already + owns an s-lock here, it may end up in a deadlock with another thread + which requests an x-lock here. Therefore, we will forbid recursive + s-locking of a latch: the following assert will warn the programmer + of the possibility of this kind of a deadlock. If we want to implement + safe recursive s-locking, we should keep in a list the thread ids of + the threads which have s-locked a latch. This would use some CPU + time. */ + + ut_ad(!rw_lock_own_flagged(lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); + + if (!rw_lock_s_lock_low(lock, pass, file_name, line)) { + + /* Did not succeed, try spin wait */ + + rw_lock_s_lock_spin(lock, pass, file_name, line); + } +} + +/******************************************************************//** +NOTE! Use the corresponding macro, not directly this function! Lock an +rw-lock in exclusive mode for the current thread if the lock can be +obtained immediately. +@return TRUE if success */ +UNIV_INLINE +ibool +rw_lock_x_lock_func_nowait( +/*=======================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + const char* file_name,/*!< in: file name where lock requested */ + unsigned line) /*!< in: line where requested */ +{ + lint oldval = X_LOCK_DECR; + + if (my_atomic_caslint(&lock->lock_word, &oldval, 0)) { + lock->writer_thread = os_thread_get_curr_id(); + + } else if (os_thread_eq(lock->writer_thread, os_thread_get_curr_id())) { + /* Relock: this lock_word modification is safe since no other + threads can modify (lock, unlock, or reserve) lock_word while + there is an exclusive writer and this is the writer thread. */ + if (lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR) { + /* There are 1 x-locks */ + lock->lock_word -= X_LOCK_DECR; + } else if (lock->lock_word <= -X_LOCK_DECR) { + /* There are 2 or more x-locks */ + lock->lock_word--; + } else { + /* Failure */ + return(FALSE); + } + + /* Watch for too many recursive locks */ + ut_ad(lock->lock_word < 0); + + } else { + /* Failure */ + return(FALSE); + } + + ut_d(rw_lock_add_debug_info(lock, 0, RW_LOCK_X, file_name, line)); + + lock->last_x_file_name = file_name; + lock->last_x_line = line; + + ut_ad(rw_lock_validate(lock)); + + return(TRUE); +} + +/******************************************************************//** +Releases a shared mode lock. */ +UNIV_INLINE +void +rw_lock_s_unlock_func( +/*==================*/ +#ifdef UNIV_DEBUG + ulint pass, /*!< in: pass value; != 0, if the lock may have + been passed to another thread to unlock */ +#endif /* UNIV_DEBUG */ + rw_lock_t* lock) /*!< in/out: rw-lock */ +{ + ut_ad(lock->lock_word > -X_LOCK_DECR); + ut_ad(lock->lock_word != 0); + ut_ad(lock->lock_word < X_LOCK_DECR); + + ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_S)); + + /* Increment lock_word to indicate 1 less reader */ + lint lock_word = my_atomic_addlint(&lock->lock_word, 1) + 1; + if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) { + + /* wait_ex waiter exists. It may not be asleep, but we signal + anyway. We do not wake other waiters, because they can't + exist without wait_ex waiter and wait_ex waiter goes first.*/ + os_event_set(lock->wait_ex_event); + sync_array_object_signalled(); + + } + + ut_ad(rw_lock_validate(lock)); +} + +/******************************************************************//** +Releases an exclusive mode lock. */ +UNIV_INLINE +void +rw_lock_x_unlock_func( +/*==================*/ +#ifdef UNIV_DEBUG + ulint pass, /*!< in: pass value; != 0, if the lock may have + been passed to another thread to unlock */ +#endif /* UNIV_DEBUG */ + rw_lock_t* lock) /*!< in/out: rw-lock */ +{ + ut_ad(lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR + || lock->lock_word <= -X_LOCK_DECR); + + if (lock->lock_word == 0) { + /* Last caller in a possible recursive chain. */ + lock->writer_thread = 0; + } + + ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_X)); + + if (lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR) { + /* There is 1 x-lock */ + /* atomic increment is needed, because it is last */ + if (my_atomic_addlint(&lock->lock_word, X_LOCK_DECR) <= -X_LOCK_DECR) { + ut_error; + } + + /* 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 (lock->waiters) { + my_atomic_store32((int32*) &lock->waiters, 0); + os_event_set(lock->event); + sync_array_object_signalled(); + } + } else if (lock->lock_word == -X_LOCK_DECR + || lock->lock_word == -(X_LOCK_DECR + X_LOCK_HALF_DECR)) { + /* There are 2 x-locks */ + lock->lock_word += X_LOCK_DECR; + } else { + /* There are more than 2 x-locks. */ + ut_ad(lock->lock_word < -X_LOCK_DECR); + lock->lock_word += 1; + } + + ut_ad(rw_lock_validate(lock)); +} + +/******************************************************************//** +Releases a sx mode lock. */ +UNIV_INLINE +void +rw_lock_sx_unlock_func( +/*===================*/ +#ifdef UNIV_DEBUG + ulint pass, /*!< in: pass value; != 0, if the lock may have + been passed to another thread to unlock */ +#endif /* UNIV_DEBUG */ + rw_lock_t* lock) /*!< in/out: rw-lock */ +{ + ut_ad(rw_lock_get_sx_lock_count(lock)); + ut_ad(lock->sx_recursive > 0); + + --lock->sx_recursive; + + ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_SX)); + + if (lock->sx_recursive == 0) { + /* Last caller in a possible recursive chain. */ + if (lock->lock_word > 0) { + lock->writer_thread = 0; + + if (my_atomic_addlint(&lock->lock_word, X_LOCK_HALF_DECR) <= 0) { + ut_error; + } + /* 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 (lock->waiters) { + my_atomic_store32((int32*) &lock->waiters, 0); + os_event_set(lock->event); + sync_array_object_signalled(); + } + } else { + /* still has x-lock */ + ut_ad(lock->lock_word == -X_LOCK_HALF_DECR + || lock->lock_word <= -(X_LOCK_DECR + + X_LOCK_HALF_DECR)); + lock->lock_word += X_LOCK_HALF_DECR; + } + } + + ut_ad(rw_lock_validate(lock)); +} + +#ifdef UNIV_PFS_RWLOCK + +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_create_func(). +NOTE! Please use the corresponding macro rw_lock_create(), not directly +this function! */ +UNIV_INLINE +void +pfs_rw_lock_create_func( +/*====================*/ + mysql_pfs_key_t key, /*!< in: key registered with + performance schema */ + rw_lock_t* lock, /*!< in/out: pointer to memory */ +# ifdef UNIV_DEBUG + latch_level_t level, /*!< in: level */ +# endif /* UNIV_DEBUG */ + const char* cfile_name, /*!< in: file name where created */ + unsigned cline) /*!< in: file line where created */ +{ + ut_d(new(lock) rw_lock_t()); + + /* Initialize the rwlock for performance schema */ + lock->pfs_psi = PSI_RWLOCK_CALL(init_rwlock)(key, lock); + + /* The actual function to initialize an rwlock */ + rw_lock_create_func(lock, +#ifdef UNIV_DEBUG + level, +#endif /* UNIV_DEBUG */ + cfile_name, + cline); +} +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_x_lock_func() +NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly +this function! */ +UNIV_INLINE +void +pfs_rw_lock_x_lock_func( +/*====================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass, /*!< in: pass value; != 0, if the lock will + be passed to another thread to unlock */ + const char* file_name,/*!< in: file name where lock requested */ + unsigned line) /*!< in: line where requested */ +{ + if (lock->pfs_psi != NULL) { + PSI_rwlock_locker* locker; + PSI_rwlock_locker_state state; + + /* Record the acquisition of a read-write lock in exclusive + mode in performance schema */ +/* MySQL 5.7 New PSI */ +#define PSI_RWLOCK_EXCLUSIVELOCK PSI_RWLOCK_WRITELOCK + + locker = PSI_RWLOCK_CALL(start_rwlock_wrwait)( + &state, lock->pfs_psi, PSI_RWLOCK_EXCLUSIVELOCK, + file_name, static_cast(line)); + + rw_lock_x_lock_func( + lock, pass, file_name, static_cast(line)); + + if (locker != NULL) { + PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, 0); + } + } else { + rw_lock_x_lock_func(lock, pass, file_name, line); + } +} +/******************************************************************//** +Performance schema instrumented wrap function for +rw_lock_x_lock_func_nowait() +NOTE! Please use the corresponding macro rw_lock_x_lock_func(), +not directly this function! +@return TRUE if success */ +UNIV_INLINE +ibool +pfs_rw_lock_x_lock_func_nowait( +/*===========================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + const char* file_name,/*!< in: file name where lock + requested */ + unsigned line) /*!< in: line where requested */ +{ + ibool ret; + + if (lock->pfs_psi != NULL) { + PSI_rwlock_locker* locker; + PSI_rwlock_locker_state state; + + /* Record the acquisition of a read-write trylock in exclusive + mode in performance schema */ + +#define PSI_RWLOCK_TRYEXCLUSIVELOCK PSI_RWLOCK_TRYWRITELOCK + locker = PSI_RWLOCK_CALL(start_rwlock_wrwait)( + &state, lock->pfs_psi, PSI_RWLOCK_TRYEXCLUSIVELOCK, + file_name, static_cast(line)); + + ret = rw_lock_x_lock_func_nowait(lock, file_name, line); + + if (locker != NULL) { + PSI_RWLOCK_CALL(end_rwlock_wrwait)( + locker, static_cast(ret)); + } + } else { + ret = rw_lock_x_lock_func_nowait(lock, file_name, line); + } + + return(ret); +} +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_free_func() +NOTE! Please use the corresponding macro rw_lock_free(), not directly +this function! */ +UNIV_INLINE +void +pfs_rw_lock_free_func( +/*==================*/ + rw_lock_t* lock) /*!< in: pointer to rw-lock */ +{ + if (lock->pfs_psi != NULL) { + PSI_RWLOCK_CALL(destroy_rwlock)(lock->pfs_psi); + lock->pfs_psi = NULL; + } + + rw_lock_free_func(lock); +} +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_s_lock_func() +NOTE! Please use the corresponding macro rw_lock_s_lock(), not +directly this function! */ +UNIV_INLINE +void +pfs_rw_lock_s_lock_func( +/*====================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass, /*!< in: pass value; != 0, if the + lock will be passed to another + thread to unlock */ + const char* file_name,/*!< in: file name where lock + requested */ + unsigned line) /*!< in: line where requested */ +{ + if (lock->pfs_psi != NULL) { + PSI_rwlock_locker* locker; + PSI_rwlock_locker_state state; + +#define PSI_RWLOCK_SHAREDLOCK PSI_RWLOCK_READLOCK + /* Instrumented to inform we are aquiring a shared rwlock */ + locker = PSI_RWLOCK_CALL(start_rwlock_rdwait)( + &state, lock->pfs_psi, PSI_RWLOCK_SHAREDLOCK, + file_name, static_cast(line)); + + rw_lock_s_lock_func(lock, pass, file_name, line); + + if (locker != NULL) { + PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, 0); + } + } else { + rw_lock_s_lock_func(lock, pass, file_name, line); + } +} +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_sx_lock_func() +NOTE! Please use the corresponding macro rw_lock_sx_lock(), not +directly this function! */ +UNIV_INLINE +void +pfs_rw_lock_sx_lock_func( +/*====================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass, /*!< in: pass value; != 0, if the + lock will be passed to another + thread to unlock */ + const char* file_name,/*!< in: file name where lock + requested */ + unsigned line) /*!< in: line where requested */ +{ + if (lock->pfs_psi != NULL) { + PSI_rwlock_locker* locker; + PSI_rwlock_locker_state state; + +#define PSI_RWLOCK_SHAREDEXCLUSIVELOCK PSI_RWLOCK_WRITELOCK + /* Instrumented to inform we are aquiring a shared rwlock */ + locker = PSI_RWLOCK_CALL(start_rwlock_wrwait)( + &state, lock->pfs_psi, PSI_RWLOCK_SHAREDEXCLUSIVELOCK, + file_name, static_cast(line)); + + rw_lock_sx_lock_func(lock, pass, file_name, line); + + if (locker != NULL) { + PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, 0); + } + } else { + rw_lock_sx_lock_func(lock, pass, file_name, line); + } +} +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_s_lock_func() +NOTE! Please use the corresponding macro rw_lock_s_lock(), not +directly this function! +@return TRUE if success */ +UNIV_INLINE +ibool +pfs_rw_lock_s_lock_low( +/*===================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass, /*!< in: pass value; != 0, if the + lock will be passed to another + thread to unlock */ + const char* file_name, /*!< in: file name where lock requested */ + unsigned line) /*!< in: line where requested */ +{ + ibool ret; + + if (lock->pfs_psi != NULL) { + PSI_rwlock_locker* locker; + PSI_rwlock_locker_state state; + +#define PSI_RWLOCK_TRYSHAREDLOCK PSI_RWLOCK_TRYREADLOCK + /* Instrumented to inform we are aquiring a shared rwlock */ + locker = PSI_RWLOCK_CALL(start_rwlock_rdwait)( + &state, lock->pfs_psi, PSI_RWLOCK_TRYSHAREDLOCK, + file_name, static_cast(line)); + + ret = rw_lock_s_lock_low(lock, pass, file_name, line); + + if (locker != NULL) { + PSI_RWLOCK_CALL(end_rwlock_rdwait)( + locker, static_cast(ret)); + } + } else { + ret = rw_lock_s_lock_low(lock, pass, file_name, line); + } + + return(ret); +} +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_sx_lock_nowait() +NOTE! Please use the corresponding macro, not +directly this function! +@return TRUE if success */ +UNIV_INLINE +ibool +pfs_rw_lock_sx_lock_low( +/*====================*/ + rw_lock_t* lock, /*!< in: pointer to rw-lock */ + ulint pass, /*!< in: pass value; != 0, if the + lock will be passed to another + thread to unlock */ + const char* file_name, /*!< in: file name where lock requested */ + unsigned line) /*!< in: line where requested */ +{ + ibool ret; + + if (lock->pfs_psi != NULL) { + PSI_rwlock_locker* locker; + PSI_rwlock_locker_state state; + +#define PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK PSI_RWLOCK_TRYWRITELOCK + /* Instrumented to inform we are aquiring a shared + exclusive rwlock */ + locker = PSI_RWLOCK_CALL(start_rwlock_rdwait)( + &state, lock->pfs_psi, + PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK, + file_name, static_cast(line)); + + ret = rw_lock_sx_lock_low(lock, pass, file_name, line); + + if (locker != NULL) { + PSI_RWLOCK_CALL(end_rwlock_rdwait)( + locker, static_cast(ret)); + } + } else { + ret = rw_lock_sx_lock_low(lock, pass, file_name, line); + } + + return(ret); +} +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_x_unlock_func() +NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly +this function! */ +UNIV_INLINE +void +pfs_rw_lock_x_unlock_func( +/*======================*/ +#ifdef UNIV_DEBUG + ulint pass, /*!< in: pass value; != 0, if the + lock may have been passed to another + thread to unlock */ +#endif /* UNIV_DEBUG */ + rw_lock_t* lock) /*!< in/out: rw-lock */ +{ + /* Inform performance schema we are unlocking the lock */ + if (lock->pfs_psi != NULL) { + PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); + } + + rw_lock_x_unlock_func( +#ifdef UNIV_DEBUG + pass, +#endif /* UNIV_DEBUG */ + lock); +} + +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_sx_unlock_func() +NOTE! Please use the corresponding macro rw_lock_sx_unlock(), not directly +this function! */ +UNIV_INLINE +void +pfs_rw_lock_sx_unlock_func( +/*======================*/ +#ifdef UNIV_DEBUG + ulint pass, /*!< in: pass value; != 0, if the + lock may have been passed to another + thread to unlock */ +#endif /* UNIV_DEBUG */ + rw_lock_t* lock) /*!< in/out: rw-lock */ +{ + /* Inform performance schema we are unlocking the lock */ + if (lock->pfs_psi != NULL) { + PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); + } + + rw_lock_sx_unlock_func( +#ifdef UNIV_DEBUG + pass, +#endif /* UNIV_DEBUG */ + lock); +} + +/******************************************************************//** +Performance schema instrumented wrap function for rw_lock_s_unlock_func() +NOTE! Please use the corresponding macro pfs_rw_lock_s_unlock(), not +directly this function! */ +UNIV_INLINE +void +pfs_rw_lock_s_unlock_func( +/*======================*/ +#ifdef UNIV_DEBUG + ulint pass, /*!< in: pass value; != 0, if the + lock may have been passed to another + thread to unlock */ +#endif /* UNIV_DEBUG */ + rw_lock_t* lock) /*!< in/out: rw-lock */ +{ + /* Inform performance schema we are unlocking the lock */ + if (lock->pfs_psi != NULL) { + PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); + } + + rw_lock_s_unlock_func( +#ifdef UNIV_DEBUG + pass, +#endif /* UNIV_DEBUG */ + lock); + +} +#endif /* UNIV_PFS_RWLOCK */ diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 73d497dd64a..341daa0f3e4 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -537,6 +537,6 @@ struct trx_purge_rec_t { roll_ptr_t roll_ptr; /*!< File pointr to UNDO record */ }; -#include "trx0purge.ic" +#include "trx0purge.inl" #endif /* trx0purge_h */ diff --git a/storage/innobase/include/trx0purge.ic b/storage/innobase/include/trx0purge.ic deleted file mode 100644 index 0ccff6f7798..00000000000 --- a/storage/innobase/include/trx0purge.ic +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2013, 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/trx0purge.ic -Purge old versions - -Created 3/26/1996 Heikki Tuuri -*******************************************************/ - -#include "trx0undo.h" - -/********************************************************************//** -Calculates the file address of an undo log header when we have the file -address of its history list node. -@return file address of the log */ -UNIV_INLINE -fil_addr_t -trx_purge_get_log_from_hist( -/*========================*/ - fil_addr_t node_addr) /*!< in: file address of the history - list node of the log */ -{ - node_addr.boffset -= TRX_UNDO_HISTORY_NODE; - - return(node_addr); -} - -/********************************************************************//** -address of its history list node. -@return true if purge_sys_t::limit <= purge_sys_t::iter */ -UNIV_INLINE -bool -trx_purge_check_limit(void) -/*=======================*/ -{ - /* limit is used to track till what point purge element has been - processed and so limit <= iter. - undo_no ordering is enforced only within the same rollback segment. - If a transaction uses multiple rollback segments then we need to - consider the rollback segment space id too. */ - return(purge_sys->iter.trx_no > purge_sys->limit.trx_no - || (purge_sys->iter.trx_no == purge_sys->limit.trx_no - && ((purge_sys->iter.undo_no >= purge_sys->limit.undo_no) - || (purge_sys->iter.undo_rseg_space - != purge_sys->limit.undo_rseg_space)))); -} - diff --git a/storage/innobase/include/trx0purge.inl b/storage/innobase/include/trx0purge.inl new file mode 100644 index 00000000000..0ccff6f7798 --- /dev/null +++ b/storage/innobase/include/trx0purge.inl @@ -0,0 +1,63 @@ +/***************************************************************************** + +Copyright (c) 1996, 2013, 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/trx0purge.ic +Purge old versions + +Created 3/26/1996 Heikki Tuuri +*******************************************************/ + +#include "trx0undo.h" + +/********************************************************************//** +Calculates the file address of an undo log header when we have the file +address of its history list node. +@return file address of the log */ +UNIV_INLINE +fil_addr_t +trx_purge_get_log_from_hist( +/*========================*/ + fil_addr_t node_addr) /*!< in: file address of the history + list node of the log */ +{ + node_addr.boffset -= TRX_UNDO_HISTORY_NODE; + + return(node_addr); +} + +/********************************************************************//** +address of its history list node. +@return true if purge_sys_t::limit <= purge_sys_t::iter */ +UNIV_INLINE +bool +trx_purge_check_limit(void) +/*=======================*/ +{ + /* limit is used to track till what point purge element has been + processed and so limit <= iter. + undo_no ordering is enforced only within the same rollback segment. + If a transaction uses multiple rollback segments then we need to + consider the rollback segment space id too. */ + return(purge_sys->iter.trx_no > purge_sys->limit.trx_no + || (purge_sys->iter.trx_no == purge_sys->limit.trx_no + && ((purge_sys->iter.undo_no >= purge_sys->limit.undo_no) + || (purge_sys->iter.undo_rseg_space + != purge_sys->limit.undo_rseg_space)))); +} + diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index be06db4c954..9d1a93ab9f4 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -341,6 +341,6 @@ record */ storage fields: used by purge to free the external storage */ -#include "trx0rec.ic" +#include "trx0rec.inl" #endif /* trx0rec_h */ diff --git a/storage/innobase/include/trx0rec.ic b/storage/innobase/include/trx0rec.ic deleted file mode 100644 index ecae142d8f5..00000000000 --- a/storage/innobase/include/trx0rec.ic +++ /dev/null @@ -1,102 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 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/trx0rec.ic -Transaction undo log record - -Created 3/26/1996 Heikki Tuuri -*******************************************************/ - -/**********************************************************************//** -Reads from an undo log record the record type. -@return record type */ -UNIV_INLINE -ulint -trx_undo_rec_get_type( -/*==================*/ - const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ -{ - return(mach_read_from_1(undo_rec + 2) & (TRX_UNDO_CMPL_INFO_MULT - 1)); -} - -/**********************************************************************//** -Reads from an undo log record the record compiler info. -@return compiler info */ -UNIV_INLINE -ulint -trx_undo_rec_get_cmpl_info( -/*=======================*/ - const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ -{ - return(mach_read_from_1(undo_rec + 2) / TRX_UNDO_CMPL_INFO_MULT); -} - -/**********************************************************************//** -Returns TRUE if an undo log record contains an extern storage field. -@return TRUE if extern */ -UNIV_INLINE -ibool -trx_undo_rec_get_extern_storage( -/*============================*/ - const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ -{ - if (mach_read_from_1(undo_rec + 2) & TRX_UNDO_UPD_EXTERN) { - - return(TRUE); - } - - return(FALSE); -} - -/**********************************************************************//** -Reads the undo log record number. -@return undo no */ -UNIV_INLINE -undo_no_t -trx_undo_rec_get_undo_no( -/*=====================*/ - const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ -{ - const byte* ptr; - - ptr = undo_rec + 3; - - return(mach_u64_read_much_compressed(ptr)); -} - -/***********************************************************************//** -Copies the undo record to the heap. -@return own: copy of undo log record */ -UNIV_INLINE -trx_undo_rec_t* -trx_undo_rec_copy( -/*==============*/ - const trx_undo_rec_t* undo_rec, /*!< in: undo log record */ - mem_heap_t* heap) /*!< in: heap where copied */ -{ - ulint len; - - len = mach_read_from_2(undo_rec) - - ut_align_offset(undo_rec, UNIV_PAGE_SIZE); - ut_ad(len < UNIV_PAGE_SIZE); - trx_undo_rec_t* rec = static_cast( - mem_heap_dup(heap, undo_rec, len)); - mach_write_to_2(rec, len); - return rec; -} diff --git a/storage/innobase/include/trx0rec.inl b/storage/innobase/include/trx0rec.inl new file mode 100644 index 00000000000..ecae142d8f5 --- /dev/null +++ b/storage/innobase/include/trx0rec.inl @@ -0,0 +1,102 @@ +/***************************************************************************** + +Copyright (c) 1996, 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/trx0rec.ic +Transaction undo log record + +Created 3/26/1996 Heikki Tuuri +*******************************************************/ + +/**********************************************************************//** +Reads from an undo log record the record type. +@return record type */ +UNIV_INLINE +ulint +trx_undo_rec_get_type( +/*==================*/ + const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ +{ + return(mach_read_from_1(undo_rec + 2) & (TRX_UNDO_CMPL_INFO_MULT - 1)); +} + +/**********************************************************************//** +Reads from an undo log record the record compiler info. +@return compiler info */ +UNIV_INLINE +ulint +trx_undo_rec_get_cmpl_info( +/*=======================*/ + const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ +{ + return(mach_read_from_1(undo_rec + 2) / TRX_UNDO_CMPL_INFO_MULT); +} + +/**********************************************************************//** +Returns TRUE if an undo log record contains an extern storage field. +@return TRUE if extern */ +UNIV_INLINE +ibool +trx_undo_rec_get_extern_storage( +/*============================*/ + const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ +{ + if (mach_read_from_1(undo_rec + 2) & TRX_UNDO_UPD_EXTERN) { + + return(TRUE); + } + + return(FALSE); +} + +/**********************************************************************//** +Reads the undo log record number. +@return undo no */ +UNIV_INLINE +undo_no_t +trx_undo_rec_get_undo_no( +/*=====================*/ + const trx_undo_rec_t* undo_rec) /*!< in: undo log record */ +{ + const byte* ptr; + + ptr = undo_rec + 3; + + return(mach_u64_read_much_compressed(ptr)); +} + +/***********************************************************************//** +Copies the undo record to the heap. +@return own: copy of undo log record */ +UNIV_INLINE +trx_undo_rec_t* +trx_undo_rec_copy( +/*==============*/ + const trx_undo_rec_t* undo_rec, /*!< in: undo log record */ + mem_heap_t* heap) /*!< in: heap where copied */ +{ + ulint len; + + len = mach_read_from_2(undo_rec) + - ut_align_offset(undo_rec, UNIV_PAGE_SIZE); + ut_ad(len < UNIV_PAGE_SIZE); + trx_undo_rec_t* rec = static_cast( + mem_heap_dup(heap, undo_rec, len)); + mach_write_to_2(rec, len); + return rec; +} diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h index 0fd6973e551..ae747b652ac 100644 --- a/storage/innobase/include/trx0roll.h +++ b/storage/innobase/include/trx0roll.h @@ -212,6 +212,6 @@ struct trx_named_savept_t{ transaction */ }; -#include "trx0roll.ic" +#include "trx0roll.inl" #endif diff --git a/storage/innobase/include/trx0roll.ic b/storage/innobase/include/trx0roll.ic deleted file mode 100644 index 79b8e9083dd..00000000000 --- a/storage/innobase/include/trx0roll.ic +++ /dev/null @@ -1,62 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2013, 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/trx0roll.ic -Transaction rollback - -Created 3/26/1996 Heikki Tuuri -*******************************************************/ - -#ifdef UNIV_DEBUG -/*******************************************************************//** -Check if undo numbering is maintained while processing undo records -for rollback. -@return true if undo numbering is maintained. */ -UNIV_INLINE -bool -trx_roll_check_undo_rec_ordering( -/*=============================*/ - undo_no_t curr_undo_rec_no, /*!< in: record number of - undo record to process. */ - ulint curr_undo_space_id, /*!< in: space-id of rollback - segment that contains the - undo record to process. */ - const trx_t* trx) /*!< in: transaction */ -{ - /* Each transaction now can have multiple rollback segments. - If a transaction involves temp and non-temp tables, both the rollback - segments will be active. In this case undo records will be distrubuted - across the two rollback segments. - CASE-1: UNDO action will apply all undo records from one rollback - segment before moving to next. This means undo record numbers can't be - sequential but ordering is still enforced as next undo record number - should be < processed undo record number. - CASE-2: For normal rollback (not initiated by crash) all rollback - segments will be active (including non-redo). - Based on transaction operation pattern undo record number of first - undo record from this new rollback segment can be > last undo number - from previous rollback segment and so we ignore this check if - rollback segments are switching. Once switched new rollback segment - should re-follow undo record number pattern (as mentioned in CASE-1). */ - - return(curr_undo_space_id != trx->undo_rseg_space - || curr_undo_rec_no + 1 <= trx->undo_no); -} -#endif /* UNIV_DEBUG */ - diff --git a/storage/innobase/include/trx0roll.inl b/storage/innobase/include/trx0roll.inl new file mode 100644 index 00000000000..79b8e9083dd --- /dev/null +++ b/storage/innobase/include/trx0roll.inl @@ -0,0 +1,62 @@ +/***************************************************************************** + +Copyright (c) 1996, 2013, 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/trx0roll.ic +Transaction rollback + +Created 3/26/1996 Heikki Tuuri +*******************************************************/ + +#ifdef UNIV_DEBUG +/*******************************************************************//** +Check if undo numbering is maintained while processing undo records +for rollback. +@return true if undo numbering is maintained. */ +UNIV_INLINE +bool +trx_roll_check_undo_rec_ordering( +/*=============================*/ + undo_no_t curr_undo_rec_no, /*!< in: record number of + undo record to process. */ + ulint curr_undo_space_id, /*!< in: space-id of rollback + segment that contains the + undo record to process. */ + const trx_t* trx) /*!< in: transaction */ +{ + /* Each transaction now can have multiple rollback segments. + If a transaction involves temp and non-temp tables, both the rollback + segments will be active. In this case undo records will be distrubuted + across the two rollback segments. + CASE-1: UNDO action will apply all undo records from one rollback + segment before moving to next. This means undo record numbers can't be + sequential but ordering is still enforced as next undo record number + should be < processed undo record number. + CASE-2: For normal rollback (not initiated by crash) all rollback + segments will be active (including non-redo). + Based on transaction operation pattern undo record number of first + undo record from this new rollback segment can be > last undo number + from previous rollback segment and so we ignore this check if + rollback segments are switching. Once switched new rollback segment + should re-follow undo record number pattern (as mentioned in CASE-1). */ + + return(curr_undo_space_id != trx->undo_rseg_space + || curr_undo_rec_no + 1 <= trx->undo_no); +} +#endif /* UNIV_DEBUG */ + diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index 8ca17998df4..db125d69b34 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -246,6 +246,6 @@ struct trx_rseg_t { /* Undo log segment slots */ /*-------------------------------------------------------------*/ -#include "trx0rseg.ic" +#include "trx0rseg.inl" #endif diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic deleted file mode 100644 index eed487176e8..00000000000 --- a/storage/innobase/include/trx0rseg.ic +++ /dev/null @@ -1,154 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2013, 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/trx0rseg.ic -Rollback segment - -Created 3/26/1996 Heikki Tuuri -*******************************************************/ - -#include "srv0srv.h" -#include "mtr0log.h" - -/** Gets a rollback segment header. -@param[in] space space where placed -@param[in] page_no page number of the header -@param[in,out] mtr mini-transaction -@return rollback segment header, page x-latched */ -UNIV_INLINE -trx_rsegf_t* -trx_rsegf_get( - ulint space, - ulint page_no, - mtr_t* mtr) -{ - buf_block_t* block; - trx_rsegf_t* header; - - ut_ad(space <= srv_undo_space_id_start + srv_undo_tablespaces_active - || space == SRV_TMP_SPACE_ID - || !srv_was_started); - ut_ad(space <= srv_undo_space_id_start + 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); - - buf_block_dbg_add_level(block, SYNC_RSEG_HEADER); - - header = TRX_RSEG + buf_block_get_frame(block); - - return(header); -} - -/** Gets a newly created rollback segment header. -@param[in] space space where placed -@param[in] page_no page number of the header -@param[in,out] mtr mini-transaction -@return rollback segment header, page x-latched */ -UNIV_INLINE -trx_rsegf_t* -trx_rsegf_get_new( - ulint space, - ulint page_no, - mtr_t* mtr) -{ - buf_block_t* block; - trx_rsegf_t* header; - - ut_ad(space <= srv_undo_tablespaces_active || space == SRV_TMP_SPACE_ID - || !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); - - buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); - - header = TRX_RSEG + buf_block_get_frame(block); - - return(header); -} - -/***************************************************************//** -Gets the file page number of the nth undo log slot. -@return page number of the undo log segment */ -UNIV_INLINE -ulint -trx_rsegf_get_nth_undo( -/*===================*/ - trx_rsegf_t* rsegf, /*!< in: rollback segment header */ - ulint n, /*!< in: index of slot */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_a(n < TRX_RSEG_N_SLOTS); - - return(mtr_read_ulint(rsegf + TRX_RSEG_UNDO_SLOTS - + n * TRX_RSEG_SLOT_SIZE, MLOG_4BYTES, mtr)); -} - -/***************************************************************//** -Sets the file page number of the nth undo log slot. */ -UNIV_INLINE -void -trx_rsegf_set_nth_undo( -/*===================*/ - trx_rsegf_t* rsegf, /*!< in: rollback segment header */ - ulint n, /*!< in: index of slot */ - ulint page_no,/*!< in: page number of the undo log segment */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_a(n < TRX_RSEG_N_SLOTS); - - mlog_write_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE, - page_no, MLOG_4BYTES, mtr); -} - -/****************************************************************//** -Looks for a free slot for an undo log segment. -@return slot index or ULINT_UNDEFINED if not found */ -UNIV_INLINE -ulint -trx_rsegf_undo_find_free( -/*=====================*/ - trx_rsegf_t* rsegf, /*!< in: rollback segment header */ - mtr_t* mtr) /*!< in: mtr */ -{ - ulint i; - ulint page_no; - ulint max_slots = TRX_RSEG_N_SLOTS; - -#ifdef UNIV_DEBUG - if (trx_rseg_n_slots_debug) { - max_slots = ut_min(static_cast(trx_rseg_n_slots_debug), - static_cast(TRX_RSEG_N_SLOTS)); - } -#endif - - for (i = 0; i < max_slots; i++) { - page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr); - - if (page_no == FIL_NULL) { - return(i); - } - } - - return(ULINT_UNDEFINED); -} diff --git a/storage/innobase/include/trx0rseg.inl b/storage/innobase/include/trx0rseg.inl new file mode 100644 index 00000000000..eed487176e8 --- /dev/null +++ b/storage/innobase/include/trx0rseg.inl @@ -0,0 +1,154 @@ +/***************************************************************************** + +Copyright (c) 1996, 2013, 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/trx0rseg.ic +Rollback segment + +Created 3/26/1996 Heikki Tuuri +*******************************************************/ + +#include "srv0srv.h" +#include "mtr0log.h" + +/** Gets a rollback segment header. +@param[in] space space where placed +@param[in] page_no page number of the header +@param[in,out] mtr mini-transaction +@return rollback segment header, page x-latched */ +UNIV_INLINE +trx_rsegf_t* +trx_rsegf_get( + ulint space, + ulint page_no, + mtr_t* mtr) +{ + buf_block_t* block; + trx_rsegf_t* header; + + ut_ad(space <= srv_undo_space_id_start + srv_undo_tablespaces_active + || space == SRV_TMP_SPACE_ID + || !srv_was_started); + ut_ad(space <= srv_undo_space_id_start + 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); + + buf_block_dbg_add_level(block, SYNC_RSEG_HEADER); + + header = TRX_RSEG + buf_block_get_frame(block); + + return(header); +} + +/** Gets a newly created rollback segment header. +@param[in] space space where placed +@param[in] page_no page number of the header +@param[in,out] mtr mini-transaction +@return rollback segment header, page x-latched */ +UNIV_INLINE +trx_rsegf_t* +trx_rsegf_get_new( + ulint space, + ulint page_no, + mtr_t* mtr) +{ + buf_block_t* block; + trx_rsegf_t* header; + + ut_ad(space <= srv_undo_tablespaces_active || space == SRV_TMP_SPACE_ID + || !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); + + buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); + + header = TRX_RSEG + buf_block_get_frame(block); + + return(header); +} + +/***************************************************************//** +Gets the file page number of the nth undo log slot. +@return page number of the undo log segment */ +UNIV_INLINE +ulint +trx_rsegf_get_nth_undo( +/*===================*/ + trx_rsegf_t* rsegf, /*!< in: rollback segment header */ + ulint n, /*!< in: index of slot */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_a(n < TRX_RSEG_N_SLOTS); + + return(mtr_read_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + + n * TRX_RSEG_SLOT_SIZE, MLOG_4BYTES, mtr)); +} + +/***************************************************************//** +Sets the file page number of the nth undo log slot. */ +UNIV_INLINE +void +trx_rsegf_set_nth_undo( +/*===================*/ + trx_rsegf_t* rsegf, /*!< in: rollback segment header */ + ulint n, /*!< in: index of slot */ + ulint page_no,/*!< in: page number of the undo log segment */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_a(n < TRX_RSEG_N_SLOTS); + + mlog_write_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE, + page_no, MLOG_4BYTES, mtr); +} + +/****************************************************************//** +Looks for a free slot for an undo log segment. +@return slot index or ULINT_UNDEFINED if not found */ +UNIV_INLINE +ulint +trx_rsegf_undo_find_free( +/*=====================*/ + trx_rsegf_t* rsegf, /*!< in: rollback segment header */ + mtr_t* mtr) /*!< in: mtr */ +{ + ulint i; + ulint page_no; + ulint max_slots = TRX_RSEG_N_SLOTS; + +#ifdef UNIV_DEBUG + if (trx_rseg_n_slots_debug) { + max_slots = ut_min(static_cast(trx_rseg_n_slots_debug), + static_cast(TRX_RSEG_N_SLOTS)); + } +#endif + + for (i = 0; i < max_slots; i++) { + page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr); + + if (page_no == FIL_NULL) { + return(i); + } + } + + return(ULINT_UNDEFINED); +} diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index c4b1636cfd2..6dad409f941 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -646,6 +646,6 @@ page is updated */ trx_sys->mutex.exit(); \ } while (0) -#include "trx0sys.ic" +#include "trx0sys.inl" #endif diff --git a/storage/innobase/include/trx0sys.ic b/storage/innobase/include/trx0sys.ic deleted file mode 100644 index 8518934e94f..00000000000 --- a/storage/innobase/include/trx0sys.ic +++ /dev/null @@ -1,460 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2021, 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/trx0sys.ic -Transaction system - -Created 3/26/1996 Heikki Tuuri -*******************************************************/ - -#include "trx0trx.h" -#include "data0type.h" -#include "srv0srv.h" -#include "mtr0log.h" - -/* The typedef for rseg slot in the file copy */ -typedef byte trx_sysf_rseg_t; - -/* Rollback segment specification slot offsets */ -/*-------------------------------------------------------------*/ -#define TRX_SYS_RSEG_SPACE 0 /* space where the segment - header is placed; starting with - MySQL/InnoDB 5.1.7, this is - UNIV_UNDEFINED if the slot is unused */ -#define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the segment - header is placed; this is FIL_NULL - if the slot is unused */ -/*-------------------------------------------------------------*/ -/* Size of a rollback segment specification slot */ -#define TRX_SYS_RSEG_SLOT_SIZE 8 - -/*****************************************************************//** -Writes the value of max_trx_id to the file based trx system header. */ -void -trx_sys_flush_max_trx_id(void); -/*==========================*/ - -/** Checks if a page address is the trx sys header page. -@param[in] page_id page id -@return true if trx sys header page */ -inline bool trx_sys_hdr_page(const page_id_t page_id) -{ - return(page_id.space() == TRX_SYS_SPACE - && page_id.page_no() == TRX_SYS_PAGE_NO); -} - -/**********************************************************************//** -Gets a pointer to the transaction system header and x-latches its page. -@return pointer to system header, page x-latched. */ -UNIV_INLINE -trx_sysf_t* -trx_sysf_get( -/*=========*/ - mtr_t* mtr) /*!< in: mtr */ -{ - buf_block_t* block = NULL; - trx_sysf_t* header = NULL; - - ut_ad(mtr); - - block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), - univ_page_size, RW_X_LATCH, mtr); - - if (block) { - buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER); - - header = TRX_SYS + buf_block_get_frame(block); - } - - return(header); -} - -/*****************************************************************//** -Gets the space of the nth rollback segment slot in the trx system -file copy. -@return space id */ -UNIV_INLINE -ulint -trx_sysf_rseg_get_space( -/*====================*/ - trx_sysf_t* sys_header, /*!< in: trx sys header */ - ulint i, /*!< in: slot index == rseg id */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(sys_header); - ut_ad(i < TRX_SYS_N_RSEGS); - - return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS - + i * TRX_SYS_RSEG_SLOT_SIZE - + TRX_SYS_RSEG_SPACE, MLOG_4BYTES, mtr)); -} - -/*****************************************************************//** -Gets the page number of the nth rollback segment slot in the trx system -header. -@return page number, FIL_NULL if slot unused */ -UNIV_INLINE -ulint -trx_sysf_rseg_get_page_no( -/*======================*/ - trx_sysf_t* sys_header, /*!< in: trx system header */ - ulint i, /*!< in: slot index == rseg id */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(sys_header); - ut_ad(i < TRX_SYS_N_RSEGS); - - return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS - + i * TRX_SYS_RSEG_SLOT_SIZE - + TRX_SYS_RSEG_PAGE_NO, MLOG_4BYTES, mtr)); -} - -/*****************************************************************//** -Sets the space id of the nth rollback segment slot in the trx system -file copy. */ -UNIV_INLINE -void -trx_sysf_rseg_set_space( -/*====================*/ - trx_sysf_t* sys_header, /*!< in: trx sys file copy */ - ulint i, /*!< in: slot index == rseg id */ - ulint space, /*!< in: space id */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(sys_header); - ut_ad(i < TRX_SYS_N_RSEGS); - - mlog_write_ulint(sys_header + TRX_SYS_RSEGS - + i * TRX_SYS_RSEG_SLOT_SIZE - + TRX_SYS_RSEG_SPACE, - space, - MLOG_4BYTES, mtr); -} - -/*****************************************************************//** -Sets the page number of the nth rollback segment slot in the trx system -header. */ -UNIV_INLINE -void -trx_sysf_rseg_set_page_no( -/*======================*/ - trx_sysf_t* sys_header, /*!< in: trx sys header */ - ulint i, /*!< in: slot index == rseg id */ - ulint page_no, /*!< in: page number, FIL_NULL if the - slot is reset to unused */ - mtr_t* mtr) /*!< in: mtr */ -{ - ut_ad(sys_header); - ut_ad(i < TRX_SYS_N_RSEGS); - - mlog_write_ulint(sys_header + TRX_SYS_RSEGS - + i * TRX_SYS_RSEG_SLOT_SIZE - + TRX_SYS_RSEG_PAGE_NO, - page_no, - MLOG_4BYTES, mtr); -} - -/*****************************************************************//** -Writes a trx id to an index page. In case that the id size changes in -some future version, this function should be used instead of -mach_write_... */ -UNIV_INLINE -void -trx_write_trx_id( -/*=============*/ - byte* ptr, /*!< in: pointer to memory where written */ - trx_id_t id) /*!< in: id */ -{ -#if DATA_TRX_ID_LEN != 6 -# error "DATA_TRX_ID_LEN != 6" -#endif - mach_write_to_6(ptr, id); -} - -/*****************************************************************//** -Reads a trx id from an index page. In case that the id size changes in -some future version, this function should be used instead of -mach_read_... -@return id */ -UNIV_INLINE -trx_id_t -trx_read_trx_id( -/*============*/ - const byte* ptr) /*!< in: pointer to memory from where to read */ -{ -#if DATA_TRX_ID_LEN != 6 -# error "DATA_TRX_ID_LEN != 6" -#endif - return(mach_read_from_6(ptr)); -} - -/****************************************************************//** -Looks for the trx handle with the given id in rw_trx_list. -The caller must be holding trx_sys->mutex. -@return the trx handle or NULL if not found; -the pointer must not be dereferenced unless lock_sys->mutex was -acquired before calling this function and is still being held */ -UNIV_INLINE -trx_t* -trx_get_rw_trx_by_id( -/*=================*/ - trx_id_t trx_id) /*!< in: trx id to search for */ -{ - ut_ad(trx_id > 0); - ut_ad(trx_sys_mutex_own()); - - if (trx_sys->rw_trx_set.empty()) { - return(NULL); - } - - TrxIdSet::iterator it; - - it = trx_sys->rw_trx_set.find(TrxTrack(trx_id)); - - return(it == trx_sys->rw_trx_set.end() ? NULL : it->m_trx); -} - -/****************************************************************//** -Returns the minimum trx id in trx list. This is the smallest id for which -the trx can possibly be active. (But, you must look at the trx->state -to find out if the minimum trx id transaction itself is active, or already -committed.). The caller must be holding the trx_sys_t::mutex in shared mode. -@return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty */ -UNIV_INLINE -trx_id_t -trx_rw_min_trx_id_low(void) -/*=======================*/ -{ - trx_id_t id; - - ut_ad(trx_sys_mutex_own()); - - const trx_t* trx = UT_LIST_GET_LAST(trx_sys->rw_trx_list); - - if (trx == NULL) { - id = trx_sys->max_trx_id; - } else { - ut_ad(!trx->read_only); - ut_ad(trx->in_rw_trx_list); - ut_ad(!trx->is_autocommit_non_locking()); - id = trx->id; - } - - return(id); -} - -#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG -/***********************************************************//** -Assert that a transaction has been recovered. -@return TRUE */ -UNIV_INLINE -ibool -trx_assert_recovered( -/*=================*/ - trx_id_t trx_id) /*!< in: transaction identifier */ -{ - const trx_t* trx; - - trx_sys_mutex_enter(); - - trx = trx_get_rw_trx_by_id(trx_id); - ut_a(trx->is_recovered); - - trx_sys_mutex_exit(); - - return(TRUE); -} -#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - -/****************************************************************//** -Returns the minimum trx id in rw trx list. This is the smallest id for which -the rw trx can possibly be active. (But, you must look at the trx->state -to find out if the minimum trx id transaction itself is active, or already -committed.) -@return the minimum trx id, or trx_sys->max_trx_id if rw trx list is empty */ -UNIV_INLINE -trx_id_t -trx_rw_min_trx_id(void) -/*===================*/ -{ - trx_sys_mutex_enter(); - - trx_id_t id = trx_rw_min_trx_id_low(); - - trx_sys_mutex_exit(); - - return(id); -} - -/** Look up a rw transaction with the given id. -@param[in] trx_id transaction identifier -@param[out] corrupt flag that will be set if trx_id is corrupted -@return transaction; its state should be rechecked after acquiring trx_t::mutex -@retval NULL if there is no transaction identified by trx_id. */ -inline trx_t* trx_rw_is_active_low(trx_id_t trx_id, bool* corrupt) -{ - ut_ad(trx_sys_mutex_own()); - - if (trx_id < trx_rw_min_trx_id_low()) { - } else if (trx_id >= trx_sys->max_trx_id) { - - /* There must be corruption: we let the caller handle the - diagnostic prints in this case. */ - - if (corrupt != NULL) { - *corrupt = true; - } - } else if (trx_t* trx = trx_get_rw_trx_by_id(trx_id)) { - return trx; - } - - return NULL; -} - -/** Look up a rw transaction with the given id. -@param[in] trx_id transaction identifier -@param[out] corrupt flag that will be set if trx_id is corrupted -@param[in] ref_count whether to increment trx->n_ref -@return transaction; its state should be rechecked after acquiring trx_t::mutex -@retval NULL if there is no active transaction identified by trx_id. */ -inline trx_t* trx_rw_is_active(trx_id_t trx_id, bool* corrupt, bool ref_count) -{ - ut_ad(trx_id); - - trx_sys_mutex_enter(); - - trx_t* trx = trx_rw_is_active_low(trx_id, corrupt); - - if (trx && ref_count) { - TrxMutex* trx_mutex = &trx->mutex; - mutex_enter(trx_mutex); - ut_ad(!trx_state_eq(trx, TRX_STATE_NOT_STARTED)); - ut_ad(trx->id == trx_id); - if (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)) { - /* We have an early state check here to avoid - committer starvation in a wait loop for - transaction references, when there's a stream of - trx_rw_is_active() calls from other threads. - The trx->state may change to COMMITTED after - trx_mutex is released, and it will have to be - rechecked by the caller after reacquiring the mutex. */ - trx = NULL; - } else { - /* The reference could be safely incremented after - releasing one of trx_mutex or trx_sys->mutex. - Holding trx->mutex here may prevent a few false - references that could have a negative performance - impact on trx_commit_in_memory(). */ - trx->reference(); - } - mutex_exit(trx_mutex); - } - - trx_sys_mutex_exit(); - - return(trx); -} - -/*****************************************************************//** -Allocates a new transaction id. -@return new, allocated trx id */ -UNIV_INLINE -trx_id_t -trx_sys_get_new_trx_id() -/*====================*/ -{ - /* wsrep_fake_trx_id violates this assert */ - ut_ad(trx_sys_mutex_own()); - - /* VERY important: after the database is started, max_trx_id value is - divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if - will evaluate to TRUE when this function is first time called, - and the value for trx id will be written to disk-based header! - Thus trx id values will not overlap when the database is - repeatedly started! */ - - if (!(trx_sys->max_trx_id % TRX_SYS_TRX_ID_WRITE_MARGIN)) { - - trx_sys_flush_max_trx_id(); - } - - return(trx_sys->max_trx_id++); -} - -/*****************************************************************//** -Determines the maximum transaction id. -@return maximum currently allocated trx id; will be stale after the -next call to trx_sys_get_new_trx_id() */ -UNIV_INLINE -trx_id_t -trx_sys_get_max_trx_id(void) -/*========================*/ -{ - ut_ad(!trx_sys_mutex_own()); - -#if UNIV_WORD_SIZE < DATA_TRX_ID_LEN - /* Avoid torn reads. */ - - trx_sys_mutex_enter(); - - trx_id_t max_trx_id = trx_sys->max_trx_id; - - trx_sys_mutex_exit(); - - return(max_trx_id); -#else - /* Perform a dirty read. Callers should be prepared for stale - values, and we know that the value fits in a machine word, so - that it will be read and written atomically. */ - return(trx_sys->max_trx_id); -#endif /* UNIV_WORD_SIZE < DATA_TRX_ID_LEN */ -} - -/*****************************************************************//** -Get the number of transaction in the system, independent of their state. -@return count of transactions in trx_sys_t::rw_trx_list */ -UNIV_INLINE -ulint -trx_sys_get_n_rw_trx(void) -/*======================*/ -{ - ulint n_trx; - - trx_sys_mutex_enter(); - - n_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); - - trx_sys_mutex_exit(); - - return(n_trx); -} - -/** -Add the transaction to the RW transaction set -@param trx transaction instance to add */ -UNIV_INLINE -void -trx_sys_rw_trx_add(trx_t* trx) -{ - ut_ad(trx->id != 0); - - trx_sys->rw_trx_set.insert(TrxTrack(trx->id, trx)); - ut_d(trx->in_rw_trx_list = true); -} diff --git a/storage/innobase/include/trx0sys.inl b/storage/innobase/include/trx0sys.inl new file mode 100644 index 00000000000..8518934e94f --- /dev/null +++ b/storage/innobase/include/trx0sys.inl @@ -0,0 +1,460 @@ +/***************************************************************************** + +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, 2021, 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/trx0sys.ic +Transaction system + +Created 3/26/1996 Heikki Tuuri +*******************************************************/ + +#include "trx0trx.h" +#include "data0type.h" +#include "srv0srv.h" +#include "mtr0log.h" + +/* The typedef for rseg slot in the file copy */ +typedef byte trx_sysf_rseg_t; + +/* Rollback segment specification slot offsets */ +/*-------------------------------------------------------------*/ +#define TRX_SYS_RSEG_SPACE 0 /* space where the segment + header is placed; starting with + MySQL/InnoDB 5.1.7, this is + UNIV_UNDEFINED if the slot is unused */ +#define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the segment + header is placed; this is FIL_NULL + if the slot is unused */ +/*-------------------------------------------------------------*/ +/* Size of a rollback segment specification slot */ +#define TRX_SYS_RSEG_SLOT_SIZE 8 + +/*****************************************************************//** +Writes the value of max_trx_id to the file based trx system header. */ +void +trx_sys_flush_max_trx_id(void); +/*==========================*/ + +/** Checks if a page address is the trx sys header page. +@param[in] page_id page id +@return true if trx sys header page */ +inline bool trx_sys_hdr_page(const page_id_t page_id) +{ + return(page_id.space() == TRX_SYS_SPACE + && page_id.page_no() == TRX_SYS_PAGE_NO); +} + +/**********************************************************************//** +Gets a pointer to the transaction system header and x-latches its page. +@return pointer to system header, page x-latched. */ +UNIV_INLINE +trx_sysf_t* +trx_sysf_get( +/*=========*/ + mtr_t* mtr) /*!< in: mtr */ +{ + buf_block_t* block = NULL; + trx_sysf_t* header = NULL; + + ut_ad(mtr); + + block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), + univ_page_size, RW_X_LATCH, mtr); + + if (block) { + buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER); + + header = TRX_SYS + buf_block_get_frame(block); + } + + return(header); +} + +/*****************************************************************//** +Gets the space of the nth rollback segment slot in the trx system +file copy. +@return space id */ +UNIV_INLINE +ulint +trx_sysf_rseg_get_space( +/*====================*/ + trx_sysf_t* sys_header, /*!< in: trx sys header */ + ulint i, /*!< in: slot index == rseg id */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(sys_header); + ut_ad(i < TRX_SYS_N_RSEGS); + + return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS + + i * TRX_SYS_RSEG_SLOT_SIZE + + TRX_SYS_RSEG_SPACE, MLOG_4BYTES, mtr)); +} + +/*****************************************************************//** +Gets the page number of the nth rollback segment slot in the trx system +header. +@return page number, FIL_NULL if slot unused */ +UNIV_INLINE +ulint +trx_sysf_rseg_get_page_no( +/*======================*/ + trx_sysf_t* sys_header, /*!< in: trx system header */ + ulint i, /*!< in: slot index == rseg id */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(sys_header); + ut_ad(i < TRX_SYS_N_RSEGS); + + return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS + + i * TRX_SYS_RSEG_SLOT_SIZE + + TRX_SYS_RSEG_PAGE_NO, MLOG_4BYTES, mtr)); +} + +/*****************************************************************//** +Sets the space id of the nth rollback segment slot in the trx system +file copy. */ +UNIV_INLINE +void +trx_sysf_rseg_set_space( +/*====================*/ + trx_sysf_t* sys_header, /*!< in: trx sys file copy */ + ulint i, /*!< in: slot index == rseg id */ + ulint space, /*!< in: space id */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(sys_header); + ut_ad(i < TRX_SYS_N_RSEGS); + + mlog_write_ulint(sys_header + TRX_SYS_RSEGS + + i * TRX_SYS_RSEG_SLOT_SIZE + + TRX_SYS_RSEG_SPACE, + space, + MLOG_4BYTES, mtr); +} + +/*****************************************************************//** +Sets the page number of the nth rollback segment slot in the trx system +header. */ +UNIV_INLINE +void +trx_sysf_rseg_set_page_no( +/*======================*/ + trx_sysf_t* sys_header, /*!< in: trx sys header */ + ulint i, /*!< in: slot index == rseg id */ + ulint page_no, /*!< in: page number, FIL_NULL if the + slot is reset to unused */ + mtr_t* mtr) /*!< in: mtr */ +{ + ut_ad(sys_header); + ut_ad(i < TRX_SYS_N_RSEGS); + + mlog_write_ulint(sys_header + TRX_SYS_RSEGS + + i * TRX_SYS_RSEG_SLOT_SIZE + + TRX_SYS_RSEG_PAGE_NO, + page_no, + MLOG_4BYTES, mtr); +} + +/*****************************************************************//** +Writes a trx id to an index page. In case that the id size changes in +some future version, this function should be used instead of +mach_write_... */ +UNIV_INLINE +void +trx_write_trx_id( +/*=============*/ + byte* ptr, /*!< in: pointer to memory where written */ + trx_id_t id) /*!< in: id */ +{ +#if DATA_TRX_ID_LEN != 6 +# error "DATA_TRX_ID_LEN != 6" +#endif + mach_write_to_6(ptr, id); +} + +/*****************************************************************//** +Reads a trx id from an index page. In case that the id size changes in +some future version, this function should be used instead of +mach_read_... +@return id */ +UNIV_INLINE +trx_id_t +trx_read_trx_id( +/*============*/ + const byte* ptr) /*!< in: pointer to memory from where to read */ +{ +#if DATA_TRX_ID_LEN != 6 +# error "DATA_TRX_ID_LEN != 6" +#endif + return(mach_read_from_6(ptr)); +} + +/****************************************************************//** +Looks for the trx handle with the given id in rw_trx_list. +The caller must be holding trx_sys->mutex. +@return the trx handle or NULL if not found; +the pointer must not be dereferenced unless lock_sys->mutex was +acquired before calling this function and is still being held */ +UNIV_INLINE +trx_t* +trx_get_rw_trx_by_id( +/*=================*/ + trx_id_t trx_id) /*!< in: trx id to search for */ +{ + ut_ad(trx_id > 0); + ut_ad(trx_sys_mutex_own()); + + if (trx_sys->rw_trx_set.empty()) { + return(NULL); + } + + TrxIdSet::iterator it; + + it = trx_sys->rw_trx_set.find(TrxTrack(trx_id)); + + return(it == trx_sys->rw_trx_set.end() ? NULL : it->m_trx); +} + +/****************************************************************//** +Returns the minimum trx id in trx list. This is the smallest id for which +the trx can possibly be active. (But, you must look at the trx->state +to find out if the minimum trx id transaction itself is active, or already +committed.). The caller must be holding the trx_sys_t::mutex in shared mode. +@return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty */ +UNIV_INLINE +trx_id_t +trx_rw_min_trx_id_low(void) +/*=======================*/ +{ + trx_id_t id; + + ut_ad(trx_sys_mutex_own()); + + const trx_t* trx = UT_LIST_GET_LAST(trx_sys->rw_trx_list); + + if (trx == NULL) { + id = trx_sys->max_trx_id; + } else { + ut_ad(!trx->read_only); + ut_ad(trx->in_rw_trx_list); + ut_ad(!trx->is_autocommit_non_locking()); + id = trx->id; + } + + return(id); +} + +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG +/***********************************************************//** +Assert that a transaction has been recovered. +@return TRUE */ +UNIV_INLINE +ibool +trx_assert_recovered( +/*=================*/ + trx_id_t trx_id) /*!< in: transaction identifier */ +{ + const trx_t* trx; + + trx_sys_mutex_enter(); + + trx = trx_get_rw_trx_by_id(trx_id); + ut_a(trx->is_recovered); + + trx_sys_mutex_exit(); + + return(TRUE); +} +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ + +/****************************************************************//** +Returns the minimum trx id in rw trx list. This is the smallest id for which +the rw trx can possibly be active. (But, you must look at the trx->state +to find out if the minimum trx id transaction itself is active, or already +committed.) +@return the minimum trx id, or trx_sys->max_trx_id if rw trx list is empty */ +UNIV_INLINE +trx_id_t +trx_rw_min_trx_id(void) +/*===================*/ +{ + trx_sys_mutex_enter(); + + trx_id_t id = trx_rw_min_trx_id_low(); + + trx_sys_mutex_exit(); + + return(id); +} + +/** Look up a rw transaction with the given id. +@param[in] trx_id transaction identifier +@param[out] corrupt flag that will be set if trx_id is corrupted +@return transaction; its state should be rechecked after acquiring trx_t::mutex +@retval NULL if there is no transaction identified by trx_id. */ +inline trx_t* trx_rw_is_active_low(trx_id_t trx_id, bool* corrupt) +{ + ut_ad(trx_sys_mutex_own()); + + if (trx_id < trx_rw_min_trx_id_low()) { + } else if (trx_id >= trx_sys->max_trx_id) { + + /* There must be corruption: we let the caller handle the + diagnostic prints in this case. */ + + if (corrupt != NULL) { + *corrupt = true; + } + } else if (trx_t* trx = trx_get_rw_trx_by_id(trx_id)) { + return trx; + } + + return NULL; +} + +/** Look up a rw transaction with the given id. +@param[in] trx_id transaction identifier +@param[out] corrupt flag that will be set if trx_id is corrupted +@param[in] ref_count whether to increment trx->n_ref +@return transaction; its state should be rechecked after acquiring trx_t::mutex +@retval NULL if there is no active transaction identified by trx_id. */ +inline trx_t* trx_rw_is_active(trx_id_t trx_id, bool* corrupt, bool ref_count) +{ + ut_ad(trx_id); + + trx_sys_mutex_enter(); + + trx_t* trx = trx_rw_is_active_low(trx_id, corrupt); + + if (trx && ref_count) { + TrxMutex* trx_mutex = &trx->mutex; + mutex_enter(trx_mutex); + ut_ad(!trx_state_eq(trx, TRX_STATE_NOT_STARTED)); + ut_ad(trx->id == trx_id); + if (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)) { + /* We have an early state check here to avoid + committer starvation in a wait loop for + transaction references, when there's a stream of + trx_rw_is_active() calls from other threads. + The trx->state may change to COMMITTED after + trx_mutex is released, and it will have to be + rechecked by the caller after reacquiring the mutex. */ + trx = NULL; + } else { + /* The reference could be safely incremented after + releasing one of trx_mutex or trx_sys->mutex. + Holding trx->mutex here may prevent a few false + references that could have a negative performance + impact on trx_commit_in_memory(). */ + trx->reference(); + } + mutex_exit(trx_mutex); + } + + trx_sys_mutex_exit(); + + return(trx); +} + +/*****************************************************************//** +Allocates a new transaction id. +@return new, allocated trx id */ +UNIV_INLINE +trx_id_t +trx_sys_get_new_trx_id() +/*====================*/ +{ + /* wsrep_fake_trx_id violates this assert */ + ut_ad(trx_sys_mutex_own()); + + /* VERY important: after the database is started, max_trx_id value is + divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if + will evaluate to TRUE when this function is first time called, + and the value for trx id will be written to disk-based header! + Thus trx id values will not overlap when the database is + repeatedly started! */ + + if (!(trx_sys->max_trx_id % TRX_SYS_TRX_ID_WRITE_MARGIN)) { + + trx_sys_flush_max_trx_id(); + } + + return(trx_sys->max_trx_id++); +} + +/*****************************************************************//** +Determines the maximum transaction id. +@return maximum currently allocated trx id; will be stale after the +next call to trx_sys_get_new_trx_id() */ +UNIV_INLINE +trx_id_t +trx_sys_get_max_trx_id(void) +/*========================*/ +{ + ut_ad(!trx_sys_mutex_own()); + +#if UNIV_WORD_SIZE < DATA_TRX_ID_LEN + /* Avoid torn reads. */ + + trx_sys_mutex_enter(); + + trx_id_t max_trx_id = trx_sys->max_trx_id; + + trx_sys_mutex_exit(); + + return(max_trx_id); +#else + /* Perform a dirty read. Callers should be prepared for stale + values, and we know that the value fits in a machine word, so + that it will be read and written atomically. */ + return(trx_sys->max_trx_id); +#endif /* UNIV_WORD_SIZE < DATA_TRX_ID_LEN */ +} + +/*****************************************************************//** +Get the number of transaction in the system, independent of their state. +@return count of transactions in trx_sys_t::rw_trx_list */ +UNIV_INLINE +ulint +trx_sys_get_n_rw_trx(void) +/*======================*/ +{ + ulint n_trx; + + trx_sys_mutex_enter(); + + n_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); + + trx_sys_mutex_exit(); + + return(n_trx); +} + +/** +Add the transaction to the RW transaction set +@param trx transaction instance to add */ +UNIV_INLINE +void +trx_sys_rw_trx_add(trx_t* trx) +{ + ut_ad(trx->id != 0); + + trx_sys->rw_trx_set.insert(TrxTrack(trx->id, trx)); + ut_d(trx->in_rw_trx_list = true); +} diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 90365400d72..47a93c805ab 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1208,6 +1208,6 @@ struct commit_node_t{ mutex_exit(&t->mutex); \ } while (0) -#include "trx0trx.ic" +#include "trx0trx.inl" #endif diff --git a/storage/innobase/include/trx0trx.ic b/storage/innobase/include/trx0trx.ic deleted file mode 100644 index 2a53509b206..00000000000 --- a/storage/innobase/include/trx0trx.ic +++ /dev/null @@ -1,234 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2021, 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/trx0trx.ic -The transaction - -Created 3/26/1996 Heikki Tuuri -*******************************************************/ - -#include "read0read.h" - -/**********************************************************************//** -Determines if a transaction is in the given state. -The caller must hold trx_sys->mutex, or it must be the thread -that is serving a running transaction. -A running RW transaction must be in trx_sys->rw_trx_list. -@return TRUE if trx->state == state */ -UNIV_INLINE -bool -trx_state_eq( -/*=========*/ - const trx_t* trx, /*!< in: transaction */ - trx_state_t state, /*!< in: state; - if state != TRX_STATE_NOT_STARTED - asserts that - trx->state != TRX_STATE_NOT_STARTED */ - bool relaxed) - /*!< in: whether to allow - trx->state == TRX_STATE_NOT_STARTED - after an error has been reported */ -{ -#ifdef UNIV_DEBUG - switch (trx->state) { - case TRX_STATE_PREPARED: - case TRX_STATE_PREPARED_RECOVERED: - case TRX_STATE_COMMITTED_IN_MEMORY: - ut_ad(!trx->is_autocommit_non_locking()); - return(trx->state == state); - - case TRX_STATE_ACTIVE: - if (trx->is_autocommit_non_locking()) { - ut_ad(!trx->is_recovered); - ut_ad(trx->read_only); - ut_ad(trx->mysql_thd); - ut_ad(!trx->in_rw_trx_list); - ut_ad(trx->in_mysql_trx_list); - } - return(state == trx->state); - - case TRX_STATE_NOT_STARTED: - /* These states are not allowed for running transactions. */ - ut_a(state == TRX_STATE_NOT_STARTED - || (relaxed - && thd_get_error_number(trx->mysql_thd))); - - ut_ad(!trx->in_rw_trx_list); - - return(true); - } - ut_error; -#endif /* UNIV_DEBUG */ - return(trx->state == state); -} - -/****************************************************************//** -Retrieves the error_info field from a trx. -@return the error info */ -UNIV_INLINE -const dict_index_t* -trx_get_error_info( -/*===============*/ - const trx_t* trx) /*!< in: trx object */ -{ - return(trx->error_info); -} - -/*******************************************************************//** -Retrieves transaction's que state in a human readable string. The string -should not be free()'d or modified. -@return string in the data segment */ -UNIV_INLINE -const char* -trx_get_que_state_str( -/*==================*/ - const trx_t* trx) /*!< in: transaction */ -{ - /* be sure to adjust TRX_QUE_STATE_STR_MAX_LEN if you change this */ - switch (trx->lock.que_state) { - case TRX_QUE_RUNNING: - return("RUNNING"); - case TRX_QUE_LOCK_WAIT: - return("LOCK WAIT"); - case TRX_QUE_ROLLING_BACK: - return("ROLLING BACK"); - case TRX_QUE_COMMITTING: - return("COMMITTING"); - default: - return("UNKNOWN"); - } -} - -/** Retreieves the transaction ID. -In a given point in time it is guaranteed that IDs of the running -transactions are unique. The values returned by this function for readonly -transactions may be reused, so a subsequent RO transaction may get the same ID -as a RO transaction that existed in the past. The values returned by this -function should be used for printing purposes only. -@param[in] trx transaction whose id to retrieve -@return transaction id */ -UNIV_INLINE -trx_id_t -trx_get_id_for_print( - const trx_t* trx) -{ - /* Readonly and transactions whose intentions are unknown (whether - they will eventually do a WRITE) don't have trx_t::id assigned (it is - 0 for those transactions). Transaction IDs in - innodb_trx.trx_id, - innodb_locks.lock_id, - innodb_locks.lock_trx_id, - innodb_lock_waits.requesting_trx_id, - innodb_lock_waits.blocking_trx_id should match because those tables - could be used in an SQL JOIN on those columns. Also trx_t::id is - printed by SHOW ENGINE INNODB STATUS, and in logs, so we must have the - same value printed everywhere consistently. */ - - /* DATA_TRX_ID_LEN is the storage size in bytes. */ - static const trx_id_t max_trx_id - = (1ULL << (DATA_TRX_ID_LEN * CHAR_BIT)) - 1; - - ut_ad(trx->id <= max_trx_id); - - return(trx->id != 0 - ? trx->id - : reinterpret_cast(trx) | (max_trx_id + 1)); -} - -/**********************************************************************//** -Determine if a transaction is a dictionary operation. -@return dictionary operation mode */ -UNIV_INLINE -enum trx_dict_op_t -trx_get_dict_operation( -/*===================*/ - const trx_t* trx) /*!< in: transaction */ -{ - trx_dict_op_t op = static_cast(trx->dict_operation); - -#ifdef UNIV_DEBUG - switch (op) { - case TRX_DICT_OP_NONE: - case TRX_DICT_OP_TABLE: - case TRX_DICT_OP_INDEX: - return(op); - } - ut_error; -#endif /* UNIV_DEBUG */ - return(op); -} -/**********************************************************************//** -Flag a transaction a dictionary operation. */ -UNIV_INLINE -void -trx_set_dict_operation( -/*===================*/ - trx_t* trx, /*!< in/out: transaction */ - enum trx_dict_op_t op) /*!< in: operation, not - TRX_DICT_OP_NONE */ -{ -#ifdef UNIV_DEBUG - enum trx_dict_op_t old_op = trx_get_dict_operation(trx); - - switch (op) { - case TRX_DICT_OP_NONE: - ut_error; - break; - case TRX_DICT_OP_TABLE: - switch (old_op) { - case TRX_DICT_OP_NONE: - case TRX_DICT_OP_INDEX: - case TRX_DICT_OP_TABLE: - goto ok; - } - ut_error; - break; - case TRX_DICT_OP_INDEX: - ut_ad(old_op == TRX_DICT_OP_NONE); - break; - } -ok: -#endif /* UNIV_DEBUG */ - - trx->ddl = true; - trx->dict_operation = op; -} - -/** -@param trx Get the active view for this transaction, if one exists -@return the transaction's read view or NULL if one not assigned. */ -UNIV_INLINE -ReadView* -trx_get_read_view( - trx_t* trx) -{ - return(!MVCC::is_view_active(trx->read_view) ? NULL : trx->read_view); -} - -/** -@param trx Get the active view for this transaction, if one exists -@return the transaction's read view or NULL if one not assigned. */ -UNIV_INLINE -const ReadView* -trx_get_read_view( - const trx_t* trx) -{ - return(!MVCC::is_view_active(trx->read_view) ? NULL : trx->read_view); -} diff --git a/storage/innobase/include/trx0trx.inl b/storage/innobase/include/trx0trx.inl new file mode 100644 index 00000000000..2a53509b206 --- /dev/null +++ b/storage/innobase/include/trx0trx.inl @@ -0,0 +1,234 @@ +/***************************************************************************** + +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, 2021, 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/trx0trx.ic +The transaction + +Created 3/26/1996 Heikki Tuuri +*******************************************************/ + +#include "read0read.h" + +/**********************************************************************//** +Determines if a transaction is in the given state. +The caller must hold trx_sys->mutex, or it must be the thread +that is serving a running transaction. +A running RW transaction must be in trx_sys->rw_trx_list. +@return TRUE if trx->state == state */ +UNIV_INLINE +bool +trx_state_eq( +/*=========*/ + const trx_t* trx, /*!< in: transaction */ + trx_state_t state, /*!< in: state; + if state != TRX_STATE_NOT_STARTED + asserts that + trx->state != TRX_STATE_NOT_STARTED */ + bool relaxed) + /*!< in: whether to allow + trx->state == TRX_STATE_NOT_STARTED + after an error has been reported */ +{ +#ifdef UNIV_DEBUG + switch (trx->state) { + case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: + case TRX_STATE_COMMITTED_IN_MEMORY: + ut_ad(!trx->is_autocommit_non_locking()); + return(trx->state == state); + + case TRX_STATE_ACTIVE: + if (trx->is_autocommit_non_locking()) { + ut_ad(!trx->is_recovered); + ut_ad(trx->read_only); + ut_ad(trx->mysql_thd); + ut_ad(!trx->in_rw_trx_list); + ut_ad(trx->in_mysql_trx_list); + } + return(state == trx->state); + + case TRX_STATE_NOT_STARTED: + /* These states are not allowed for running transactions. */ + ut_a(state == TRX_STATE_NOT_STARTED + || (relaxed + && thd_get_error_number(trx->mysql_thd))); + + ut_ad(!trx->in_rw_trx_list); + + return(true); + } + ut_error; +#endif /* UNIV_DEBUG */ + return(trx->state == state); +} + +/****************************************************************//** +Retrieves the error_info field from a trx. +@return the error info */ +UNIV_INLINE +const dict_index_t* +trx_get_error_info( +/*===============*/ + const trx_t* trx) /*!< in: trx object */ +{ + return(trx->error_info); +} + +/*******************************************************************//** +Retrieves transaction's que state in a human readable string. The string +should not be free()'d or modified. +@return string in the data segment */ +UNIV_INLINE +const char* +trx_get_que_state_str( +/*==================*/ + const trx_t* trx) /*!< in: transaction */ +{ + /* be sure to adjust TRX_QUE_STATE_STR_MAX_LEN if you change this */ + switch (trx->lock.que_state) { + case TRX_QUE_RUNNING: + return("RUNNING"); + case TRX_QUE_LOCK_WAIT: + return("LOCK WAIT"); + case TRX_QUE_ROLLING_BACK: + return("ROLLING BACK"); + case TRX_QUE_COMMITTING: + return("COMMITTING"); + default: + return("UNKNOWN"); + } +} + +/** Retreieves the transaction ID. +In a given point in time it is guaranteed that IDs of the running +transactions are unique. The values returned by this function for readonly +transactions may be reused, so a subsequent RO transaction may get the same ID +as a RO transaction that existed in the past. The values returned by this +function should be used for printing purposes only. +@param[in] trx transaction whose id to retrieve +@return transaction id */ +UNIV_INLINE +trx_id_t +trx_get_id_for_print( + const trx_t* trx) +{ + /* Readonly and transactions whose intentions are unknown (whether + they will eventually do a WRITE) don't have trx_t::id assigned (it is + 0 for those transactions). Transaction IDs in + innodb_trx.trx_id, + innodb_locks.lock_id, + innodb_locks.lock_trx_id, + innodb_lock_waits.requesting_trx_id, + innodb_lock_waits.blocking_trx_id should match because those tables + could be used in an SQL JOIN on those columns. Also trx_t::id is + printed by SHOW ENGINE INNODB STATUS, and in logs, so we must have the + same value printed everywhere consistently. */ + + /* DATA_TRX_ID_LEN is the storage size in bytes. */ + static const trx_id_t max_trx_id + = (1ULL << (DATA_TRX_ID_LEN * CHAR_BIT)) - 1; + + ut_ad(trx->id <= max_trx_id); + + return(trx->id != 0 + ? trx->id + : reinterpret_cast(trx) | (max_trx_id + 1)); +} + +/**********************************************************************//** +Determine if a transaction is a dictionary operation. +@return dictionary operation mode */ +UNIV_INLINE +enum trx_dict_op_t +trx_get_dict_operation( +/*===================*/ + const trx_t* trx) /*!< in: transaction */ +{ + trx_dict_op_t op = static_cast(trx->dict_operation); + +#ifdef UNIV_DEBUG + switch (op) { + case TRX_DICT_OP_NONE: + case TRX_DICT_OP_TABLE: + case TRX_DICT_OP_INDEX: + return(op); + } + ut_error; +#endif /* UNIV_DEBUG */ + return(op); +} +/**********************************************************************//** +Flag a transaction a dictionary operation. */ +UNIV_INLINE +void +trx_set_dict_operation( +/*===================*/ + trx_t* trx, /*!< in/out: transaction */ + enum trx_dict_op_t op) /*!< in: operation, not + TRX_DICT_OP_NONE */ +{ +#ifdef UNIV_DEBUG + enum trx_dict_op_t old_op = trx_get_dict_operation(trx); + + switch (op) { + case TRX_DICT_OP_NONE: + ut_error; + break; + case TRX_DICT_OP_TABLE: + switch (old_op) { + case TRX_DICT_OP_NONE: + case TRX_DICT_OP_INDEX: + case TRX_DICT_OP_TABLE: + goto ok; + } + ut_error; + break; + case TRX_DICT_OP_INDEX: + ut_ad(old_op == TRX_DICT_OP_NONE); + break; + } +ok: +#endif /* UNIV_DEBUG */ + + trx->ddl = true; + trx->dict_operation = op; +} + +/** +@param trx Get the active view for this transaction, if one exists +@return the transaction's read view or NULL if one not assigned. */ +UNIV_INLINE +ReadView* +trx_get_read_view( + trx_t* trx) +{ + return(!MVCC::is_view_active(trx->read_view) ? NULL : trx->read_view); +} + +/** +@param trx Get the active view for this transaction, if one exists +@return the transaction's read view or NULL if one not assigned. */ +UNIV_INLINE +const ReadView* +trx_get_read_view( + const trx_t* trx) +{ + return(!MVCC::is_view_active(trx->read_view) ? NULL : trx->read_view); +} diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index 99330453c33..4edac22289c 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -558,7 +558,7 @@ quite a large overhead. */ with the XA XID */ /* @} */ -#include "trx0undo.ic" +#include "trx0undo.inl" #endif /* !UNIV_INNOCHECKSUM */ #endif diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic deleted file mode 100644 index 2e26e6547c3..00000000000 --- a/storage/innobase/include/trx0undo.ic +++ /dev/null @@ -1,352 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2013, 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/trx0undo.ic -Transaction undo log - -Created 3/26/1996 Heikki Tuuri -*******************************************************/ - -#include "data0type.h" -#include "page0page.h" - -/***********************************************************************//** -Builds a roll pointer. -@return roll pointer */ -UNIV_INLINE -roll_ptr_t -trx_undo_build_roll_ptr( -/*====================*/ - ibool is_insert, /*!< in: TRUE if insert undo log */ - ulint rseg_id, /*!< in: rollback segment id */ - ulint page_no, /*!< in: page number */ - ulint offset) /*!< in: offset of the undo entry within page */ -{ - roll_ptr_t roll_ptr; -#if DATA_ROLL_PTR_LEN != 7 -# error "DATA_ROLL_PTR_LEN != 7" -#endif - ut_ad(is_insert == 0 || is_insert == 1); - ut_ad(rseg_id < TRX_SYS_N_RSEGS); - ut_ad(offset < 65536); - - roll_ptr = (roll_ptr_t) is_insert << ROLL_PTR_INSERT_FLAG_POS - | (roll_ptr_t) rseg_id << ROLL_PTR_RSEG_ID_POS - | (roll_ptr_t) page_no << ROLL_PTR_PAGE_POS - | offset; - return(roll_ptr); -} - -/***********************************************************************//** -Decodes a roll pointer. */ -UNIV_INLINE -void -trx_undo_decode_roll_ptr( -/*=====================*/ - roll_ptr_t roll_ptr, /*!< in: roll pointer */ - ibool* is_insert, /*!< out: TRUE if insert undo log */ - ulint* rseg_id, /*!< out: rollback segment id */ - ulint* page_no, /*!< out: page number */ - ulint* offset) /*!< out: offset of the undo - entry within page */ -{ -#if DATA_ROLL_PTR_LEN != 7 -# error "DATA_ROLL_PTR_LEN != 7" -#endif -#if TRUE != 1 -# error "TRUE != 1" -#endif - ut_ad(roll_ptr < (1ULL << 56)); - *offset = (ulint) roll_ptr & 0xFFFF; - roll_ptr >>= 16; - *page_no = (ulint) roll_ptr & 0xFFFFFFFF; - roll_ptr >>= 32; - *rseg_id = (ulint) roll_ptr & 0x7F; - roll_ptr >>= 7; - *is_insert = (ibool) roll_ptr; /* TRUE==1 */ -} - -/***********************************************************************//** -Returns TRUE if the roll pointer is of the insert type. -@return TRUE if insert undo log */ -UNIV_INLINE -ibool -trx_undo_roll_ptr_is_insert( -/*========================*/ - roll_ptr_t roll_ptr) /*!< in: roll pointer */ -{ -#if DATA_ROLL_PTR_LEN != 7 -# error "DATA_ROLL_PTR_LEN != 7" -#endif -#if TRUE != 1 -# error "TRUE != 1" -#endif - ut_ad(roll_ptr < (1ULL << 56)); - return((ibool) (roll_ptr >> 55)); -} - -/***********************************************************************//** -Returns true if the record is of the insert type. -@return true if the record was freshly inserted (not updated). */ -UNIV_INLINE -bool -trx_undo_trx_id_is_insert( -/*======================*/ - const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */ -{ -#if DATA_TRX_ID + 1 != DATA_ROLL_PTR -# error -#endif - return(static_cast(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 */ -{ -#if DATA_ROLL_PTR_LEN != 7 -# error "DATA_ROLL_PTR_LEN != 7" -#endif - 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 */ -{ -#if DATA_ROLL_PTR_LEN != 7 -# error "DATA_ROLL_PTR_LEN != 7" -#endif - 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 -@return pointer to page x-latched */ -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_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); - - return(buf_block_get_frame(block)); -} - -/** Gets an undo log page and s-latches it. -@param[in] page_id page id -@param[in,out] mtr mini-transaction -@return pointer to page s-latched */ -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_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); - - return(buf_block_get_frame(block)); -} - -/******************************************************************//** -Returns the start offset of the undo log records of the specified undo -log on the page. -@return start offset */ -UNIV_INLINE -ulint -trx_undo_page_get_start( -/*====================*/ - page_t* undo_page,/*!< in: undo log page */ - ulint page_no,/*!< in: undo log header page number */ - ulint offset) /*!< in: undo log header offset on page */ -{ - ulint start; - - if (page_no == page_get_page_no(undo_page)) { - - start = mach_read_from_2(offset + undo_page - + TRX_UNDO_LOG_START); - } else { - start = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE; - } - - return(start); -} - -/******************************************************************//** -Returns the end offset of the undo log records of the specified undo -log on the page. -@return end offset */ -UNIV_INLINE -ulint -trx_undo_page_get_end( -/*==================*/ - page_t* undo_page,/*!< in: undo log page */ - ulint page_no,/*!< in: undo log header page number */ - ulint offset) /*!< in: undo log header offset on page */ -{ - trx_ulogf_t* log_hdr; - ulint end; - - if (page_no == page_get_page_no(undo_page)) { - - log_hdr = undo_page + offset; - - end = mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG); - - if (end == 0) { - end = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR - + TRX_UNDO_PAGE_FREE); - } - } else { - end = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR - + TRX_UNDO_PAGE_FREE); - } - - return(end); -} - -/******************************************************************//** -Returns the previous undo record on the page in the specified log, or -NULL if none exists. -@return pointer to record, NULL if none */ -UNIV_INLINE -trx_undo_rec_t* -trx_undo_page_get_prev_rec( -/*=======================*/ - trx_undo_rec_t* rec, /*!< in: undo log record */ - ulint page_no,/*!< in: undo log header page number */ - ulint offset) /*!< in: undo log header offset on page */ -{ - page_t* undo_page; - ulint start; - - undo_page = (page_t*) ut_align_down(rec, UNIV_PAGE_SIZE); - - start = trx_undo_page_get_start(undo_page, page_no, offset); - - if (start + undo_page == rec) { - - return(NULL); - } - - return(undo_page + mach_read_from_2(rec - 2)); -} - -/******************************************************************//** -Returns the next undo log record on the page in the specified log, or -NULL if none exists. -@return pointer to record, NULL if none */ -UNIV_INLINE -trx_undo_rec_t* -trx_undo_page_get_next_rec( -/*=======================*/ - trx_undo_rec_t* rec, /*!< in: undo log record */ - ulint page_no,/*!< in: undo log header page number */ - ulint offset) /*!< in: undo log header offset on page */ -{ - page_t* undo_page; - ulint end; - ulint next; - - undo_page = (page_t*) ut_align_down(rec, UNIV_PAGE_SIZE); - - end = trx_undo_page_get_end(undo_page, page_no, offset); - - next = mach_read_from_2(rec); - - if (next == end) { - - return(NULL); - } - - return(undo_page + next); -} - -/******************************************************************//** -Returns the last undo record on the page in the specified undo log, or -NULL if none exists. -@return pointer to record, NULL if none */ -UNIV_INLINE -trx_undo_rec_t* -trx_undo_page_get_last_rec( -/*=======================*/ - page_t* undo_page,/*!< in: undo log page */ - ulint page_no,/*!< in: undo log header page number */ - ulint offset) /*!< in: undo log header offset on page */ -{ - ulint start; - ulint end; - - start = trx_undo_page_get_start(undo_page, page_no, offset); - end = trx_undo_page_get_end(undo_page, page_no, offset); - - if (start == end) { - - return(NULL); - } - - return(undo_page + mach_read_from_2(undo_page + end - 2)); -} - -/******************************************************************//** -Returns the first undo record on the page in the specified undo log, or -NULL if none exists. -@return pointer to record, NULL if none */ -UNIV_INLINE -trx_undo_rec_t* -trx_undo_page_get_first_rec( -/*========================*/ - page_t* undo_page,/*!< in: undo log page */ - ulint page_no,/*!< in: undo log header page number */ - ulint offset) /*!< in: undo log header offset on page */ -{ - ulint start; - ulint end; - - start = trx_undo_page_get_start(undo_page, page_no, offset); - end = trx_undo_page_get_end(undo_page, page_no, offset); - - if (start == end) { - - return(NULL); - } - - return(undo_page + start); -} diff --git a/storage/innobase/include/trx0undo.inl b/storage/innobase/include/trx0undo.inl new file mode 100644 index 00000000000..2e26e6547c3 --- /dev/null +++ b/storage/innobase/include/trx0undo.inl @@ -0,0 +1,352 @@ +/***************************************************************************** + +Copyright (c) 1996, 2013, 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/trx0undo.ic +Transaction undo log + +Created 3/26/1996 Heikki Tuuri +*******************************************************/ + +#include "data0type.h" +#include "page0page.h" + +/***********************************************************************//** +Builds a roll pointer. +@return roll pointer */ +UNIV_INLINE +roll_ptr_t +trx_undo_build_roll_ptr( +/*====================*/ + ibool is_insert, /*!< in: TRUE if insert undo log */ + ulint rseg_id, /*!< in: rollback segment id */ + ulint page_no, /*!< in: page number */ + ulint offset) /*!< in: offset of the undo entry within page */ +{ + roll_ptr_t roll_ptr; +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif + ut_ad(is_insert == 0 || is_insert == 1); + ut_ad(rseg_id < TRX_SYS_N_RSEGS); + ut_ad(offset < 65536); + + roll_ptr = (roll_ptr_t) is_insert << ROLL_PTR_INSERT_FLAG_POS + | (roll_ptr_t) rseg_id << ROLL_PTR_RSEG_ID_POS + | (roll_ptr_t) page_no << ROLL_PTR_PAGE_POS + | offset; + return(roll_ptr); +} + +/***********************************************************************//** +Decodes a roll pointer. */ +UNIV_INLINE +void +trx_undo_decode_roll_ptr( +/*=====================*/ + roll_ptr_t roll_ptr, /*!< in: roll pointer */ + ibool* is_insert, /*!< out: TRUE if insert undo log */ + ulint* rseg_id, /*!< out: rollback segment id */ + ulint* page_no, /*!< out: page number */ + ulint* offset) /*!< out: offset of the undo + entry within page */ +{ +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif +#if TRUE != 1 +# error "TRUE != 1" +#endif + ut_ad(roll_ptr < (1ULL << 56)); + *offset = (ulint) roll_ptr & 0xFFFF; + roll_ptr >>= 16; + *page_no = (ulint) roll_ptr & 0xFFFFFFFF; + roll_ptr >>= 32; + *rseg_id = (ulint) roll_ptr & 0x7F; + roll_ptr >>= 7; + *is_insert = (ibool) roll_ptr; /* TRUE==1 */ +} + +/***********************************************************************//** +Returns TRUE if the roll pointer is of the insert type. +@return TRUE if insert undo log */ +UNIV_INLINE +ibool +trx_undo_roll_ptr_is_insert( +/*========================*/ + roll_ptr_t roll_ptr) /*!< in: roll pointer */ +{ +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif +#if TRUE != 1 +# error "TRUE != 1" +#endif + ut_ad(roll_ptr < (1ULL << 56)); + return((ibool) (roll_ptr >> 55)); +} + +/***********************************************************************//** +Returns true if the record is of the insert type. +@return true if the record was freshly inserted (not updated). */ +UNIV_INLINE +bool +trx_undo_trx_id_is_insert( +/*======================*/ + const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */ +{ +#if DATA_TRX_ID + 1 != DATA_ROLL_PTR +# error +#endif + return(static_cast(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 */ +{ +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif + 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 */ +{ +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif + 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 +@return pointer to page x-latched */ +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_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); + + return(buf_block_get_frame(block)); +} + +/** Gets an undo log page and s-latches it. +@param[in] page_id page id +@param[in,out] mtr mini-transaction +@return pointer to page s-latched */ +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_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); + + return(buf_block_get_frame(block)); +} + +/******************************************************************//** +Returns the start offset of the undo log records of the specified undo +log on the page. +@return start offset */ +UNIV_INLINE +ulint +trx_undo_page_get_start( +/*====================*/ + page_t* undo_page,/*!< in: undo log page */ + ulint page_no,/*!< in: undo log header page number */ + ulint offset) /*!< in: undo log header offset on page */ +{ + ulint start; + + if (page_no == page_get_page_no(undo_page)) { + + start = mach_read_from_2(offset + undo_page + + TRX_UNDO_LOG_START); + } else { + start = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE; + } + + return(start); +} + +/******************************************************************//** +Returns the end offset of the undo log records of the specified undo +log on the page. +@return end offset */ +UNIV_INLINE +ulint +trx_undo_page_get_end( +/*==================*/ + page_t* undo_page,/*!< in: undo log page */ + ulint page_no,/*!< in: undo log header page number */ + ulint offset) /*!< in: undo log header offset on page */ +{ + trx_ulogf_t* log_hdr; + ulint end; + + if (page_no == page_get_page_no(undo_page)) { + + log_hdr = undo_page + offset; + + end = mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG); + + if (end == 0) { + end = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + + TRX_UNDO_PAGE_FREE); + } + } else { + end = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + + TRX_UNDO_PAGE_FREE); + } + + return(end); +} + +/******************************************************************//** +Returns the previous undo record on the page in the specified log, or +NULL if none exists. +@return pointer to record, NULL if none */ +UNIV_INLINE +trx_undo_rec_t* +trx_undo_page_get_prev_rec( +/*=======================*/ + trx_undo_rec_t* rec, /*!< in: undo log record */ + ulint page_no,/*!< in: undo log header page number */ + ulint offset) /*!< in: undo log header offset on page */ +{ + page_t* undo_page; + ulint start; + + undo_page = (page_t*) ut_align_down(rec, UNIV_PAGE_SIZE); + + start = trx_undo_page_get_start(undo_page, page_no, offset); + + if (start + undo_page == rec) { + + return(NULL); + } + + return(undo_page + mach_read_from_2(rec - 2)); +} + +/******************************************************************//** +Returns the next undo log record on the page in the specified log, or +NULL if none exists. +@return pointer to record, NULL if none */ +UNIV_INLINE +trx_undo_rec_t* +trx_undo_page_get_next_rec( +/*=======================*/ + trx_undo_rec_t* rec, /*!< in: undo log record */ + ulint page_no,/*!< in: undo log header page number */ + ulint offset) /*!< in: undo log header offset on page */ +{ + page_t* undo_page; + ulint end; + ulint next; + + undo_page = (page_t*) ut_align_down(rec, UNIV_PAGE_SIZE); + + end = trx_undo_page_get_end(undo_page, page_no, offset); + + next = mach_read_from_2(rec); + + if (next == end) { + + return(NULL); + } + + return(undo_page + next); +} + +/******************************************************************//** +Returns the last undo record on the page in the specified undo log, or +NULL if none exists. +@return pointer to record, NULL if none */ +UNIV_INLINE +trx_undo_rec_t* +trx_undo_page_get_last_rec( +/*=======================*/ + page_t* undo_page,/*!< in: undo log page */ + ulint page_no,/*!< in: undo log header page number */ + ulint offset) /*!< in: undo log header offset on page */ +{ + ulint start; + ulint end; + + start = trx_undo_page_get_start(undo_page, page_no, offset); + end = trx_undo_page_get_end(undo_page, page_no, offset); + + if (start == end) { + + return(NULL); + } + + return(undo_page + mach_read_from_2(undo_page + end - 2)); +} + +/******************************************************************//** +Returns the first undo record on the page in the specified undo log, or +NULL if none exists. +@return pointer to record, NULL if none */ +UNIV_INLINE +trx_undo_rec_t* +trx_undo_page_get_first_rec( +/*========================*/ + page_t* undo_page,/*!< in: undo log page */ + ulint page_no,/*!< in: undo log header page number */ + ulint offset) /*!< in: undo log header offset on page */ +{ + ulint start; + ulint end; + + start = trx_undo_page_get_start(undo_page, page_no, offset); + end = trx_undo_page_get_end(undo_page, page_no, offset); + + if (start == end) { + + return(NULL); + } + + return(undo_page + start); +} diff --git a/storage/innobase/include/ut0byte.h b/storage/innobase/include/ut0byte.h index 4ce931e0189..1a90b523b2d 100644 --- a/storage/innobase/include/ut0byte.h +++ b/storage/innobase/include/ut0byte.h @@ -112,6 +112,6 @@ ut_bit_set_nth( ulint n, /*!< in: nth bit requested */ ibool val); /*!< in: value for the bit to set */ -#include "ut0byte.ic" +#include "ut0byte.inl" #endif diff --git a/storage/innobase/include/ut0byte.ic b/storage/innobase/include/ut0byte.ic deleted file mode 100644 index 8ca54c06dbc..00000000000 --- a/storage/innobase/include/ut0byte.ic +++ /dev/null @@ -1,173 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2013, 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/ut0byte.ic -Utilities for byte operations - -Created 5/30/1994 Heikki Tuuri -*******************************************************************/ - -/*******************************************************//** -Creates a 64-bit integer out of two 32-bit integers. -@return created integer */ -UNIV_INLINE -ib_uint64_t -ut_ull_create( -/*==========*/ - ulint high, /*!< in: high-order 32 bits */ - ulint low) /*!< in: low-order 32 bits */ -{ - ut_ad(high <= ULINT32_MASK); - ut_ad(low <= ULINT32_MASK); - return(((ib_uint64_t) high) << 32 | low); -} - -/********************************************************//** -Rounds a 64-bit integer downward to a multiple of a power of 2. -@return rounded value */ -UNIV_INLINE -ib_uint64_t -ut_uint64_align_down( -/*=================*/ - ib_uint64_t n, /*!< in: number to be rounded */ - ulint align_no) /*!< in: align by this number - which must be a power of 2 */ -{ - ut_ad(align_no > 0); - ut_ad(ut_is_2pow(align_no)); - - return(n & ~((ib_uint64_t) align_no - 1)); -} - -/********************************************************//** -Rounds ib_uint64_t upward to a multiple of a power of 2. -@return rounded value */ -UNIV_INLINE -ib_uint64_t -ut_uint64_align_up( -/*===============*/ - ib_uint64_t n, /*!< in: number to be rounded */ - ulint align_no) /*!< in: align by this number - which must be a power of 2 */ -{ - ib_uint64_t align_1 = (ib_uint64_t) align_no - 1; - - ut_ad(align_no > 0); - ut_ad(ut_is_2pow(align_no)); - - return((n + align_1) & ~align_1); -} - -/*********************************************************//** -The following function rounds up a pointer to the nearest aligned address. -@return aligned pointer */ -UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) -void* -ut_align( -/*=====*/ - const void* ptr, /*!< in: pointer */ - ulint align_no) /*!< in: align by this number */ -{ - ut_ad(align_no > 0); - ut_ad(((align_no - 1) & align_no) == 0); - ut_ad(ptr); - - ut_ad(sizeof(void*) == sizeof(ulint)); - - return((void*)((((ulint) ptr) + align_no - 1) & ~(align_no - 1))); -} - -/*********************************************************//** -The following function rounds down a pointer to the nearest -aligned address. -@return aligned pointer */ -UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) -void* -ut_align_down( -/*==========*/ - const void* ptr, /*!< in: pointer */ - ulint align_no) /*!< in: align by this number */ -{ - ut_ad(align_no > 0); - ut_ad(((align_no - 1) & align_no) == 0); - ut_ad(ptr); - - ut_ad(sizeof(void*) == sizeof(ulint)); - - return((void*)(((ulint) ptr) & ~(align_no - 1))); -} - -/*********************************************************//** -The following function computes the offset of a pointer from the nearest -aligned address. -@return distance from aligned pointer */ -UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) -ulint -ut_align_offset( -/*============*/ - const void* ptr, /*!< in: pointer */ - ulint align_no) /*!< in: align by this number */ -{ - ut_ad(align_no > 0); - ut_ad(((align_no - 1) & align_no) == 0); - ut_ad(ptr); - - ut_ad(sizeof(void*) == sizeof(ulint)); - - return(((ulint) ptr) & (align_no - 1)); -} - -/*****************************************************************//** -Gets the nth bit of a ulint. -@return TRUE if nth bit is 1; 0th bit is defined to be the least significant */ -UNIV_INLINE -ibool -ut_bit_get_nth( -/*===========*/ - ulint a, /*!< in: ulint */ - ulint n) /*!< in: nth bit requested */ -{ - ut_ad(n < 8 * sizeof(ulint)); -#if TRUE != 1 -# error "TRUE != 1" -#endif - return(1 & (a >> n)); -} - -/*****************************************************************//** -Sets the nth bit of a ulint. -@return the ulint with the bit set as requested */ -UNIV_INLINE -ulint -ut_bit_set_nth( -/*===========*/ - ulint a, /*!< in: ulint */ - ulint n, /*!< in: nth bit requested */ - ibool val) /*!< in: value for the bit to set */ -{ - ut_ad(n < 8 * sizeof(ulint)); -#if TRUE != 1 -# error "TRUE != 1" -#endif - if (val) { - return(((ulint) 1 << n) | a); - } else { - return(~((ulint) 1 << n) & a); - } -} diff --git a/storage/innobase/include/ut0byte.inl b/storage/innobase/include/ut0byte.inl new file mode 100644 index 00000000000..8ca54c06dbc --- /dev/null +++ b/storage/innobase/include/ut0byte.inl @@ -0,0 +1,173 @@ +/***************************************************************************** + +Copyright (c) 1994, 2013, 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/ut0byte.ic +Utilities for byte operations + +Created 5/30/1994 Heikki Tuuri +*******************************************************************/ + +/*******************************************************//** +Creates a 64-bit integer out of two 32-bit integers. +@return created integer */ +UNIV_INLINE +ib_uint64_t +ut_ull_create( +/*==========*/ + ulint high, /*!< in: high-order 32 bits */ + ulint low) /*!< in: low-order 32 bits */ +{ + ut_ad(high <= ULINT32_MASK); + ut_ad(low <= ULINT32_MASK); + return(((ib_uint64_t) high) << 32 | low); +} + +/********************************************************//** +Rounds a 64-bit integer downward to a multiple of a power of 2. +@return rounded value */ +UNIV_INLINE +ib_uint64_t +ut_uint64_align_down( +/*=================*/ + ib_uint64_t n, /*!< in: number to be rounded */ + ulint align_no) /*!< in: align by this number + which must be a power of 2 */ +{ + ut_ad(align_no > 0); + ut_ad(ut_is_2pow(align_no)); + + return(n & ~((ib_uint64_t) align_no - 1)); +} + +/********************************************************//** +Rounds ib_uint64_t upward to a multiple of a power of 2. +@return rounded value */ +UNIV_INLINE +ib_uint64_t +ut_uint64_align_up( +/*===============*/ + ib_uint64_t n, /*!< in: number to be rounded */ + ulint align_no) /*!< in: align by this number + which must be a power of 2 */ +{ + ib_uint64_t align_1 = (ib_uint64_t) align_no - 1; + + ut_ad(align_no > 0); + ut_ad(ut_is_2pow(align_no)); + + return((n + align_1) & ~align_1); +} + +/*********************************************************//** +The following function rounds up a pointer to the nearest aligned address. +@return aligned pointer */ +UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) +void* +ut_align( +/*=====*/ + const void* ptr, /*!< in: pointer */ + ulint align_no) /*!< in: align by this number */ +{ + ut_ad(align_no > 0); + ut_ad(((align_no - 1) & align_no) == 0); + ut_ad(ptr); + + ut_ad(sizeof(void*) == sizeof(ulint)); + + return((void*)((((ulint) ptr) + align_no - 1) & ~(align_no - 1))); +} + +/*********************************************************//** +The following function rounds down a pointer to the nearest +aligned address. +@return aligned pointer */ +UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) +void* +ut_align_down( +/*==========*/ + const void* ptr, /*!< in: pointer */ + ulint align_no) /*!< in: align by this number */ +{ + ut_ad(align_no > 0); + ut_ad(((align_no - 1) & align_no) == 0); + ut_ad(ptr); + + ut_ad(sizeof(void*) == sizeof(ulint)); + + return((void*)(((ulint) ptr) & ~(align_no - 1))); +} + +/*********************************************************//** +The following function computes the offset of a pointer from the nearest +aligned address. +@return distance from aligned pointer */ +UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) +ulint +ut_align_offset( +/*============*/ + const void* ptr, /*!< in: pointer */ + ulint align_no) /*!< in: align by this number */ +{ + ut_ad(align_no > 0); + ut_ad(((align_no - 1) & align_no) == 0); + ut_ad(ptr); + + ut_ad(sizeof(void*) == sizeof(ulint)); + + return(((ulint) ptr) & (align_no - 1)); +} + +/*****************************************************************//** +Gets the nth bit of a ulint. +@return TRUE if nth bit is 1; 0th bit is defined to be the least significant */ +UNIV_INLINE +ibool +ut_bit_get_nth( +/*===========*/ + ulint a, /*!< in: ulint */ + ulint n) /*!< in: nth bit requested */ +{ + ut_ad(n < 8 * sizeof(ulint)); +#if TRUE != 1 +# error "TRUE != 1" +#endif + return(1 & (a >> n)); +} + +/*****************************************************************//** +Sets the nth bit of a ulint. +@return the ulint with the bit set as requested */ +UNIV_INLINE +ulint +ut_bit_set_nth( +/*===========*/ + ulint a, /*!< in: ulint */ + ulint n, /*!< in: nth bit requested */ + ibool val) /*!< in: value for the bit to set */ +{ + ut_ad(n < 8 * sizeof(ulint)); +#if TRUE != 1 +# error "TRUE != 1" +#endif + if (val) { + return(((ulint) 1 << n) | a); + } else { + return(~((ulint) 1 << n) & a); + } +} diff --git a/storage/innobase/include/ut0list.h b/storage/innobase/include/ut0list.h index 7e27e10884b..765f6a2a339 100644 --- a/storage/innobase/include/ut0list.h +++ b/storage/innobase/include/ut0list.h @@ -141,6 +141,6 @@ struct ib_list_helper_t { void* data; /*!< user data */ }; -#include "ut0list.ic" +#include "ut0list.inl" #endif diff --git a/storage/innobase/include/ut0list.ic b/storage/innobase/include/ut0list.ic deleted file mode 100644 index 3bdba52bfaa..00000000000 --- a/storage/innobase/include/ut0list.ic +++ /dev/null @@ -1,80 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2006, 2013, 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/ut0list.ic -A double-linked list - -Created 4/26/2006 Osku Salerma -************************************************************************/ - -/****************************************************************//** -Get the first node in the list. -@return first node, or NULL */ -UNIV_INLINE -ib_list_node_t* -ib_list_get_first( -/*==============*/ - ib_list_t* list) /*!< in: list */ -{ - return(list->first); -} - -/****************************************************************//** -Get the last node in the list. -@return last node, or NULL */ -UNIV_INLINE -ib_list_node_t* -ib_list_get_last( -/*=============*/ - ib_list_t* list) /*!< in: list */ -{ - return(list->last); -} - -/******************************************************************** -Check if list is empty. */ -UNIV_INLINE -ibool -ib_list_is_empty( -/*=============*/ - /* out: TRUE if empty else FALSE */ - const ib_list_t* list) /* in: list */ -{ - return(!(list->first || list->last)); -} - -/******************************************************************** -Get number of items on list. -@return number of items on list */ -UNIV_INLINE -ulint -ib_list_len( -/*========*/ - const ib_list_t* list) /*first; - - while(node) { - len++; - node = node->next; - } - - return (len); -} diff --git a/storage/innobase/include/ut0list.inl b/storage/innobase/include/ut0list.inl new file mode 100644 index 00000000000..3bdba52bfaa --- /dev/null +++ b/storage/innobase/include/ut0list.inl @@ -0,0 +1,80 @@ +/***************************************************************************** + +Copyright (c) 2006, 2013, 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/ut0list.ic +A double-linked list + +Created 4/26/2006 Osku Salerma +************************************************************************/ + +/****************************************************************//** +Get the first node in the list. +@return first node, or NULL */ +UNIV_INLINE +ib_list_node_t* +ib_list_get_first( +/*==============*/ + ib_list_t* list) /*!< in: list */ +{ + return(list->first); +} + +/****************************************************************//** +Get the last node in the list. +@return last node, or NULL */ +UNIV_INLINE +ib_list_node_t* +ib_list_get_last( +/*=============*/ + ib_list_t* list) /*!< in: list */ +{ + return(list->last); +} + +/******************************************************************** +Check if list is empty. */ +UNIV_INLINE +ibool +ib_list_is_empty( +/*=============*/ + /* out: TRUE if empty else FALSE */ + const ib_list_t* list) /* in: list */ +{ + return(!(list->first || list->last)); +} + +/******************************************************************** +Get number of items on list. +@return number of items on list */ +UNIV_INLINE +ulint +ib_list_len( +/*========*/ + const ib_list_t* list) /*first; + + while(node) { + len++; + node = node->next; + } + + return (len); +} diff --git a/storage/innobase/include/ut0mem.h b/storage/innobase/include/ut0mem.h index 32d557d4f2a..99811c400da 100644 --- a/storage/innobase/include/ut0mem.h +++ b/storage/innobase/include/ut0mem.h @@ -126,6 +126,6 @@ ut_str_sql_format( ulint buf_size); /*!< in: output buffer size in bytes */ -#include "ut0mem.ic" +#include "ut0mem.inl" #endif diff --git a/storage/innobase/include/ut0mem.ic b/storage/innobase/include/ut0mem.ic deleted file mode 100644 index 8c8788a38aa..00000000000 --- a/storage/innobase/include/ut0mem.ic +++ /dev/null @@ -1,318 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2014, 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/ut0mem.ic -Memory primitives - -Created 5/30/1994 Heikki Tuuri -************************************************************************/ - -#include "ut0byte.h" -#include "mach0data.h" - -/** Wrapper for memcpy(3). Copy memory area when the source and -target are not overlapping. -@param[in,out] dest copy to -@param[in] src copy from -@param[in] n number of bytes to copy -@return dest */ -UNIV_INLINE -void* -ut_memcpy(void* dest, const void* src, ulint n) -{ - return(memcpy(dest, src, n)); -} - -/** Wrapper for memmove(3). Copy memory area when the source and -target are overlapping. -@param[in,out] dest Move to -@param[in] src Move from -@param[in] n number of bytes to move -@return dest */ -UNIV_INLINE -void* -ut_memmove(void* dest, const void* src, ulint n) -{ - return(memmove(dest, src, n)); -} - -/** Wrapper for memcmp(3). Compare memory areas. -@param[in] str1 first memory block to compare -@param[in] str2 second memory block to compare -@param[in] n number of bytes to compare -@return negative, 0, or positive if str1 is smaller, equal, - or greater than str2, respectively. */ -UNIV_INLINE -int -ut_memcmp(const void* str1, const void* str2, ulint n) -{ - return(memcmp(str1, str2, n)); -} - -/** Wrapper for strcpy(3). Copy a NUL-terminated string. -@param[in,out] dest Destination to copy to -@param[in] src Source to copy from -@return dest */ -UNIV_INLINE -char* -ut_strcpy(char* dest, const char* src) -{ - return(strcpy(dest, src)); -} - -/** Wrapper for strlen(3). Determine the length of a NUL-terminated string. -@param[in] str string -@return length of the string in bytes, excluding the terminating NUL */ -UNIV_INLINE -ulint -ut_strlen(const char* str) -{ - return(strlen(str)); -} - -/** Wrapper for strcmp(3). Compare NUL-terminated strings. -@param[in] str1 first string to compare -@param[in] str2 second string to compare -@return negative, 0, or positive if str1 is smaller, equal, - or greater than str2, respectively. */ -UNIV_INLINE -int -ut_strcmp(const char* str1, const char* str2) -{ - return(strcmp(str1, str2)); -} - -/**********************************************************************//** -Converts a raw binary data to a NUL-terminated hex string. The output is -truncated if there is not enough space in "hex", make sure "hex_size" is at -least (2 * raw_size + 1) if you do not want this to happen. Returns the -actual number of characters written to "hex" (including the NUL). -@return number of chars written */ -UNIV_INLINE -ulint -ut_raw_to_hex( -/*==========*/ - const void* raw, /*!< in: raw data */ - ulint raw_size, /*!< in: "raw" length in bytes */ - char* hex, /*!< out: hex string */ - ulint hex_size) /*!< in: "hex" size in bytes */ -{ - -#ifdef WORDS_BIGENDIAN - -#define MK_UINT16(a, b) (((uint16) (a)) << 8 | (uint16) (b)) - -#define UINT16_GET_A(u) ((char) ((u) >> 8)) -#define UINT16_GET_B(u) ((char) ((u) & 0xFF)) - -#else /* WORDS_BIGENDIAN */ - -#define MK_UINT16(a, b) (((uint16) (b)) << 8 | (uint16) (a)) - -#define UINT16_GET_A(u) ((char) ((u) & 0xFF)) -#define UINT16_GET_B(u) ((char) ((u) >> 8)) - -#endif /* WORDS_BIGENDIAN */ - -#define MK_ALL_UINT16_WITH_A(a) \ - MK_UINT16(a, '0'), \ - MK_UINT16(a, '1'), \ - MK_UINT16(a, '2'), \ - MK_UINT16(a, '3'), \ - MK_UINT16(a, '4'), \ - MK_UINT16(a, '5'), \ - MK_UINT16(a, '6'), \ - MK_UINT16(a, '7'), \ - MK_UINT16(a, '8'), \ - MK_UINT16(a, '9'), \ - MK_UINT16(a, 'A'), \ - MK_UINT16(a, 'B'), \ - MK_UINT16(a, 'C'), \ - MK_UINT16(a, 'D'), \ - MK_UINT16(a, 'E'), \ - MK_UINT16(a, 'F') - - static const uint16 hex_map[256] = { - MK_ALL_UINT16_WITH_A('0'), - MK_ALL_UINT16_WITH_A('1'), - MK_ALL_UINT16_WITH_A('2'), - MK_ALL_UINT16_WITH_A('3'), - MK_ALL_UINT16_WITH_A('4'), - MK_ALL_UINT16_WITH_A('5'), - MK_ALL_UINT16_WITH_A('6'), - MK_ALL_UINT16_WITH_A('7'), - MK_ALL_UINT16_WITH_A('8'), - MK_ALL_UINT16_WITH_A('9'), - MK_ALL_UINT16_WITH_A('A'), - MK_ALL_UINT16_WITH_A('B'), - MK_ALL_UINT16_WITH_A('C'), - MK_ALL_UINT16_WITH_A('D'), - MK_ALL_UINT16_WITH_A('E'), - MK_ALL_UINT16_WITH_A('F') - }; - const unsigned char* rawc; - ulint read_bytes; - ulint write_bytes; - ulint i; - - rawc = (const unsigned char*) raw; - - if (hex_size == 0) { - - return(0); - } - - if (hex_size <= 2 * raw_size) { - - read_bytes = hex_size / 2; - write_bytes = hex_size; - } else { - - read_bytes = raw_size; - write_bytes = 2 * raw_size + 1; - } - -#define LOOP_READ_BYTES(ASSIGN) \ - for (i = 0; i < read_bytes; i++) { \ - ASSIGN; \ - hex += 2; \ - rawc++; \ - } - - if (ut_align_offset(hex, 2) == 0) { - - LOOP_READ_BYTES( - *(uint16*) hex = hex_map[*rawc] - ); - } else { - - LOOP_READ_BYTES( - *hex = UINT16_GET_A(hex_map[*rawc]); - *(hex + 1) = UINT16_GET_B(hex_map[*rawc]) - ); - } - - if (hex_size <= 2 * raw_size && hex_size % 2 == 0) { - - hex--; - } - - *hex = '\0'; - - return(write_bytes); -} - -/*******************************************************************//** -Adds single quotes to the start and end of string and escapes any quotes -by doubling them. Returns the number of bytes that were written to "buf" -(including the terminating NUL). If buf_size is too small then the -trailing bytes from "str" are discarded. -@return number of bytes that were written */ -UNIV_INLINE -ulint -ut_str_sql_format( -/*==============*/ - const char* str, /*!< in: string */ - ulint str_len, /*!< in: string length in bytes */ - char* buf, /*!< out: output buffer */ - ulint buf_size) /*!< in: output buffer size - in bytes */ -{ - ulint str_i; - ulint buf_i; - - buf_i = 0; - - switch (buf_size) { - case 3: - - if (str_len == 0) { - - buf[buf_i] = '\''; - buf_i++; - buf[buf_i] = '\''; - buf_i++; - } - /* FALLTHROUGH */ - case 2: - case 1: - - buf[buf_i] = '\0'; - buf_i++; - /* FALLTHROUGH */ - case 0: - - return(buf_i); - } - - /* buf_size >= 4 */ - - buf[0] = '\''; - buf_i = 1; - - for (str_i = 0; str_i < str_len; str_i++) { - - char ch; - - if (buf_size - buf_i == 2) { - - break; - } - - ch = str[str_i]; - - switch (ch) { - case '\0': - - if (buf_size - buf_i < 4) { - - goto func_exit; - } - buf[buf_i] = '\\'; - buf_i++; - buf[buf_i] = '0'; - buf_i++; - break; - case '\'': - case '\\': - - if (buf_size - buf_i < 4) { - - goto func_exit; - } - buf[buf_i] = ch; - buf_i++; - /* FALLTHROUGH */ - default: - - buf[buf_i] = ch; - buf_i++; - } - } - -func_exit: - - buf[buf_i] = '\''; - buf_i++; - buf[buf_i] = '\0'; - buf_i++; - - return(buf_i); -} diff --git a/storage/innobase/include/ut0mem.inl b/storage/innobase/include/ut0mem.inl new file mode 100644 index 00000000000..8c8788a38aa --- /dev/null +++ b/storage/innobase/include/ut0mem.inl @@ -0,0 +1,318 @@ +/***************************************************************************** + +Copyright (c) 1994, 2014, 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/ut0mem.ic +Memory primitives + +Created 5/30/1994 Heikki Tuuri +************************************************************************/ + +#include "ut0byte.h" +#include "mach0data.h" + +/** Wrapper for memcpy(3). Copy memory area when the source and +target are not overlapping. +@param[in,out] dest copy to +@param[in] src copy from +@param[in] n number of bytes to copy +@return dest */ +UNIV_INLINE +void* +ut_memcpy(void* dest, const void* src, ulint n) +{ + return(memcpy(dest, src, n)); +} + +/** Wrapper for memmove(3). Copy memory area when the source and +target are overlapping. +@param[in,out] dest Move to +@param[in] src Move from +@param[in] n number of bytes to move +@return dest */ +UNIV_INLINE +void* +ut_memmove(void* dest, const void* src, ulint n) +{ + return(memmove(dest, src, n)); +} + +/** Wrapper for memcmp(3). Compare memory areas. +@param[in] str1 first memory block to compare +@param[in] str2 second memory block to compare +@param[in] n number of bytes to compare +@return negative, 0, or positive if str1 is smaller, equal, + or greater than str2, respectively. */ +UNIV_INLINE +int +ut_memcmp(const void* str1, const void* str2, ulint n) +{ + return(memcmp(str1, str2, n)); +} + +/** Wrapper for strcpy(3). Copy a NUL-terminated string. +@param[in,out] dest Destination to copy to +@param[in] src Source to copy from +@return dest */ +UNIV_INLINE +char* +ut_strcpy(char* dest, const char* src) +{ + return(strcpy(dest, src)); +} + +/** Wrapper for strlen(3). Determine the length of a NUL-terminated string. +@param[in] str string +@return length of the string in bytes, excluding the terminating NUL */ +UNIV_INLINE +ulint +ut_strlen(const char* str) +{ + return(strlen(str)); +} + +/** Wrapper for strcmp(3). Compare NUL-terminated strings. +@param[in] str1 first string to compare +@param[in] str2 second string to compare +@return negative, 0, or positive if str1 is smaller, equal, + or greater than str2, respectively. */ +UNIV_INLINE +int +ut_strcmp(const char* str1, const char* str2) +{ + return(strcmp(str1, str2)); +} + +/**********************************************************************//** +Converts a raw binary data to a NUL-terminated hex string. The output is +truncated if there is not enough space in "hex", make sure "hex_size" is at +least (2 * raw_size + 1) if you do not want this to happen. Returns the +actual number of characters written to "hex" (including the NUL). +@return number of chars written */ +UNIV_INLINE +ulint +ut_raw_to_hex( +/*==========*/ + const void* raw, /*!< in: raw data */ + ulint raw_size, /*!< in: "raw" length in bytes */ + char* hex, /*!< out: hex string */ + ulint hex_size) /*!< in: "hex" size in bytes */ +{ + +#ifdef WORDS_BIGENDIAN + +#define MK_UINT16(a, b) (((uint16) (a)) << 8 | (uint16) (b)) + +#define UINT16_GET_A(u) ((char) ((u) >> 8)) +#define UINT16_GET_B(u) ((char) ((u) & 0xFF)) + +#else /* WORDS_BIGENDIAN */ + +#define MK_UINT16(a, b) (((uint16) (b)) << 8 | (uint16) (a)) + +#define UINT16_GET_A(u) ((char) ((u) & 0xFF)) +#define UINT16_GET_B(u) ((char) ((u) >> 8)) + +#endif /* WORDS_BIGENDIAN */ + +#define MK_ALL_UINT16_WITH_A(a) \ + MK_UINT16(a, '0'), \ + MK_UINT16(a, '1'), \ + MK_UINT16(a, '2'), \ + MK_UINT16(a, '3'), \ + MK_UINT16(a, '4'), \ + MK_UINT16(a, '5'), \ + MK_UINT16(a, '6'), \ + MK_UINT16(a, '7'), \ + MK_UINT16(a, '8'), \ + MK_UINT16(a, '9'), \ + MK_UINT16(a, 'A'), \ + MK_UINT16(a, 'B'), \ + MK_UINT16(a, 'C'), \ + MK_UINT16(a, 'D'), \ + MK_UINT16(a, 'E'), \ + MK_UINT16(a, 'F') + + static const uint16 hex_map[256] = { + MK_ALL_UINT16_WITH_A('0'), + MK_ALL_UINT16_WITH_A('1'), + MK_ALL_UINT16_WITH_A('2'), + MK_ALL_UINT16_WITH_A('3'), + MK_ALL_UINT16_WITH_A('4'), + MK_ALL_UINT16_WITH_A('5'), + MK_ALL_UINT16_WITH_A('6'), + MK_ALL_UINT16_WITH_A('7'), + MK_ALL_UINT16_WITH_A('8'), + MK_ALL_UINT16_WITH_A('9'), + MK_ALL_UINT16_WITH_A('A'), + MK_ALL_UINT16_WITH_A('B'), + MK_ALL_UINT16_WITH_A('C'), + MK_ALL_UINT16_WITH_A('D'), + MK_ALL_UINT16_WITH_A('E'), + MK_ALL_UINT16_WITH_A('F') + }; + const unsigned char* rawc; + ulint read_bytes; + ulint write_bytes; + ulint i; + + rawc = (const unsigned char*) raw; + + if (hex_size == 0) { + + return(0); + } + + if (hex_size <= 2 * raw_size) { + + read_bytes = hex_size / 2; + write_bytes = hex_size; + } else { + + read_bytes = raw_size; + write_bytes = 2 * raw_size + 1; + } + +#define LOOP_READ_BYTES(ASSIGN) \ + for (i = 0; i < read_bytes; i++) { \ + ASSIGN; \ + hex += 2; \ + rawc++; \ + } + + if (ut_align_offset(hex, 2) == 0) { + + LOOP_READ_BYTES( + *(uint16*) hex = hex_map[*rawc] + ); + } else { + + LOOP_READ_BYTES( + *hex = UINT16_GET_A(hex_map[*rawc]); + *(hex + 1) = UINT16_GET_B(hex_map[*rawc]) + ); + } + + if (hex_size <= 2 * raw_size && hex_size % 2 == 0) { + + hex--; + } + + *hex = '\0'; + + return(write_bytes); +} + +/*******************************************************************//** +Adds single quotes to the start and end of string and escapes any quotes +by doubling them. Returns the number of bytes that were written to "buf" +(including the terminating NUL). If buf_size is too small then the +trailing bytes from "str" are discarded. +@return number of bytes that were written */ +UNIV_INLINE +ulint +ut_str_sql_format( +/*==============*/ + const char* str, /*!< in: string */ + ulint str_len, /*!< in: string length in bytes */ + char* buf, /*!< out: output buffer */ + ulint buf_size) /*!< in: output buffer size + in bytes */ +{ + ulint str_i; + ulint buf_i; + + buf_i = 0; + + switch (buf_size) { + case 3: + + if (str_len == 0) { + + buf[buf_i] = '\''; + buf_i++; + buf[buf_i] = '\''; + buf_i++; + } + /* FALLTHROUGH */ + case 2: + case 1: + + buf[buf_i] = '\0'; + buf_i++; + /* FALLTHROUGH */ + case 0: + + return(buf_i); + } + + /* buf_size >= 4 */ + + buf[0] = '\''; + buf_i = 1; + + for (str_i = 0; str_i < str_len; str_i++) { + + char ch; + + if (buf_size - buf_i == 2) { + + break; + } + + ch = str[str_i]; + + switch (ch) { + case '\0': + + if (buf_size - buf_i < 4) { + + goto func_exit; + } + buf[buf_i] = '\\'; + buf_i++; + buf[buf_i] = '0'; + buf_i++; + break; + case '\'': + case '\\': + + if (buf_size - buf_i < 4) { + + goto func_exit; + } + buf[buf_i] = ch; + buf_i++; + /* FALLTHROUGH */ + default: + + buf[buf_i] = ch; + buf_i++; + } + } + +func_exit: + + buf[buf_i] = '\''; + buf_i++; + buf[buf_i] = '\0'; + buf_i++; + + return(buf_i); +} diff --git a/storage/innobase/include/ut0rnd.h b/storage/innobase/include/ut0rnd.h index 9af8687bfd0..d2b43a12550 100644 --- a/storage/innobase/include/ut0rnd.h +++ b/storage/innobase/include/ut0rnd.h @@ -133,6 +133,6 @@ ut_fold_binary( ulint len) /*!< in: length */ MY_ATTRIBUTE((pure)); -#include "ut0rnd.ic" +#include "ut0rnd.inl" #endif diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic deleted file mode 100644 index c0105160a42..00000000000 --- a/storage/innobase/include/ut0rnd.ic +++ /dev/null @@ -1,150 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2016, 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 include/ut0rnd.ic -Random numbers and hashing - -Created 5/30/1994 Heikki Tuuri -*******************************************************************/ - -#define UT_HASH_RANDOM_MASK 1463735687 -#define UT_HASH_RANDOM_MASK2 1653893711 - -#ifndef UNIV_INNOCHECKSUM - -/*******************************************************//** -The following function generates a hash value for a ulint integer -to a hash table of size table_size, which should be a prime -or some random number for the hash table to work reliably. -@return hash value */ -UNIV_INLINE -ulint -ut_hash_ulint( -/*==========*/ - ulint key, /*!< in: value to be hashed */ - ulint table_size) /*!< in: hash table size */ -{ - ut_ad(table_size); - key = key ^ UT_HASH_RANDOM_MASK2; - - return(key % table_size); -} - -/*************************************************************//** -Folds a 64-bit integer. -@return folded value */ -UNIV_INLINE -ulint -ut_fold_ull( -/*========*/ - ib_uint64_t d) /*!< in: 64-bit integer */ -{ - return(ut_fold_ulint_pair((ulint) d & ULINT32_MASK, - (ulint) (d >> 32))); -} - -/*************************************************************//** -Folds a character string ending in the null character. -@return folded value */ -UNIV_INLINE -ulint -ut_fold_string( -/*===========*/ - const char* str) /*!< in: null-terminated string */ -{ - ulint fold = 0; - - ut_ad(str); - - while (*str != '\0') { - fold = ut_fold_ulint_pair(fold, (ulint)(*str)); - str++; - } - - return(fold); -} - -#endif /* !UNIV_INNOCHECKSUM */ - -/*************************************************************//** -Folds a pair of ulints. -@return folded value */ -UNIV_INLINE -ulint -ut_fold_ulint_pair( -/*===============*/ - ulint n1, /*!< in: ulint */ - ulint n2) /*!< in: ulint */ -{ - return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1) - ^ UT_HASH_RANDOM_MASK) + n2); -} - -/*************************************************************//** -Folds a binary string. -@return folded value */ -UNIV_INLINE -ulint -ut_fold_binary( -/*===========*/ - const byte* str, /*!< in: string of bytes */ - ulint len) /*!< in: length */ -{ - ulint fold = 0; - const byte* str_end = str + (len & 0xFFFFFFF8); - - ut_ad(str || !len); - - while (str < str_end) { - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - } - - switch (len & 0x7) { - case 7: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - /* fall through */ - case 6: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - /* fall through */ - case 5: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - /* fall through */ - case 4: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - /* fall through */ - case 3: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - /* fall through */ - case 2: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - /* fall through */ - case 1: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); - } - - return(fold); -} diff --git a/storage/innobase/include/ut0rnd.inl b/storage/innobase/include/ut0rnd.inl new file mode 100644 index 00000000000..c0105160a42 --- /dev/null +++ b/storage/innobase/include/ut0rnd.inl @@ -0,0 +1,150 @@ +/***************************************************************************** + +Copyright (c) 1994, 2016, 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 include/ut0rnd.ic +Random numbers and hashing + +Created 5/30/1994 Heikki Tuuri +*******************************************************************/ + +#define UT_HASH_RANDOM_MASK 1463735687 +#define UT_HASH_RANDOM_MASK2 1653893711 + +#ifndef UNIV_INNOCHECKSUM + +/*******************************************************//** +The following function generates a hash value for a ulint integer +to a hash table of size table_size, which should be a prime +or some random number for the hash table to work reliably. +@return hash value */ +UNIV_INLINE +ulint +ut_hash_ulint( +/*==========*/ + ulint key, /*!< in: value to be hashed */ + ulint table_size) /*!< in: hash table size */ +{ + ut_ad(table_size); + key = key ^ UT_HASH_RANDOM_MASK2; + + return(key % table_size); +} + +/*************************************************************//** +Folds a 64-bit integer. +@return folded value */ +UNIV_INLINE +ulint +ut_fold_ull( +/*========*/ + ib_uint64_t d) /*!< in: 64-bit integer */ +{ + return(ut_fold_ulint_pair((ulint) d & ULINT32_MASK, + (ulint) (d >> 32))); +} + +/*************************************************************//** +Folds a character string ending in the null character. +@return folded value */ +UNIV_INLINE +ulint +ut_fold_string( +/*===========*/ + const char* str) /*!< in: null-terminated string */ +{ + ulint fold = 0; + + ut_ad(str); + + while (*str != '\0') { + fold = ut_fold_ulint_pair(fold, (ulint)(*str)); + str++; + } + + return(fold); +} + +#endif /* !UNIV_INNOCHECKSUM */ + +/*************************************************************//** +Folds a pair of ulints. +@return folded value */ +UNIV_INLINE +ulint +ut_fold_ulint_pair( +/*===============*/ + ulint n1, /*!< in: ulint */ + ulint n2) /*!< in: ulint */ +{ + return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1) + ^ UT_HASH_RANDOM_MASK) + n2); +} + +/*************************************************************//** +Folds a binary string. +@return folded value */ +UNIV_INLINE +ulint +ut_fold_binary( +/*===========*/ + const byte* str, /*!< in: string of bytes */ + ulint len) /*!< in: length */ +{ + ulint fold = 0; + const byte* str_end = str + (len & 0xFFFFFFF8); + + ut_ad(str || !len); + + while (str < str_end) { + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + } + + switch (len & 0x7) { + case 7: + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ + case 6: + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ + case 5: + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ + case 4: + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ + case 3: + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ + case 2: + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ + case 1: + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + } + + return(fold); +} diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index a19f3db188d..70096942e1d 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -508,7 +508,7 @@ private: } // namespace ib -#include "ut0ut.ic" +#include "ut0ut.inl" #endif diff --git a/storage/innobase/include/ut0ut.ic b/storage/innobase/include/ut0ut.ic deleted file mode 100644 index 73feaf82c6a..00000000000 --- a/storage/innobase/include/ut0ut.ic +++ /dev/null @@ -1,143 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 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/ut0ut.ic -Various utilities - -Created 5/30/1994 Heikki Tuuri -*******************************************************************/ - -#include - -/** Calculate the minimum of two pairs. -@param[out] min_hi MSB of the minimum pair -@param[out] min_lo LSB of the minimum pair -@param[in] a_hi MSB of the first pair -@param[in] a_lo LSB of the first pair -@param[in] b_hi MSB of the second pair -@param[in] b_lo LSB of the second pair */ -UNIV_INLINE -void -ut_pair_min( - ulint* min_hi, - ulint* min_lo, - ulint a_hi, - ulint a_lo, - ulint b_hi, - ulint b_lo) -{ - if (a_hi == b_hi) { - *min_hi = a_hi; - *min_lo = std::min(a_lo, b_lo); - } else if (a_hi < b_hi) { - *min_hi = a_hi; - *min_lo = a_lo; - } else { - *min_hi = b_hi; - *min_lo = b_lo; - } -} - -/******************************************************//** -Compares two ulints. -@return 1 if a > b, 0 if a == b, -1 if a < b */ -UNIV_INLINE -int -ut_ulint_cmp( -/*=========*/ - ulint a, /*!< in: ulint */ - ulint b) /*!< in: ulint */ -{ - if (a < b) { - return(-1); - } else if (a == b) { - return(0); - } else { - return(1); - } -} - -/** Compare two pairs of integers. -@param[in] a_h more significant part of first pair -@param[in] a_l less significant part of first pair -@param[in] b_h more significant part of second pair -@param[in] b_l less significant part of second pair -@return comparison result of (a_h,a_l) and (b_h,b_l) -@retval -1 if (a_h,a_l) is less than (b_h,b_l) -@retval 0 if (a_h,a_l) is equal to (b_h,b_l) -@retval 1 if (a_h,a_l) is greater than (b_h,b_l) */ -UNIV_INLINE -int -ut_pair_cmp( - ulint a_h, - ulint a_l, - ulint b_h, - ulint b_l) -{ - if (a_h < b_h) { - return(-1); - } - if (a_h > b_h) { - return(1); - } - return(ut_ulint_cmp(a_l, b_l)); -} - -/*************************************************************//** -Calculates fast the 2-logarithm of a number, rounded upward to an -integer. -@return logarithm in the base 2, rounded upward */ -UNIV_INLINE -ulint -ut_2_log( -/*=====*/ - ulint n) /*!< in: number != 0 */ -{ - ulint res; - - res = 0; - - ut_ad(n > 0); - - n = n - 1; - - for (;;) { - n = n / 2; - - if (n == 0) { - break; - } - - res++; - } - - return(res + 1); -} - -/*************************************************************//** -Calculates 2 to power n. -@return 2 to power n */ -UNIV_INLINE -ulint -ut_2_exp( -/*=====*/ - ulint n) /*!< in: number */ -{ - return((ulint) 1 << n); -} diff --git a/storage/innobase/include/ut0ut.inl b/storage/innobase/include/ut0ut.inl new file mode 100644 index 00000000000..73feaf82c6a --- /dev/null +++ b/storage/innobase/include/ut0ut.inl @@ -0,0 +1,143 @@ +/***************************************************************************** + +Copyright (c) 1994, 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/ut0ut.ic +Various utilities + +Created 5/30/1994 Heikki Tuuri +*******************************************************************/ + +#include + +/** Calculate the minimum of two pairs. +@param[out] min_hi MSB of the minimum pair +@param[out] min_lo LSB of the minimum pair +@param[in] a_hi MSB of the first pair +@param[in] a_lo LSB of the first pair +@param[in] b_hi MSB of the second pair +@param[in] b_lo LSB of the second pair */ +UNIV_INLINE +void +ut_pair_min( + ulint* min_hi, + ulint* min_lo, + ulint a_hi, + ulint a_lo, + ulint b_hi, + ulint b_lo) +{ + if (a_hi == b_hi) { + *min_hi = a_hi; + *min_lo = std::min(a_lo, b_lo); + } else if (a_hi < b_hi) { + *min_hi = a_hi; + *min_lo = a_lo; + } else { + *min_hi = b_hi; + *min_lo = b_lo; + } +} + +/******************************************************//** +Compares two ulints. +@return 1 if a > b, 0 if a == b, -1 if a < b */ +UNIV_INLINE +int +ut_ulint_cmp( +/*=========*/ + ulint a, /*!< in: ulint */ + ulint b) /*!< in: ulint */ +{ + if (a < b) { + return(-1); + } else if (a == b) { + return(0); + } else { + return(1); + } +} + +/** Compare two pairs of integers. +@param[in] a_h more significant part of first pair +@param[in] a_l less significant part of first pair +@param[in] b_h more significant part of second pair +@param[in] b_l less significant part of second pair +@return comparison result of (a_h,a_l) and (b_h,b_l) +@retval -1 if (a_h,a_l) is less than (b_h,b_l) +@retval 0 if (a_h,a_l) is equal to (b_h,b_l) +@retval 1 if (a_h,a_l) is greater than (b_h,b_l) */ +UNIV_INLINE +int +ut_pair_cmp( + ulint a_h, + ulint a_l, + ulint b_h, + ulint b_l) +{ + if (a_h < b_h) { + return(-1); + } + if (a_h > b_h) { + return(1); + } + return(ut_ulint_cmp(a_l, b_l)); +} + +/*************************************************************//** +Calculates fast the 2-logarithm of a number, rounded upward to an +integer. +@return logarithm in the base 2, rounded upward */ +UNIV_INLINE +ulint +ut_2_log( +/*=====*/ + ulint n) /*!< in: number != 0 */ +{ + ulint res; + + res = 0; + + ut_ad(n > 0); + + n = n - 1; + + for (;;) { + n = n / 2; + + if (n == 0) { + break; + } + + res++; + } + + return(res + 1); +} + +/*************************************************************//** +Calculates 2 to power n. +@return 2 to power n */ +UNIV_INLINE +ulint +ut_2_exp( +/*=====*/ + ulint n) /*!< in: number */ +{ + return((ulint) 1 << n); +} diff --git a/storage/innobase/include/ut0vec.h b/storage/innobase/include/ut0vec.h index cfdaee607be..f4660f9646c 100644 --- a/storage/innobase/include/ut0vec.h +++ b/storage/innobase/include/ut0vec.h @@ -280,6 +280,6 @@ struct ib_vector_t { ulint sizeof_value; }; -#include "ut0vec.ic" +#include "ut0vec.inl" #endif /* IB_VECTOR_H */ diff --git a/storage/innobase/include/ut0vec.ic b/storage/innobase/include/ut0vec.ic deleted file mode 100644 index 531f0f22ae0..00000000000 --- a/storage/innobase/include/ut0vec.ic +++ /dev/null @@ -1,348 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2006, 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/ut0vec.ic -A vector of pointers to data items - -Created 4/6/2006 Osku Salerma -************************************************************************/ - -#define IB_VEC_OFFSET(v, i) (vec->sizeof_value * i) - -/******************************************************************** -The default ib_vector_t heap malloc. Uses mem_heap_alloc(). */ -UNIV_INLINE -void* -ib_heap_malloc( -/*===========*/ - ib_alloc_t* allocator, /* in: allocator */ - ulint size) /* in: size in bytes */ -{ - mem_heap_t* heap = (mem_heap_t*) allocator->arg; - - return(mem_heap_alloc(heap, size)); -} - -/******************************************************************** -The default ib_vector_t heap free. Does nothing. */ -UNIV_INLINE -void -ib_heap_free( -/*=========*/ - ib_alloc_t* allocator UNIV_UNUSED, /* in: allocator */ - void* ptr UNIV_UNUSED) /* in: size in bytes */ -{ - /* We can't free individual elements. */ -} - -/******************************************************************** -The default ib_vector_t heap resize. Since we can't resize the heap -we have to copy the elements from the old ptr to the new ptr. -We always assume new_size >= old_size, so the buffer won't overflow. -Uses mem_heap_alloc(). */ -UNIV_INLINE -void* -ib_heap_resize( -/*===========*/ - ib_alloc_t* allocator, /* in: allocator */ - void* old_ptr, /* in: pointer to memory */ - ulint old_size, /* in: old size in bytes */ - ulint new_size) /* in: new size in bytes */ -{ - void* new_ptr; - mem_heap_t* heap = (mem_heap_t*) allocator->arg; - - ut_a(new_size >= old_size); - new_ptr = mem_heap_alloc(heap, new_size); - memcpy(new_ptr, old_ptr, old_size); - - return(new_ptr); -} - -/******************************************************************** -Create a heap allocator that uses the passed in heap. */ -UNIV_INLINE -ib_alloc_t* -ib_heap_allocator_create( -/*=====================*/ - mem_heap_t* heap) /* in: heap to use */ -{ - ib_alloc_t* heap_alloc; - - heap_alloc = (ib_alloc_t*) mem_heap_alloc(heap, sizeof(*heap_alloc)); - - heap_alloc->arg = heap; - heap_alloc->mem_release = ib_heap_free; - heap_alloc->mem_malloc = ib_heap_malloc; - heap_alloc->mem_resize = ib_heap_resize; - - return(heap_alloc); -} - -/******************************************************************** -Free a heap allocator. */ -UNIV_INLINE -void -ib_heap_allocator_free( -/*===================*/ - ib_alloc_t* ib_ut_alloc) /* in: alloc instace to free */ -{ - mem_heap_free((mem_heap_t*) ib_ut_alloc->arg); -} - -/******************************************************************** -Get number of elements in vector. */ -UNIV_INLINE -ulint -ib_vector_size( -/*===========*/ - /* out: number of elements in vector*/ - const ib_vector_t* vec) /* in: vector */ -{ - return(vec->used); -} - -/****************************************************************//** -Get n'th element. */ -UNIV_INLINE -void* -ib_vector_get( -/*==========*/ - ib_vector_t* vec, /*!< in: vector */ - ulint n) /*!< in: element index to get */ -{ - ut_a(n < vec->used); - - return((byte*) vec->data + IB_VEC_OFFSET(vec, n)); -} - -/******************************************************************** -Const version of the get n'th element. -@return n'th element */ -UNIV_INLINE -const void* -ib_vector_get_const( -/*================*/ - const ib_vector_t* vec, /* in: vector */ - ulint n) /* in: element index to get */ -{ - ut_a(n < vec->used); - - return((byte*) vec->data + IB_VEC_OFFSET(vec, n)); -} -/****************************************************************//** -Get last element. The vector must not be empty. -@return last element */ -UNIV_INLINE -void* -ib_vector_get_last( -/*===============*/ - ib_vector_t* vec) /*!< in: vector */ -{ - ut_a(vec->used > 0); - - return((byte*) ib_vector_get(vec, vec->used - 1)); -} - -/****************************************************************//** -Set the n'th element. */ -UNIV_INLINE -void -ib_vector_set( -/*==========*/ - ib_vector_t* vec, /*!< in/out: vector */ - ulint n, /*!< in: element index to set */ - void* elem) /*!< in: data element */ -{ - void* slot; - - ut_a(n < vec->used); - - slot = ((byte*) vec->data + IB_VEC_OFFSET(vec, n)); - memcpy(slot, elem, vec->sizeof_value); -} - -/******************************************************************** -Reset the vector size to 0 elements. */ -UNIV_INLINE -void -ib_vector_reset( -/*============*/ - /* out: void */ - ib_vector_t* vec) /* in: vector */ -{ - vec->used = 0; -} - -/******************************************************************** -Get the last element of the vector. */ -UNIV_INLINE -void* -ib_vector_last( -/*===========*/ - /* out: void */ - ib_vector_t* vec) /* in: vector */ -{ - ut_a(ib_vector_size(vec) > 0); - - return(ib_vector_get(vec, ib_vector_size(vec) - 1)); -} - -/******************************************************************** -Get the last element of the vector. */ -UNIV_INLINE -const void* -ib_vector_last_const( -/*=================*/ - /* out: void */ - const ib_vector_t* vec) /* in: vector */ -{ - ut_a(ib_vector_size(vec) > 0); - - return(ib_vector_get_const(vec, ib_vector_size(vec) - 1)); -} - -/****************************************************************//** -Remove the last element from the vector. -@return last vector element */ -UNIV_INLINE -void* -ib_vector_pop( -/*==========*/ - /* out: pointer to element */ - ib_vector_t* vec) /* in: vector */ -{ - void* elem; - - ut_a(vec->used > 0); - - elem = ib_vector_last(vec); - --vec->used; - - return(elem); -} - -/******************************************************************** -Append an element to the vector, if elem != NULL then copy the data -from elem.*/ -UNIV_INLINE -void* -ib_vector_push( -/*===========*/ - /* out: pointer to the "new" element */ - ib_vector_t* vec, /* in: vector */ - const void* elem) /* in: element to add (can be NULL) */ -{ - void* last; - - if (vec->used >= vec->total) { - ib_vector_resize(vec); - } - - last = (byte*) vec->data + IB_VEC_OFFSET(vec, vec->used); - -#ifdef UNIV_DEBUG - memset(last, 0, vec->sizeof_value); -#endif - - if (elem) { - memcpy(last, elem, vec->sizeof_value); - } - - ++vec->used; - - return(last); -} - -/*******************************************************************//** -Remove an element to the vector -@return pointer to the "removed" element */ -UNIV_INLINE -void* -ib_vector_remove( -/*=============*/ - ib_vector_t* vec, /*!< in: vector */ - const void* elem) /*!< in: value to remove */ -{ - void* current = NULL; - void* next; - ulint i; - ulint old_used_count = vec->used; - - for (i = 0; i < vec->used; i++) { - current = ib_vector_get(vec, i); - - if (*(void**) current == elem) { - if (i == vec->used - 1) { - return(ib_vector_pop(vec)); - } - - next = ib_vector_get(vec, i + 1); - memmove(current, next, vec->sizeof_value - * (vec->used - i - 1)); - --vec->used; - break; - } - } - - return((old_used_count != vec->used) ? current : NULL); -} - -/******************************************************************** -Sort the vector elements. */ -UNIV_INLINE -void -ib_vector_sort( -/*===========*/ - /* out: void */ - ib_vector_t* vec, /* in: vector */ - ib_compare_t compare)/* in: the comparator to use for sort */ -{ - qsort(vec->data, vec->used, vec->sizeof_value, compare); -} - -/******************************************************************** -Destroy the vector. Make sure the vector owns the allocator, e.g., -the heap in the the heap allocator. */ -UNIV_INLINE -void -ib_vector_free( -/*===========*/ - ib_vector_t* vec) /* in, own: vector */ -{ - /* Currently we only support one type of allocator - heap, - when the heap is freed all the elements are freed too. */ - - /* Only the heap allocator uses the arg field. */ - ut_ad(vec->allocator->arg != NULL); - - mem_heap_free((mem_heap_t*) vec->allocator->arg); -} - -/******************************************************************** -Test whether a vector is empty or not. -@return TRUE if empty */ -UNIV_INLINE -ibool -ib_vector_is_empty( -/*===============*/ - const ib_vector_t* vec) /*!< in: vector */ -{ - return(ib_vector_size(vec) == 0); -} diff --git a/storage/innobase/include/ut0vec.inl b/storage/innobase/include/ut0vec.inl new file mode 100644 index 00000000000..531f0f22ae0 --- /dev/null +++ b/storage/innobase/include/ut0vec.inl @@ -0,0 +1,348 @@ +/***************************************************************************** + +Copyright (c) 2006, 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/ut0vec.ic +A vector of pointers to data items + +Created 4/6/2006 Osku Salerma +************************************************************************/ + +#define IB_VEC_OFFSET(v, i) (vec->sizeof_value * i) + +/******************************************************************** +The default ib_vector_t heap malloc. Uses mem_heap_alloc(). */ +UNIV_INLINE +void* +ib_heap_malloc( +/*===========*/ + ib_alloc_t* allocator, /* in: allocator */ + ulint size) /* in: size in bytes */ +{ + mem_heap_t* heap = (mem_heap_t*) allocator->arg; + + return(mem_heap_alloc(heap, size)); +} + +/******************************************************************** +The default ib_vector_t heap free. Does nothing. */ +UNIV_INLINE +void +ib_heap_free( +/*=========*/ + ib_alloc_t* allocator UNIV_UNUSED, /* in: allocator */ + void* ptr UNIV_UNUSED) /* in: size in bytes */ +{ + /* We can't free individual elements. */ +} + +/******************************************************************** +The default ib_vector_t heap resize. Since we can't resize the heap +we have to copy the elements from the old ptr to the new ptr. +We always assume new_size >= old_size, so the buffer won't overflow. +Uses mem_heap_alloc(). */ +UNIV_INLINE +void* +ib_heap_resize( +/*===========*/ + ib_alloc_t* allocator, /* in: allocator */ + void* old_ptr, /* in: pointer to memory */ + ulint old_size, /* in: old size in bytes */ + ulint new_size) /* in: new size in bytes */ +{ + void* new_ptr; + mem_heap_t* heap = (mem_heap_t*) allocator->arg; + + ut_a(new_size >= old_size); + new_ptr = mem_heap_alloc(heap, new_size); + memcpy(new_ptr, old_ptr, old_size); + + return(new_ptr); +} + +/******************************************************************** +Create a heap allocator that uses the passed in heap. */ +UNIV_INLINE +ib_alloc_t* +ib_heap_allocator_create( +/*=====================*/ + mem_heap_t* heap) /* in: heap to use */ +{ + ib_alloc_t* heap_alloc; + + heap_alloc = (ib_alloc_t*) mem_heap_alloc(heap, sizeof(*heap_alloc)); + + heap_alloc->arg = heap; + heap_alloc->mem_release = ib_heap_free; + heap_alloc->mem_malloc = ib_heap_malloc; + heap_alloc->mem_resize = ib_heap_resize; + + return(heap_alloc); +} + +/******************************************************************** +Free a heap allocator. */ +UNIV_INLINE +void +ib_heap_allocator_free( +/*===================*/ + ib_alloc_t* ib_ut_alloc) /* in: alloc instace to free */ +{ + mem_heap_free((mem_heap_t*) ib_ut_alloc->arg); +} + +/******************************************************************** +Get number of elements in vector. */ +UNIV_INLINE +ulint +ib_vector_size( +/*===========*/ + /* out: number of elements in vector*/ + const ib_vector_t* vec) /* in: vector */ +{ + return(vec->used); +} + +/****************************************************************//** +Get n'th element. */ +UNIV_INLINE +void* +ib_vector_get( +/*==========*/ + ib_vector_t* vec, /*!< in: vector */ + ulint n) /*!< in: element index to get */ +{ + ut_a(n < vec->used); + + return((byte*) vec->data + IB_VEC_OFFSET(vec, n)); +} + +/******************************************************************** +Const version of the get n'th element. +@return n'th element */ +UNIV_INLINE +const void* +ib_vector_get_const( +/*================*/ + const ib_vector_t* vec, /* in: vector */ + ulint n) /* in: element index to get */ +{ + ut_a(n < vec->used); + + return((byte*) vec->data + IB_VEC_OFFSET(vec, n)); +} +/****************************************************************//** +Get last element. The vector must not be empty. +@return last element */ +UNIV_INLINE +void* +ib_vector_get_last( +/*===============*/ + ib_vector_t* vec) /*!< in: vector */ +{ + ut_a(vec->used > 0); + + return((byte*) ib_vector_get(vec, vec->used - 1)); +} + +/****************************************************************//** +Set the n'th element. */ +UNIV_INLINE +void +ib_vector_set( +/*==========*/ + ib_vector_t* vec, /*!< in/out: vector */ + ulint n, /*!< in: element index to set */ + void* elem) /*!< in: data element */ +{ + void* slot; + + ut_a(n < vec->used); + + slot = ((byte*) vec->data + IB_VEC_OFFSET(vec, n)); + memcpy(slot, elem, vec->sizeof_value); +} + +/******************************************************************** +Reset the vector size to 0 elements. */ +UNIV_INLINE +void +ib_vector_reset( +/*============*/ + /* out: void */ + ib_vector_t* vec) /* in: vector */ +{ + vec->used = 0; +} + +/******************************************************************** +Get the last element of the vector. */ +UNIV_INLINE +void* +ib_vector_last( +/*===========*/ + /* out: void */ + ib_vector_t* vec) /* in: vector */ +{ + ut_a(ib_vector_size(vec) > 0); + + return(ib_vector_get(vec, ib_vector_size(vec) - 1)); +} + +/******************************************************************** +Get the last element of the vector. */ +UNIV_INLINE +const void* +ib_vector_last_const( +/*=================*/ + /* out: void */ + const ib_vector_t* vec) /* in: vector */ +{ + ut_a(ib_vector_size(vec) > 0); + + return(ib_vector_get_const(vec, ib_vector_size(vec) - 1)); +} + +/****************************************************************//** +Remove the last element from the vector. +@return last vector element */ +UNIV_INLINE +void* +ib_vector_pop( +/*==========*/ + /* out: pointer to element */ + ib_vector_t* vec) /* in: vector */ +{ + void* elem; + + ut_a(vec->used > 0); + + elem = ib_vector_last(vec); + --vec->used; + + return(elem); +} + +/******************************************************************** +Append an element to the vector, if elem != NULL then copy the data +from elem.*/ +UNIV_INLINE +void* +ib_vector_push( +/*===========*/ + /* out: pointer to the "new" element */ + ib_vector_t* vec, /* in: vector */ + const void* elem) /* in: element to add (can be NULL) */ +{ + void* last; + + if (vec->used >= vec->total) { + ib_vector_resize(vec); + } + + last = (byte*) vec->data + IB_VEC_OFFSET(vec, vec->used); + +#ifdef UNIV_DEBUG + memset(last, 0, vec->sizeof_value); +#endif + + if (elem) { + memcpy(last, elem, vec->sizeof_value); + } + + ++vec->used; + + return(last); +} + +/*******************************************************************//** +Remove an element to the vector +@return pointer to the "removed" element */ +UNIV_INLINE +void* +ib_vector_remove( +/*=============*/ + ib_vector_t* vec, /*!< in: vector */ + const void* elem) /*!< in: value to remove */ +{ + void* current = NULL; + void* next; + ulint i; + ulint old_used_count = vec->used; + + for (i = 0; i < vec->used; i++) { + current = ib_vector_get(vec, i); + + if (*(void**) current == elem) { + if (i == vec->used - 1) { + return(ib_vector_pop(vec)); + } + + next = ib_vector_get(vec, i + 1); + memmove(current, next, vec->sizeof_value + * (vec->used - i - 1)); + --vec->used; + break; + } + } + + return((old_used_count != vec->used) ? current : NULL); +} + +/******************************************************************** +Sort the vector elements. */ +UNIV_INLINE +void +ib_vector_sort( +/*===========*/ + /* out: void */ + ib_vector_t* vec, /* in: vector */ + ib_compare_t compare)/* in: the comparator to use for sort */ +{ + qsort(vec->data, vec->used, vec->sizeof_value, compare); +} + +/******************************************************************** +Destroy the vector. Make sure the vector owns the allocator, e.g., +the heap in the the heap allocator. */ +UNIV_INLINE +void +ib_vector_free( +/*===========*/ + ib_vector_t* vec) /* in, own: vector */ +{ + /* Currently we only support one type of allocator - heap, + when the heap is freed all the elements are freed too. */ + + /* Only the heap allocator uses the arg field. */ + ut_ad(vec->allocator->arg != NULL); + + mem_heap_free((mem_heap_t*) vec->allocator->arg); +} + +/******************************************************************** +Test whether a vector is empty or not. +@return TRUE if empty */ +UNIV_INLINE +ibool +ib_vector_is_empty( +/*===============*/ + const ib_vector_t* vec) /*!< in: vector */ +{ + return(ib_vector_size(vec) == 0); +} diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 51bf8843d87..a13228d7b59 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -50,7 +50,7 @@ #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80) #define IS_MB2_CHAR(x,y) (isbig5head(x) && isbig5tail(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" static const uchar ctype_big5[257] = @@ -6681,13 +6681,13 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_MB2(x,y) (big5code(x, y)) #define WEIGHT_MB2_FRM(x,y) (big5strokexfrm((uint16) WEIGHT_MB2(x, y))) #define DEFINE_STRNXFRM -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _big5_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (big5code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -6696,14 +6696,14 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_MB2(x,y) (big5code(x, y)) #define WEIGHT_MB2_FRM(x,y) (big5strokexfrm((uint16) WEIGHT_MB2(x, y))) #define DEFINE_STRNXFRM -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _big5_nopad_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (big5code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" static MY_COLLATION_HANDLER my_collation_handler_big5_chinese_ci= diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index bf97d1feb83..3da8458575a 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -188,7 +188,7 @@ static const uchar sort_order_cp932[]= #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80 || iscp932kata(x)) #define IS_MB2_CHAR(x,y) (iscp932head(x) && iscp932tail(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" #define cp932code(c,d) ((((uint) (uchar)(c)) << 8) | (uint) (uchar) (d)) @@ -34636,14 +34636,14 @@ size_t my_numcells_cp932(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) sort_order_cp932[(uchar) (x)]) #define WEIGHT_MB2(x,y) (cp932code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _cp932_bin #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) (uchar) (x)) #define WEIGHT_MB2(x,y) (cp932code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -34651,7 +34651,7 @@ size_t my_numcells_cp932(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) sort_order_cp932[(uchar) (x)]) #define WEIGHT_MB2(x,y) (cp932code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -34659,7 +34659,7 @@ size_t my_numcells_cp932(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) (uchar) (x)) #define WEIGHT_MB2(x,y) (cp932code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" static MY_COLLATION_HANDLER my_collation_handler_cp932_japanese_ci= diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index deb13957900..0d1685b60cb 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -207,7 +207,7 @@ static const uchar sort_order_euc_kr[]= #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80) #define IS_MB2_CHAR(x,y) (iseuc_kr_head(x) && iseuc_kr_tail(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" static MY_UNICASE_CHARACTER cA3[256]= @@ -9929,27 +9929,27 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _euckr_korean_ci #define WEIGHT_MB1(x) (sort_order_euc_kr[(uchar) (x)]) #define WEIGHT_MB2(x,y) (euckrcode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _euckr_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (euckrcode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _euckr_korean_nopad_ci #define WEIGHT_MB1(x) (sort_order_euc_kr[(uchar) (x)]) #define WEIGHT_MB2(x,y) (euckrcode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _euckr_nopad_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (euckrcode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" static MY_COLLATION_HANDLER my_collation_handler_euckr_korean_ci= diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 118e8286703..6fba471134f 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -201,7 +201,7 @@ static const uchar sort_order_eucjpms[]= #define IS_MB3_CHAR(x,y,z) (iseucjpms_ss3(x) && IS_MB2_JIS(y,z)) #define IS_MB_PREFIX2(x,y) (iseucjpms_ss3(x) && iseucjpms(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _eucjpms_japanese_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) @@ -209,7 +209,7 @@ static const uchar sort_order_eucjpms[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _eucjpms_bin @@ -218,7 +218,7 @@ static const uchar sort_order_eucjpms[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -228,7 +228,7 @@ static const uchar sort_order_eucjpms[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -238,7 +238,7 @@ static const uchar sort_order_eucjpms[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" /* Case info pages for JIS-X-0208 range */ diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 166619bf5cc..f776b3ad1b9 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -170,7 +170,7 @@ static const uchar sort_order_gb2312[]= #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80) #define IS_MB2_CHAR(x,y) (isgb2312head(x) && isgb2312tail(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" static MY_UNICASE_CHARACTER cA2[256]= @@ -6334,27 +6334,27 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _gb2312_chinese_ci #define WEIGHT_MB1(x) (sort_order_gb2312[(uchar) (x)]) #define WEIGHT_MB2(x,y) (gb2312code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _gb2312_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (gb2312code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _gb2312_chinese_nopad_ci #define WEIGHT_MB1(x) (sort_order_gb2312[(uchar) (x)]) #define WEIGHT_MB2(x,y) (gb2312code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _gb2312_nopad_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (gb2312code(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" static MY_COLLATION_HANDLER my_collation_handler_gb2312_chinese_ci= diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index efaa2e5c728..2e757f009ed 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -47,7 +47,7 @@ #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80) #define IS_MB2_CHAR(x,y) (isgbkhead(x) && isgbktail(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" static const uchar ctype_gbk[257] = @@ -10616,13 +10616,13 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_MB1(x) (sort_order_gbk[(uchar) (x)]) #define WEIGHT_MB2(x,y) (gbksortorder(gbkcode(x,y))) #define DEFINE_STRNXFRM -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _gbk_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (gbkcode(x,y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -10630,14 +10630,14 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_MB1(x) (sort_order_gbk[(uchar) (x)]) #define WEIGHT_MB2(x,y) (gbksortorder(gbkcode(x,y))) #define DEFINE_STRNXFRM -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _gbk_nopad_bin #define WEIGHT_MB1(x) ((uchar) (x)) #define WEIGHT_MB2(x,y) (gbkcode(x,y)) -#include "strcoll.ic" +#include "strcoll.inl" static MY_COLLATION_HANDLER my_collation_handler_gbk_chinese_ci= diff --git a/strings/ctype-mb.ic b/strings/ctype-mb.ic deleted file mode 100644 index 336c482d24f..00000000000 --- a/strings/ctype-mb.ic +++ /dev/null @@ -1,263 +0,0 @@ -/* - Copyright (c) 2015, MariaDB Foundation - - 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-1335 USA -*/ - - -#ifndef MY_FUNCTION_NAME -#error MY_FUNCTION_NAME is not defined -#endif - -#if defined(IS_MB3_CHAR) && !defined(IS_MB2_CHAR) -#error IS_MB3_CHAR is defined, while IS_MB2_CHAR is not! -#endif - -#if defined(IS_MB4_CHAR) && !defined(IS_MB3_CHAR) -#error IS_MB4_CHAR is defined, while IS_MB3_CHAR is not! -#endif - - -#ifdef DEFINE_ASIAN_ROUTINES -#define DEFINE_WELL_FORMED_CHAR_LENGTH -#define DEFINE_CHARLEN -#define DEFINE_NATIVE_TO_MB_VARLEN -#endif - - -#ifdef DEFINE_CHARLEN -/** - Returns length of the left-most character of a string. - @param cs - charset with mbminlen==1 and mbmaxlen<=4 - @param b - the beginning of the string - @param e - the end of the string - - @return MY_CS_ILSEQ if a bad byte sequence was found - @return MY_CS_TOOSMALL(N) if the string ended unexpectedly - @return >0 if a valid character was found -*/ -static int -MY_FUNCTION_NAME(charlen)(CHARSET_INFO *cs __attribute__((unused)), - const uchar *b, const uchar *e) -{ - DBUG_ASSERT(cs->mbminlen == 1); - DBUG_ASSERT(cs->mbmaxlen <= 4); - - if (b >= e) - return MY_CS_TOOSMALL; - if ((uchar) b[0] < 128) - return 1; /* Single byte ASCII character */ - -#ifdef IS_8BIT_CHAR - if (IS_8BIT_CHAR(b[0])) - { - /* Single byte non-ASCII character, e.g. half width kana in sjis */ - return 1; - } -#endif - - if (b + 2 > e) - return MY_CS_TOOSMALLN(2); - if (IS_MB2_CHAR(b[0], b[1])) - return 2; /* Double byte character */ - -#ifdef IS_MB3_CHAR - if (b + 3 > e) - { -#ifdef IS_MB_PREFIX2 - if (!IS_MB_PREFIX2(b[0], b[1])) - return MY_CS_ILSEQ; -#endif - return MY_CS_TOOSMALLN(3); - } - if (IS_MB3_CHAR(b[0], b[1], b[2])) - return 3; /* Three-byte character */ -#endif - -#ifdef IS_MB4_CHAR - if (b + 4 > e) - return MY_CS_TOOSMALLN(4); - if (IS_MB4_CHAR(b[0], b[1], b[2], b[3])) - return 4; /* Four-byte character */ -#endif - - /* Wrong byte sequence */ - return MY_CS_ILSEQ; -} -#endif /* DEFINE_CHARLEN */ - - -#ifdef DEFINE_WELL_FORMED_CHAR_LENGTH -/** - Returns well formed length of a string - measured in characters (rather than in bytes). - Version for character sets that define IS_MB?_CHAR(), e.g. big5. -*/ -static size_t -MY_FUNCTION_NAME(well_formed_char_length)(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, - size_t nchars, - MY_STRCOPY_STATUS *status) -{ - size_t nchars0= nchars; - for ( ; b < e && nchars ; nchars--) - { - if ((uchar) b[0] < 128) - { - b++; /* Single byte ASCII character */ - continue; - } - - if (b + 2 <= e && IS_MB2_CHAR(b[0], b[1])) - { - b+= 2; /* Double byte character */ - continue; - } - -#ifdef IS_MB3_CHAR - if (b + 3 <= e && IS_MB3_CHAR(b[0], b[1], b[2])) - { - b+= 3; /* Three-byte character */ - continue; - } -#endif - -#ifdef IS_MB4_CHAR - if (b + 4 <= e && IS_MB4_CHAR(b[0], b[1], b[2], b[3])) - { - b+= 4; /* Four-byte character */ - continue; - } -#endif - -#ifdef IS_8BIT_CHAR - if (IS_8BIT_CHAR(b[0])) - { - b++; /* Single byte non-ASCII character, e.g. half width kana in sjis */ - continue; - } -#endif - - /* Wrong byte sequence */ - status->m_source_end_pos= status->m_well_formed_error_pos= b; - return nchars0 - nchars; - } - status->m_source_end_pos= b; - status->m_well_formed_error_pos= NULL; - return nchars0 - nchars; -} -#endif /* DEFINE_WELL_FORMED_CHAR_LENGTH */ - - -#ifdef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN -#ifndef CHARLEN -#error CHARLEN is not defined -#endif -/** - Returns well formed length of a string - measured in characters (rather than in bytes). - Version for character sets that define CHARLEN(), e.g. utf8. - CHARLEN(cs,b,e) must use the same return code convension that mb_wc() does: - - a positive number in the range [1-mbmaxlen] if a valid - single-byte or multi-byte character was found - - MY_CS_ILSEQ (0) on a bad byte sequence - - MY_CS_TOOSMALLxx if the incoming sequence is incomplete -*/ -static size_t -MY_FUNCTION_NAME(well_formed_char_length)(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, - size_t nchars, - MY_STRCOPY_STATUS *status) -{ - size_t nchars0= nchars; - int chlen; - for ( ; nchars ; nchars--, b+= chlen) - { - if ((chlen= CHARLEN(cs, (uchar*) b, (uchar*) e)) <= 0) - { - status->m_well_formed_error_pos= b < e ? b : NULL; - status->m_source_end_pos= b; - return nchars0 - nchars; - } - } - status->m_well_formed_error_pos= NULL; - status->m_source_end_pos= b; - return nchars0 - nchars; -} -#endif /* DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN */ - - -#ifdef DEFINE_NATIVE_TO_MB_VARLEN -/* - Write a native 2-byte character. - If the full character does not fit, only the first byte is written. -*/ -static inline int -my_native_to_mb_fixed2(my_wc_t wc, uchar *s, uchar *e) -{ - /* The caller must insure there is a space for at least one byte */ - DBUG_ASSERT(s < e); - s[0]= (uchar) (wc >> 8); - if (s + 2 > e) - return MY_CS_TOOSMALL2; - s[1]= wc & 0xFF; - return 2; -} - - -/* - Write a native 3-byte character. - If the full character does not fit, only the leading bytes are written. -*/ -static inline int -my_native_to_mb_fixed3(my_wc_t wc, uchar *s, uchar *e) -{ - /* The caller must insure there is a space for at least one byte */ - DBUG_ASSERT(s < e); - s[0]= (uchar) (wc >> 16); - if (s + 2 > e) - return MY_CS_TOOSMALL2; - s[1]= (wc >> 8) & 0xFF; - if (s + 3 > e) - return MY_CS_TOOSMALL3; - s[2]= wc & 0xFF; - return 3; -} - - -/* - Write a native 1-byte or 2-byte or 3-byte character. -*/ - -static int -MY_FUNCTION_NAME(native_to_mb)(CHARSET_INFO *cs __attribute__((unused)), - my_wc_t wc, uchar *s, uchar *e) -{ - if (s >= e) - return MY_CS_TOOSMALL; - if ((int) wc <= 0xFF) - { - s[0]= (uchar) wc; - return 1; - } -#ifdef IS_MB3_HEAD - if (wc > 0xFFFF) - return my_native_to_mb_fixed3(wc, s, e); -#endif - return my_native_to_mb_fixed2(wc, s, e); -} -#endif /* DEFINE_NATIVE_TO_MB_VARLEN */ - - -#undef MY_FUNCTION_NAME diff --git a/strings/ctype-mb.inl b/strings/ctype-mb.inl new file mode 100644 index 00000000000..336c482d24f --- /dev/null +++ b/strings/ctype-mb.inl @@ -0,0 +1,263 @@ +/* + Copyright (c) 2015, MariaDB Foundation + + 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-1335 USA +*/ + + +#ifndef MY_FUNCTION_NAME +#error MY_FUNCTION_NAME is not defined +#endif + +#if defined(IS_MB3_CHAR) && !defined(IS_MB2_CHAR) +#error IS_MB3_CHAR is defined, while IS_MB2_CHAR is not! +#endif + +#if defined(IS_MB4_CHAR) && !defined(IS_MB3_CHAR) +#error IS_MB4_CHAR is defined, while IS_MB3_CHAR is not! +#endif + + +#ifdef DEFINE_ASIAN_ROUTINES +#define DEFINE_WELL_FORMED_CHAR_LENGTH +#define DEFINE_CHARLEN +#define DEFINE_NATIVE_TO_MB_VARLEN +#endif + + +#ifdef DEFINE_CHARLEN +/** + Returns length of the left-most character of a string. + @param cs - charset with mbminlen==1 and mbmaxlen<=4 + @param b - the beginning of the string + @param e - the end of the string + + @return MY_CS_ILSEQ if a bad byte sequence was found + @return MY_CS_TOOSMALL(N) if the string ended unexpectedly + @return >0 if a valid character was found +*/ +static int +MY_FUNCTION_NAME(charlen)(CHARSET_INFO *cs __attribute__((unused)), + const uchar *b, const uchar *e) +{ + DBUG_ASSERT(cs->mbminlen == 1); + DBUG_ASSERT(cs->mbmaxlen <= 4); + + if (b >= e) + return MY_CS_TOOSMALL; + if ((uchar) b[0] < 128) + return 1; /* Single byte ASCII character */ + +#ifdef IS_8BIT_CHAR + if (IS_8BIT_CHAR(b[0])) + { + /* Single byte non-ASCII character, e.g. half width kana in sjis */ + return 1; + } +#endif + + if (b + 2 > e) + return MY_CS_TOOSMALLN(2); + if (IS_MB2_CHAR(b[0], b[1])) + return 2; /* Double byte character */ + +#ifdef IS_MB3_CHAR + if (b + 3 > e) + { +#ifdef IS_MB_PREFIX2 + if (!IS_MB_PREFIX2(b[0], b[1])) + return MY_CS_ILSEQ; +#endif + return MY_CS_TOOSMALLN(3); + } + if (IS_MB3_CHAR(b[0], b[1], b[2])) + return 3; /* Three-byte character */ +#endif + +#ifdef IS_MB4_CHAR + if (b + 4 > e) + return MY_CS_TOOSMALLN(4); + if (IS_MB4_CHAR(b[0], b[1], b[2], b[3])) + return 4; /* Four-byte character */ +#endif + + /* Wrong byte sequence */ + return MY_CS_ILSEQ; +} +#endif /* DEFINE_CHARLEN */ + + +#ifdef DEFINE_WELL_FORMED_CHAR_LENGTH +/** + Returns well formed length of a string + measured in characters (rather than in bytes). + Version for character sets that define IS_MB?_CHAR(), e.g. big5. +*/ +static size_t +MY_FUNCTION_NAME(well_formed_char_length)(CHARSET_INFO *cs __attribute__((unused)), + const char *b, const char *e, + size_t nchars, + MY_STRCOPY_STATUS *status) +{ + size_t nchars0= nchars; + for ( ; b < e && nchars ; nchars--) + { + if ((uchar) b[0] < 128) + { + b++; /* Single byte ASCII character */ + continue; + } + + if (b + 2 <= e && IS_MB2_CHAR(b[0], b[1])) + { + b+= 2; /* Double byte character */ + continue; + } + +#ifdef IS_MB3_CHAR + if (b + 3 <= e && IS_MB3_CHAR(b[0], b[1], b[2])) + { + b+= 3; /* Three-byte character */ + continue; + } +#endif + +#ifdef IS_MB4_CHAR + if (b + 4 <= e && IS_MB4_CHAR(b[0], b[1], b[2], b[3])) + { + b+= 4; /* Four-byte character */ + continue; + } +#endif + +#ifdef IS_8BIT_CHAR + if (IS_8BIT_CHAR(b[0])) + { + b++; /* Single byte non-ASCII character, e.g. half width kana in sjis */ + continue; + } +#endif + + /* Wrong byte sequence */ + status->m_source_end_pos= status->m_well_formed_error_pos= b; + return nchars0 - nchars; + } + status->m_source_end_pos= b; + status->m_well_formed_error_pos= NULL; + return nchars0 - nchars; +} +#endif /* DEFINE_WELL_FORMED_CHAR_LENGTH */ + + +#ifdef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN +#ifndef CHARLEN +#error CHARLEN is not defined +#endif +/** + Returns well formed length of a string + measured in characters (rather than in bytes). + Version for character sets that define CHARLEN(), e.g. utf8. + CHARLEN(cs,b,e) must use the same return code convension that mb_wc() does: + - a positive number in the range [1-mbmaxlen] if a valid + single-byte or multi-byte character was found + - MY_CS_ILSEQ (0) on a bad byte sequence + - MY_CS_TOOSMALLxx if the incoming sequence is incomplete +*/ +static size_t +MY_FUNCTION_NAME(well_formed_char_length)(CHARSET_INFO *cs __attribute__((unused)), + const char *b, const char *e, + size_t nchars, + MY_STRCOPY_STATUS *status) +{ + size_t nchars0= nchars; + int chlen; + for ( ; nchars ; nchars--, b+= chlen) + { + if ((chlen= CHARLEN(cs, (uchar*) b, (uchar*) e)) <= 0) + { + status->m_well_formed_error_pos= b < e ? b : NULL; + status->m_source_end_pos= b; + return nchars0 - nchars; + } + } + status->m_well_formed_error_pos= NULL; + status->m_source_end_pos= b; + return nchars0 - nchars; +} +#endif /* DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN */ + + +#ifdef DEFINE_NATIVE_TO_MB_VARLEN +/* + Write a native 2-byte character. + If the full character does not fit, only the first byte is written. +*/ +static inline int +my_native_to_mb_fixed2(my_wc_t wc, uchar *s, uchar *e) +{ + /* The caller must insure there is a space for at least one byte */ + DBUG_ASSERT(s < e); + s[0]= (uchar) (wc >> 8); + if (s + 2 > e) + return MY_CS_TOOSMALL2; + s[1]= wc & 0xFF; + return 2; +} + + +/* + Write a native 3-byte character. + If the full character does not fit, only the leading bytes are written. +*/ +static inline int +my_native_to_mb_fixed3(my_wc_t wc, uchar *s, uchar *e) +{ + /* The caller must insure there is a space for at least one byte */ + DBUG_ASSERT(s < e); + s[0]= (uchar) (wc >> 16); + if (s + 2 > e) + return MY_CS_TOOSMALL2; + s[1]= (wc >> 8) & 0xFF; + if (s + 3 > e) + return MY_CS_TOOSMALL3; + s[2]= wc & 0xFF; + return 3; +} + + +/* + Write a native 1-byte or 2-byte or 3-byte character. +*/ + +static int +MY_FUNCTION_NAME(native_to_mb)(CHARSET_INFO *cs __attribute__((unused)), + my_wc_t wc, uchar *s, uchar *e) +{ + if (s >= e) + return MY_CS_TOOSMALL; + if ((int) wc <= 0xFF) + { + s[0]= (uchar) wc; + return 1; + } +#ifdef IS_MB3_HEAD + if (wc > 0xFFFF) + return my_native_to_mb_fixed3(wc, s, e); +#endif + return my_native_to_mb_fixed2(wc, s, e); +} +#endif /* DEFINE_NATIVE_TO_MB_VARLEN */ + + +#undef MY_FUNCTION_NAME diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 902034b435d..4b7fa23f74c 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -189,7 +189,7 @@ static const uchar sort_order_sjis[]= #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80 || issjiskata(x)) #define IS_MB2_CHAR(x,y) (issjishead(x) && issjistail(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" #define sjiscode(c,d) ((((uint) (uchar)(c)) << 8) | (uint) (uchar) (d)) @@ -34015,14 +34015,14 @@ size_t my_numcells_sjis(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) sort_order_sjis[(uchar) (x)]) #define WEIGHT_MB2(x,y) (sjiscode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _sjis_bin #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) (uchar) (x)) #define WEIGHT_MB2(x,y) (sjiscode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -34030,7 +34030,7 @@ size_t my_numcells_sjis(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) sort_order_sjis[(uchar) (x)]) #define WEIGHT_MB2(x,y) (sjiscode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -34038,7 +34038,7 @@ size_t my_numcells_sjis(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_PAD_SPACE (256 * (int) ' ') #define WEIGHT_MB1(x) (256 * (int) (uchar) (x)) #define WEIGHT_MB2(x,y) (sjiscode(x, y)) -#include "strcoll.ic" +#include "strcoll.inl" static MY_COLLATION_HANDLER my_collation_handler_sjis_japanese_ci= diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 29d56919633..3fbd26bec11 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1230,27 +1230,27 @@ static inline int my_weight_mb2_utf16mb2_general_ci(uchar b0, uchar b1) #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_utf16mb2_general_ci(b0,b1) #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) ((int) MY_UTF16_WC2(b0, b1)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) MY_UTF16_WC4(b0, b1, b2, b3)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16_general_nopad_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_utf16mb2_general_ci(b0,b1) #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16_nopad_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) ((int) MY_UTF16_WC2(b0, b1)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) MY_UTF16_WC4(b0, b1, b2, b3)) -#include "strcoll.ic" +#include "strcoll.inl" #undef IS_MB2_CHAR #undef IS_MB4_CHAR @@ -1456,7 +1456,7 @@ my_charlen_utf16(CHARSET_INFO *cs, const uchar *str, const uchar *end) #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16 #define CHARLEN(cs,str,end) my_charlen_utf16(cs,str,end) #define DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN -#include "ctype-mb.ic" +#include "ctype-mb.inl" #undef MY_FUNCTION_NAME #undef CHARLEN #undef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN @@ -1781,27 +1781,27 @@ struct charset_info_st my_charset_utf16_nopad_bin= #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_utf16mb2_general_ci(b1,b0) #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16le_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) ((int) MY_UTF16_WC2(b1, b0)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) MY_UTF16_WC4(b1, b0, b3, b2)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16le_general_nopad_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_utf16mb2_general_ci(b1,b0) #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16le_nopad_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) ((int) MY_UTF16_WC2(b1, b0)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) MY_UTF16_WC4(b1, b0, b3, b2)) -#include "strcoll.ic" +#include "strcoll.inl" #undef IS_MB2_CHAR #undef IS_MB4_CHAR @@ -2137,24 +2137,24 @@ static inline int my_weight_utf32_general_ci(uchar b0, uchar b1, #define MY_FUNCTION_NAME(x) my_ ## x ## _utf32_general_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB4(b0,b1,b2,b3) my_weight_utf32_general_ci(b0, b1, b2, b3) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _utf32_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) MY_UTF32_WC4(b0, b1, b2, b3)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _utf32_general_nopad_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB4(b0,b1,b2,b3) my_weight_utf32_general_ci(b0, b1, b2, b3) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _utf32_nopad_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) MY_UTF32_WC4(b0, b1, b2, b3)) -#include "strcoll.ic" +#include "strcoll.inl" #undef IS_MB2_CHAR #undef IS_MB4_CHAR @@ -2327,7 +2327,7 @@ my_charlen_utf32(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _utf32 #define CHARLEN(cs,str,end) my_charlen_utf32(cs,str,end) #define DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN -#include "ctype-mb.ic" +#include "ctype-mb.inl" #undef MY_FUNCTION_NAME #undef CHARLEN #undef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN @@ -2993,7 +2993,7 @@ static const uchar to_upper_ucs2[] = { }; -/* Definitions for strcoll.ic */ +/* Definitions for strcoll.inl */ #define IS_MB2_CHAR(x,y) (1) #define UCS2_CODE(b0,b1) (((uchar) b0) << 8 | ((uchar) b1)) @@ -3009,27 +3009,27 @@ static inline int my_weight_mb2_ucs2_general_ci(uchar b0, uchar b1) #define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_general_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_ucs2_general_ci(b0,b1) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) UCS2_CODE(b0,b1) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_general_nopad_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_ucs2_general_ci(b0,b1) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD #define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_nopad_bin #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) UCS2_CODE(b0,b1) -#include "strcoll.ic" +#include "strcoll.inl" static int diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 949f3aadc36..f470bbd7844 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -200,7 +200,7 @@ static const uchar sort_order_ujis[]= #define IS_MB3_CHAR(x, y, z) (isujis_ss3(x) && IS_MB2_JIS(y,z)) #define IS_MB_PREFIX2(x,y) (isujis_ss3(x) && isujis(y)) #define DEFINE_ASIAN_ROUTINES -#include "ctype-mb.ic" +#include "ctype-mb.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _ujis_japanese_ci #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) @@ -208,7 +208,7 @@ static const uchar sort_order_ujis[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _ujis_bin @@ -217,7 +217,7 @@ static const uchar sort_order_ujis[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -227,7 +227,7 @@ static const uchar sort_order_ujis[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -237,7 +237,7 @@ static const uchar sort_order_ujis[]= #define WEIGHT_MB2(x,y) ((((uint) (uchar)(x)) << 16) | \ (((uint) (uchar) (y)) << 8)) #define WEIGHT_MB3(x,y,z) (WEIGHT_MB2(x,y) | ((uint) (uchar) z)) -#include "strcoll.ic" +#include "strcoll.inl" static diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 8f3b1224404..64eae11e8eb 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -99,7 +99,7 @@ ((my_wc_t) ((uchar) b2 ^ 0x80) << 6) |\ (my_wc_t) ((uchar) b3 ^ 0x80)) -/* Definitions for strcoll.ic */ +/* Definitions for strcoll.inl */ #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80) #define IS_MB1_MBHEAD_UNUSED_GAP(x) ((uchar) (x) < 0xC2) #define IS_MB2_CHAR(x,y) IS_UTF8MB2_STEP2(x,y) @@ -5402,7 +5402,7 @@ int my_charlen_utf8(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _utf8 #define CHARLEN(cs,str,end) my_charlen_utf8(cs,str,end) #define DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN -#include "ctype-mb.ic" +#include "ctype-mb.inl" #undef MY_FUNCTION_NAME #undef CHARLEN #undef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN @@ -5436,7 +5436,7 @@ static inline int my_weight_mb3_utf8_general_ci(uchar b0, uchar b1, uchar b2) #define WEIGHT_MB1(x) my_weight_mb1_utf8_general_ci(x) #define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_ci(x,y) #define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_ci(x,y,z) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -5445,7 +5445,7 @@ static inline int my_weight_mb3_utf8_general_ci(uchar b0, uchar b1, uchar b2) #define WEIGHT_MB1(x) my_weight_mb1_utf8_general_ci(x) #define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_ci(x,y) #define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_ci(x,y,z) -#include "strcoll.ic" +#include "strcoll.inl" static inline int my_weight_mb1_utf8_general_mysql500_ci(uchar b) @@ -5476,7 +5476,7 @@ my_weight_mb3_utf8_general_mysql500_ci(uchar b0, uchar b1, uchar b2) #define WEIGHT_MB1(x) my_weight_mb1_utf8_general_mysql500_ci(x) #define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_mysql500_ci(x,y) #define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_mysql500_ci(x,y,z) -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _utf8_bin @@ -5484,7 +5484,7 @@ my_weight_mb3_utf8_general_mysql500_ci(uchar b0, uchar b1, uchar b2) #define WEIGHT_MB1(x) ((int) (uchar) (x)) #define WEIGHT_MB2(x,y) ((int) UTF8MB2_CODE(x,y)) #define WEIGHT_MB3(x,y,z) ((int) UTF8MB3_CODE(x,y,z)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -5493,7 +5493,7 @@ my_weight_mb3_utf8_general_mysql500_ci(uchar b0, uchar b1, uchar b2) #define WEIGHT_MB1(x) ((int) (uchar) (x)) #define WEIGHT_MB2(x,y) ((int) UTF8MB2_CODE(x,y)) #define WEIGHT_MB3(x,y,z) ((int) UTF8MB3_CODE(x,y,z)) -#include "strcoll.ic" +#include "strcoll.inl" /* TODO-10.2: join this with pad_max_char() in ctype-mb.c @@ -7204,7 +7204,7 @@ my_charlen_filename(CHARSET_INFO *cs, const uchar *str, const uchar *end) #define MY_FUNCTION_NAME(x) my_ ## x ## _filename #define CHARLEN(cs,str,end) my_charlen_filename(cs,str,end) #define DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN -#include "ctype-mb.ic" +#include "ctype-mb.inl" #undef MY_FUNCTION_NAME #undef CHARLEN #undef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN @@ -7835,7 +7835,7 @@ my_charlen_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _utf8mb4 #define CHARLEN(cs,str,end) my_charlen_utf8mb4(cs,str,end) #define DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN -#include "ctype-mb.ic" +#include "ctype-mb.inl" #undef MY_FUNCTION_NAME #undef CHARLEN #undef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN @@ -7852,7 +7852,7 @@ my_charlen_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), All non-BMP characters have the same weight. */ #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER -#include "strcoll.ic" +#include "strcoll.inl" #define MY_FUNCTION_NAME(x) my_ ## x ## _utf8mb4_bin @@ -7861,7 +7861,7 @@ my_charlen_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_MB2(b0,b1) ((int) UTF8MB2_CODE(b0,b1)) #define WEIGHT_MB3(b0,b1,b2) ((int) UTF8MB3_CODE(b0,b1,b2)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) UTF8MB4_CODE(b0,b1,b2,b3)) -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -7875,7 +7875,7 @@ my_charlen_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), All non-BMP characters have the same weight. */ #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER -#include "strcoll.ic" +#include "strcoll.inl" #define DEFINE_STRNNCOLLSP_NOPAD @@ -7885,7 +7885,7 @@ my_charlen_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), #define WEIGHT_MB2(b0,b1) ((int) UTF8MB2_CODE(b0,b1)) #define WEIGHT_MB3(b0,b1,b2) ((int) UTF8MB3_CODE(b0,b1,b2)) #define WEIGHT_MB4(b0,b1,b2,b3) ((int) UTF8MB4_CODE(b0,b1,b2,b3)) -#include "strcoll.ic" +#include "strcoll.inl" static MY_COLLATION_HANDLER my_collation_utf8mb4_general_ci_handler= diff --git a/strings/strcoll.ic b/strings/strcoll.ic deleted file mode 100644 index eb5b3d5fe9b..00000000000 --- a/strings/strcoll.ic +++ /dev/null @@ -1,338 +0,0 @@ -/* - Copyright (c) 2015, MariaDB Foundation - - 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-1335 USA -*/ - - -#ifndef MY_FUNCTION_NAME -#error MY_FUNCTION_NAME is not defined -#endif - - -/* - The weight for automatically padded spaces when comparing strings with - the PAD SPACE property. - Should normally be equal to the weight of a regular space. -*/ -#ifndef WEIGHT_PAD_SPACE -#define WEIGHT_PAD_SPACE (' ') -#endif - - -/* - Weight of an illegal byte, must follow these rules: - 1. Must be greater than weight of any normal character in the collation. - 2. Two different bad bytes must have different weights and must be - compared in their binary order. - - Depends on mbmaxlen of the character set, as well as how the collation - sorts various single-byte and multi-byte character blocks. - - The macro below is the default definition, it is suitable for mbmaxlen=2 - character sets that sort all multi-byte characters after all single-byte - characters: big5, euckr, gb2312, gbk. - - All mbmaxlen>2 character sets must provide their own definitions. - All collations that have a more complex order (than just MB1 followed by MB2) - must also provide their own definitions (see definitions for - cp932_japanese_ci and sjis_japanese_ci as examples of a more complex order). -*/ -#ifndef WEIGHT_ILSEQ -#define WEIGHT_ILSEQ(x) (0xFF00 + (x)) -#endif - - -/** - Scan a valid character, or a bad byte, or an auto-padded space - from a string and calculate the weight of the scanned sequence. - - @param [OUT] weight - the weight is returned here - @param str - the string - @param end - the end of the string - @return - the number of bytes scanned - - The including source file must define the following macros: - IS_MB1_CHAR(b0) - for character sets that have MB1 characters - IS_MB1_MB2HEAD_GAP(b0) - optional, for better performance - IS_MB2_CHAR(b0,b1) - for character sets that have MB2 characters - IS_MB3_CHAR(b0,b1,b2) - for character sets that have MB3 characters - IS_MB4_CHAR(b0,b1,b2,b3) - for character sets with have MB4 characters - WEIGHT_PAD_SPACE - WEIGHT_MB1(b0) - for character sets that have MB1 characters - WEIGHT_MB2(b0,b1) - for character sets that have MB2 characters - WEIGHT_MB3(b0,b1,b2) - for character sets that have MB3 characters - WEIGHT_MB4(b0,b1,b2,b3) - for character sets that have MB4 characters - WEIGHT_ILSEQ(x) -*/ -static inline uint -MY_FUNCTION_NAME(scan_weight)(int *weight, const uchar *str, const uchar *end) -{ - if (str >= end) - { - *weight= WEIGHT_PAD_SPACE; - return 0; - } - -#ifdef IS_MB1_CHAR - if (IS_MB1_CHAR(*str)) - { - *weight= WEIGHT_MB1(*str); /* A valid single byte character*/ - return 1; - } -#endif - -#ifdef IS_MB1_MBHEAD_UNUSED_GAP - /* - Quickly filter out unused bytes that are neither MB1 nor MBHEAD. - E.g. [0x80..0xC1] in utf8. This allows using simplified conditions - in IS_MB2_CHAR(), IS_MB3_CHAR(), etc. - */ - if (IS_MB1_MBHEAD_UNUSED_GAP(*str)) - goto bad; -#endif - -#ifdef IS_MB2_CHAR - if (str + 2 > end) /* The string ended unexpectedly */ - goto bad; /* Treat as a bad byte */ - - if (IS_MB2_CHAR(str[0], str[1])) - { - *weight= WEIGHT_MB2(str[0], str[1]); - return 2; /* A valid two-byte character */ - } -#endif - -#ifdef IS_MB3_CHAR - if (str + 3 > end) /* Incomplete three-byte character */ - goto bad; - - if (IS_MB3_CHAR(str[0], str[1], str[2])) - { - *weight= WEIGHT_MB3(str[0], str[1], str[2]); - return 3; /* A valid three-byte character */ - } -#endif - -#ifdef IS_MB4_CHAR - if (str + 4 > end) /* Incomplete four-byte character */ - goto bad; - - if (IS_MB4_CHAR(str[0], str[1], str[2], str[3])) - { - *weight= WEIGHT_MB4(str[0], str[1], str[2], str[3]); - return 4; /* A valid four-byte character */ - } - -#endif - -bad: - *weight= WEIGHT_ILSEQ(str[0]); /* Bad byte */ - return 1; -} - - -/** - Compare two strings according to the collation, - without handling the PAD SPACE property. - - Note, cs->coll->strnncoll() is usually used to compare identifiers. - Perhaps we should eventually (in 10.2?) create a new collation - my_charset_utf8_general_ci_no_pad and have only one comparison function - in MY_COLLATION_HANDLER. - - @param cs - the character set and collation - @param a - the left string - @param a_length - the length of the left string - @param b - the right string - @param b_length - the length of the right string - @param b_is_prefix - if the caller wants to check if "b" is a prefix of "a" - @return - the comparison result -*/ -static int -MY_FUNCTION_NAME(strnncoll)(CHARSET_INFO *cs __attribute__((unused)), - const uchar *a, size_t a_length, - const uchar *b, size_t b_length, - my_bool b_is_prefix) -{ - const uchar *a_end= a + a_length; - const uchar *b_end= b + b_length; - for ( ; ; ) - { - int a_weight, b_weight, res; - uint a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end); - uint b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end); - /* - a_wlen b_wlen Comment - ------ ------ ------- - 0 0 Strings ended simultaneously, "a" and "b" are equal. - 0 >0 "a" is a prefix of "b", so "a" is smaller. - >0 0 "b" is a prefix of "a", check b_is_prefix. - >0 >0 Two weights were scanned, check weight difference. - */ - if (!a_wlen) - return b_wlen ? -b_weight : 0; - - if (!b_wlen) - return b_is_prefix ? 0 : a_weight; - - if ((res= (a_weight - b_weight))) - return res; - /* - None of the strings has ended yet. - */ - DBUG_ASSERT(a < a_end); - DBUG_ASSERT(b < b_end); - a+= a_wlen; - b+= b_wlen; - } - DBUG_ASSERT(0); - return 0; -} - - -#ifdef DEFINE_STRNNCOLLSP_NOPAD - -/** - Compare two strings according to the collation, with NO PAD handling. - - @param cs - the character set and collation - @param a - the left string - @param a_length - the length of the left string - @param b - the right string - @param b_length - the length of the right string - @return - the comparison result -*/ -static int -MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), - const uchar *a, size_t a_length, - const uchar *b, size_t b_length) -{ - return MY_FUNCTION_NAME(strnncoll)(cs, a, a_length, b, b_length, FALSE); -} -#else -/** - Compare two strings according to the collation, with PAD SPACE handling. - - @param cs - the character set and collation - @param a - the left string - @param a_length - the length of the left string - @param b - the right string - @param b_length - the length of the right string - @return - the comparison result -*/ -static int -MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), - const uchar *a, size_t a_length, - const uchar *b, size_t b_length) -{ - const uchar *a_end= a + a_length; - const uchar *b_end= b + b_length; - for ( ; ; ) - { - int a_weight, b_weight, res; - uint a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end); - uint b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end); - if ((res= (a_weight - b_weight))) - { - /* - Got two different weights. Each weight can be generated by either of: - - a real character - - a bad byte sequence or an incomplete byte sequence - - an auto-generated trailing space (PAD SPACE) - It does not matter how exactly each weight was generated. - Just return the weight difference. - */ - return res; - } - if (!a_wlen && !b_wlen) - { - /* - Got two auto-generated trailing spaces, i.e. - both strings have now ended, so they are equal. - */ - DBUG_ASSERT(a == a_end); - DBUG_ASSERT(b == b_end); - return 0; - } - /* - At least one of the strings has not ended yet, continue comparison. - */ - DBUG_ASSERT(a < a_end || b < b_end); - a+= a_wlen; - b+= b_wlen; - } - DBUG_ASSERT(0); - return 0; -} -#endif - - -#ifdef DEFINE_STRNXFRM -#ifndef WEIGHT_MB2_FRM -#define WEIGHT_MB2_FRM(x,y) WEIGHT_MB2(x,y) -#endif - -static size_t -MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *d0= dst; - uchar *de= dst + dstlen; - const uchar *se= src + srclen; - const uchar *sort_order= cs->sort_order; - - for (; dst < de && src < se && nweights; nweights--) - { - if (my_charlen(cs, (const char *) src, (const char *) se) > 1) - { - /* - Note, it is safe not to check (src < se) - in the code below, because my_charlen() would - not return 2 if src was too short - */ - uint16 e= WEIGHT_MB2_FRM(src[0], src[1]); - *dst++= (uchar) (e >> 8); - if (dst < de) - *dst++= (uchar) (e & 0xFF); - src+= 2; - } - else - *dst++= sort_order ? sort_order[*src++] : *src++; - } -#ifdef DEFINE_STRNNCOLLSP_NOPAD - return my_strxfrm_pad_desc_and_reverse_nopad(cs, d0, dst, de, - nweights, flags, 0); -#else - return my_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0); -#endif -} -#endif /* DEFINE_STRNXFRM */ - - -/* - We usually include this file at least two times from the same source file, - for the _ci and the _bin collations. Prepare for the second inclusion. -*/ -#undef MY_FUNCTION_NAME -#undef WEIGHT_ILSEQ -#undef WEIGHT_MB1 -#undef WEIGHT_MB2 -#undef WEIGHT_MB3 -#undef WEIGHT_MB4 -#undef WEIGHT_PAD_SPACE -#undef WEIGHT_MB2_FRM -#undef DEFINE_STRNXFRM -#undef DEFINE_STRNNCOLLSP_NOPAD diff --git a/strings/strcoll.inl b/strings/strcoll.inl new file mode 100644 index 00000000000..eb5b3d5fe9b --- /dev/null +++ b/strings/strcoll.inl @@ -0,0 +1,338 @@ +/* + Copyright (c) 2015, MariaDB Foundation + + 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-1335 USA +*/ + + +#ifndef MY_FUNCTION_NAME +#error MY_FUNCTION_NAME is not defined +#endif + + +/* + The weight for automatically padded spaces when comparing strings with + the PAD SPACE property. + Should normally be equal to the weight of a regular space. +*/ +#ifndef WEIGHT_PAD_SPACE +#define WEIGHT_PAD_SPACE (' ') +#endif + + +/* + Weight of an illegal byte, must follow these rules: + 1. Must be greater than weight of any normal character in the collation. + 2. Two different bad bytes must have different weights and must be + compared in their binary order. + + Depends on mbmaxlen of the character set, as well as how the collation + sorts various single-byte and multi-byte character blocks. + + The macro below is the default definition, it is suitable for mbmaxlen=2 + character sets that sort all multi-byte characters after all single-byte + characters: big5, euckr, gb2312, gbk. + + All mbmaxlen>2 character sets must provide their own definitions. + All collations that have a more complex order (than just MB1 followed by MB2) + must also provide their own definitions (see definitions for + cp932_japanese_ci and sjis_japanese_ci as examples of a more complex order). +*/ +#ifndef WEIGHT_ILSEQ +#define WEIGHT_ILSEQ(x) (0xFF00 + (x)) +#endif + + +/** + Scan a valid character, or a bad byte, or an auto-padded space + from a string and calculate the weight of the scanned sequence. + + @param [OUT] weight - the weight is returned here + @param str - the string + @param end - the end of the string + @return - the number of bytes scanned + + The including source file must define the following macros: + IS_MB1_CHAR(b0) - for character sets that have MB1 characters + IS_MB1_MB2HEAD_GAP(b0) - optional, for better performance + IS_MB2_CHAR(b0,b1) - for character sets that have MB2 characters + IS_MB3_CHAR(b0,b1,b2) - for character sets that have MB3 characters + IS_MB4_CHAR(b0,b1,b2,b3) - for character sets with have MB4 characters + WEIGHT_PAD_SPACE + WEIGHT_MB1(b0) - for character sets that have MB1 characters + WEIGHT_MB2(b0,b1) - for character sets that have MB2 characters + WEIGHT_MB3(b0,b1,b2) - for character sets that have MB3 characters + WEIGHT_MB4(b0,b1,b2,b3) - for character sets that have MB4 characters + WEIGHT_ILSEQ(x) +*/ +static inline uint +MY_FUNCTION_NAME(scan_weight)(int *weight, const uchar *str, const uchar *end) +{ + if (str >= end) + { + *weight= WEIGHT_PAD_SPACE; + return 0; + } + +#ifdef IS_MB1_CHAR + if (IS_MB1_CHAR(*str)) + { + *weight= WEIGHT_MB1(*str); /* A valid single byte character*/ + return 1; + } +#endif + +#ifdef IS_MB1_MBHEAD_UNUSED_GAP + /* + Quickly filter out unused bytes that are neither MB1 nor MBHEAD. + E.g. [0x80..0xC1] in utf8. This allows using simplified conditions + in IS_MB2_CHAR(), IS_MB3_CHAR(), etc. + */ + if (IS_MB1_MBHEAD_UNUSED_GAP(*str)) + goto bad; +#endif + +#ifdef IS_MB2_CHAR + if (str + 2 > end) /* The string ended unexpectedly */ + goto bad; /* Treat as a bad byte */ + + if (IS_MB2_CHAR(str[0], str[1])) + { + *weight= WEIGHT_MB2(str[0], str[1]); + return 2; /* A valid two-byte character */ + } +#endif + +#ifdef IS_MB3_CHAR + if (str + 3 > end) /* Incomplete three-byte character */ + goto bad; + + if (IS_MB3_CHAR(str[0], str[1], str[2])) + { + *weight= WEIGHT_MB3(str[0], str[1], str[2]); + return 3; /* A valid three-byte character */ + } +#endif + +#ifdef IS_MB4_CHAR + if (str + 4 > end) /* Incomplete four-byte character */ + goto bad; + + if (IS_MB4_CHAR(str[0], str[1], str[2], str[3])) + { + *weight= WEIGHT_MB4(str[0], str[1], str[2], str[3]); + return 4; /* A valid four-byte character */ + } + +#endif + +bad: + *weight= WEIGHT_ILSEQ(str[0]); /* Bad byte */ + return 1; +} + + +/** + Compare two strings according to the collation, + without handling the PAD SPACE property. + + Note, cs->coll->strnncoll() is usually used to compare identifiers. + Perhaps we should eventually (in 10.2?) create a new collation + my_charset_utf8_general_ci_no_pad and have only one comparison function + in MY_COLLATION_HANDLER. + + @param cs - the character set and collation + @param a - the left string + @param a_length - the length of the left string + @param b - the right string + @param b_length - the length of the right string + @param b_is_prefix - if the caller wants to check if "b" is a prefix of "a" + @return - the comparison result +*/ +static int +MY_FUNCTION_NAME(strnncoll)(CHARSET_INFO *cs __attribute__((unused)), + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + my_bool b_is_prefix) +{ + const uchar *a_end= a + a_length; + const uchar *b_end= b + b_length; + for ( ; ; ) + { + int a_weight, b_weight, res; + uint a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end); + uint b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end); + /* + a_wlen b_wlen Comment + ------ ------ ------- + 0 0 Strings ended simultaneously, "a" and "b" are equal. + 0 >0 "a" is a prefix of "b", so "a" is smaller. + >0 0 "b" is a prefix of "a", check b_is_prefix. + >0 >0 Two weights were scanned, check weight difference. + */ + if (!a_wlen) + return b_wlen ? -b_weight : 0; + + if (!b_wlen) + return b_is_prefix ? 0 : a_weight; + + if ((res= (a_weight - b_weight))) + return res; + /* + None of the strings has ended yet. + */ + DBUG_ASSERT(a < a_end); + DBUG_ASSERT(b < b_end); + a+= a_wlen; + b+= b_wlen; + } + DBUG_ASSERT(0); + return 0; +} + + +#ifdef DEFINE_STRNNCOLLSP_NOPAD + +/** + Compare two strings according to the collation, with NO PAD handling. + + @param cs - the character set and collation + @param a - the left string + @param a_length - the length of the left string + @param b - the right string + @param b_length - the length of the right string + @return - the comparison result +*/ +static int +MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), + const uchar *a, size_t a_length, + const uchar *b, size_t b_length) +{ + return MY_FUNCTION_NAME(strnncoll)(cs, a, a_length, b, b_length, FALSE); +} +#else +/** + Compare two strings according to the collation, with PAD SPACE handling. + + @param cs - the character set and collation + @param a - the left string + @param a_length - the length of the left string + @param b - the right string + @param b_length - the length of the right string + @return - the comparison result +*/ +static int +MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), + const uchar *a, size_t a_length, + const uchar *b, size_t b_length) +{ + const uchar *a_end= a + a_length; + const uchar *b_end= b + b_length; + for ( ; ; ) + { + int a_weight, b_weight, res; + uint a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end); + uint b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end); + if ((res= (a_weight - b_weight))) + { + /* + Got two different weights. Each weight can be generated by either of: + - a real character + - a bad byte sequence or an incomplete byte sequence + - an auto-generated trailing space (PAD SPACE) + It does not matter how exactly each weight was generated. + Just return the weight difference. + */ + return res; + } + if (!a_wlen && !b_wlen) + { + /* + Got two auto-generated trailing spaces, i.e. + both strings have now ended, so they are equal. + */ + DBUG_ASSERT(a == a_end); + DBUG_ASSERT(b == b_end); + return 0; + } + /* + At least one of the strings has not ended yet, continue comparison. + */ + DBUG_ASSERT(a < a_end || b < b_end); + a+= a_wlen; + b+= b_wlen; + } + DBUG_ASSERT(0); + return 0; +} +#endif + + +#ifdef DEFINE_STRNXFRM +#ifndef WEIGHT_MB2_FRM +#define WEIGHT_MB2_FRM(x,y) WEIGHT_MB2(x,y) +#endif + +static size_t +MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *d0= dst; + uchar *de= dst + dstlen; + const uchar *se= src + srclen; + const uchar *sort_order= cs->sort_order; + + for (; dst < de && src < se && nweights; nweights--) + { + if (my_charlen(cs, (const char *) src, (const char *) se) > 1) + { + /* + Note, it is safe not to check (src < se) + in the code below, because my_charlen() would + not return 2 if src was too short + */ + uint16 e= WEIGHT_MB2_FRM(src[0], src[1]); + *dst++= (uchar) (e >> 8); + if (dst < de) + *dst++= (uchar) (e & 0xFF); + src+= 2; + } + else + *dst++= sort_order ? sort_order[*src++] : *src++; + } +#ifdef DEFINE_STRNNCOLLSP_NOPAD + return my_strxfrm_pad_desc_and_reverse_nopad(cs, d0, dst, de, + nweights, flags, 0); +#else + return my_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0); +#endif +} +#endif /* DEFINE_STRNXFRM */ + + +/* + We usually include this file at least two times from the same source file, + for the _ci and the _bin collations. Prepare for the second inclusion. +*/ +#undef MY_FUNCTION_NAME +#undef WEIGHT_ILSEQ +#undef WEIGHT_MB1 +#undef WEIGHT_MB2 +#undef WEIGHT_MB3 +#undef WEIGHT_MB4 +#undef WEIGHT_PAD_SPACE +#undef WEIGHT_MB2_FRM +#undef DEFINE_STRNXFRM +#undef DEFINE_STRNNCOLLSP_NOPAD -- cgit v1.2.1 From bf9bc991066df78a37e917127d61d044700c3950 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 18 Jan 2022 15:32:01 +0400 Subject: MDEV-26129 Bad results with join comparing case insensitive VARCHAR/ENUM/SET expression to a _bin ENUM column Range optimizer incorrectly was used for ENUM columns when the operation collation did not match the column collation. Adding a virtual implementation of Field_enum::can_optimize_range() which tests if the column and the operation collation match. --- mysql-test/r/type_enum.result | 21 +++++++++++++++++++++ mysql-test/t/type_enum.test | 20 ++++++++++++++++++++ sql/field.cc | 4 ++-- sql/field.h | 13 ++++++++++++- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result index 6ad75339847..c99e18ed109 100644 --- a/mysql-test/r/type_enum.result +++ b/mysql-test/r/type_enum.result @@ -2219,3 +2219,24 @@ SELECT * FROM t1; a DROP TABLE t1; +# +# MDEV-26129 Bad results with join comparing case insensitive VARCHAR/ENUM/SET expression to a _bin ENUM column +# +CREATE TABLE t1 (a ENUM('a') CHARACTER SET latin1 PRIMARY KEY); +INSERT INTO t1 VALUES ('a'); +CREATE TABLE t2 (a ENUM('a','A','b','B','c','C','d','D','e','E') CHARACTER SET latin1 COLLATE latin1_bin); +INSERT INTO t2 VALUES ('a'),('A'); +INSERT INTO t2 VALUES ('b'),('B'),('c'),('C'),('d'),('D'),('e'),('E'); +ALTER TABLE t2 ADD PRIMARY KEY(a); +SELECT t1.a res FROM t1 JOIN t2 ON t1.a COLLATE latin1_swedish_ci=t2.a; +res +a +a +SELECT t1.a res FROM t1 LEFT JOIN t2 ON t1.a COLLATE latin1_swedish_ci=t2.a; +res +a +a +DROP TABLE IF EXISTS t1,t2; +# +# End of 10.2. tests +# diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test index 105da427219..2576b87ee51 100644 --- a/mysql-test/t/type_enum.test +++ b/mysql-test/t/type_enum.test @@ -454,3 +454,23 @@ SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR ALTER TABLE t1 MODIFY a ENUM('2001','2002'); SELECT * FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-26129 Bad results with join comparing case insensitive VARCHAR/ENUM/SET expression to a _bin ENUM column +--echo # + +CREATE TABLE t1 (a ENUM('a') CHARACTER SET latin1 PRIMARY KEY); +INSERT INTO t1 VALUES ('a'); +CREATE TABLE t2 (a ENUM('a','A','b','B','c','C','d','D','e','E') CHARACTER SET latin1 COLLATE latin1_bin); +INSERT INTO t2 VALUES ('a'),('A'); +# without the following insert the bug doesn't show, was fixed in MDEV-6978 +INSERT INTO t2 VALUES ('b'),('B'),('c'),('C'),('d'),('D'),('e'),('E'); +ALTER TABLE t2 ADD PRIMARY KEY(a); +SELECT t1.a res FROM t1 JOIN t2 ON t1.a COLLATE latin1_swedish_ci=t2.a; +SELECT t1.a res FROM t1 LEFT JOIN t2 ON t1.a COLLATE latin1_swedish_ci=t2.a; +DROP TABLE IF EXISTS t1,t2; + + +--echo # +--echo # End of 10.2. tests +--echo # diff --git a/sql/field.cc b/sql/field.cc index 4e6bc6b8341..74317a4d70b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9484,8 +9484,8 @@ uint Field_num::is_equal(Create_field *new_field) } -bool Field_enum::can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const +bool Field_enum::can_optimize_range_or_keypart_ref(const Item_bool_func *cond, + const Item *item) const { DBUG_ASSERT(cmp_type() == INT_RESULT); DBUG_ASSERT(result_type() == STRING_RESULT); diff --git a/sql/field.h b/sql/field.h index 6d8e2aecd6e..78b6dcb516b 100644 --- a/sql/field.h +++ b/sql/field.h @@ -3623,6 +3623,8 @@ uint gis_field_options_read(const uchar *buf, uint buf_len, class Field_enum :public Field_str { static void do_field_enum(Copy_field *copy_field); + bool can_optimize_range_or_keypart_ref(const Item_bool_func *cond, + const Item *item) const; protected: uint packlength; public: @@ -3700,7 +3702,10 @@ public: const uchar *from_end, uint param_data); bool can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const; + const Item *item) const + { + return can_optimize_range_or_keypart_ref(cond, item); + } bool can_optimize_group_min_max(const Item_bool_func *cond, const Item *const_item) const { @@ -3713,6 +3718,12 @@ public: */ return false; } + bool can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const + { + return can_optimize_range_or_keypart_ref(cond, item); + } private: int do_save_field_metadata(uchar *first_byte); uint is_equal(Create_field *new_field); -- cgit v1.2.1 From 4db6e86ebec7213b294df395299772430d1b0e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 18 Jan 2022 18:16:10 +0200 Subject: MDEV-27539 Merge new release of InnoDB 5.7.37 to 10.2 There were no InnoDB changes in the MySQL 5.7.37 release that would be relevant to MariaDB Server. We will merely update the reported InnoDB version number. --- storage/innobase/include/univ.i | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index fb1f5b705aa..92466ff595d 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -41,7 +41,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 7 -#define INNODB_VERSION_BUGFIX 36 +#define INNODB_VERSION_BUGFIX 37 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; -- cgit v1.2.1 From 410c4edef30b3ac061f21aa712020a51337cff56 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 18 Jan 2022 13:56:15 +1100 Subject: MDEV-27467: innodb to enforce the minimum innodb_buffer_pool_size in SET GLOBAL .. to be the same as startup. In resolving MDEV-27461, BUF_LRU_MIN_LEN (256) is the minimum number of pages for the innodb buffer pool size. Obviously we need more than just flushing pages. Taking the 16k page size and its default minimum, an extra 25% is needed on top of the flushing pages to make a workable buffer pool. The minimum innodb_buffer_pool_chunk_size (1M) restricts the minimum otherwise we'd have a pool made up of different chunk sizes. The resulting minimum innodb buffer pool sizes are: Page Size, Previously minimum (startup), with change. 4k 5M 2M 8k 5M 3M 16k 5M 5M 32k 24M 10M 64k 24M 20M With this patch, SET GLOBAL innodb_buffer_pool_size minimums are enforced. The evident minimum system variable size for innodb_buffer_pool_size is 2M, however this is only setable if using 4k page size. As the order of the page_size and buffer_pool_size aren't fixed, we can't hide this change. Subsequent changes: * innodb_buffer_pool_resize_with_chunks.test - raised of pool resize due to new minimums. Chunk size also needed increase as the test was for pool_size < chunk_size to generate a warning. * Removed srv_buf_pool_min_size and replaced use with MYSQL_SYSVAR_NAME(buffer_pool_size).min_val * Removed srv_buf_pool_def_size and replaced constant defination in MYSQL_SYSVAR_LONGLONG(buffer_pool_size) * Reordered ha_innodb to allow for direct use of MYSQL_SYSVAR_NAME(buffer_pool_size).min_val * Moved buf_pool_size_align into ha_innodb to access to MYSQL_SYSVAR_NAME(buffer_pool_size).min_val * loose-innodb_disable_resize_buffer_pool_debug is needed in the innodb.restart.opt test so that under debug mode, resizing of the innodb buffer pool can occur. --- .../r/innodb_buffer_pool_resize_with_chunks.result | 8 +- mysql-test/suite/innodb/r/restart,16k,innodb.rdiff | 16 +++ mysql-test/suite/innodb/r/restart,32k,innodb.rdiff | 16 +++ mysql-test/suite/innodb/r/restart,4k,innodb.rdiff | 16 +++ mysql-test/suite/innodb/r/restart,64k,innodb.rdiff | 16 +++ mysql-test/suite/innodb/r/restart,8k,innodb.rdiff | 16 +++ mysql-test/suite/innodb/r/restart.result | 13 +++ .../t/innodb_buffer_pool_resize_with_chunks.opt | 2 +- .../t/innodb_buffer_pool_resize_with_chunks.test | 2 +- mysql-test/suite/innodb/t/restart.opt | 2 + mysql-test/suite/innodb/t/restart.test | 23 ++++ mysql-test/suite/sys_vars/r/sysvars_innodb.result | 2 +- storage/innobase/buf/buf0flu.cc | 6 - storage/innobase/handler/ha_innodb.cc | 125 +++++++++++++++------ storage/innobase/include/buf0buf.h | 7 +- storage/innobase/include/buf0buf.inl | 19 ---- storage/innobase/include/srv0srv.h | 4 - storage/innobase/srv/srv0srv.cc | 3 - 18 files changed, 220 insertions(+), 76 deletions(-) create mode 100644 mysql-test/suite/innodb/r/restart,16k,innodb.rdiff create mode 100644 mysql-test/suite/innodb/r/restart,32k,innodb.rdiff create mode 100644 mysql-test/suite/innodb/r/restart,4k,innodb.rdiff create mode 100644 mysql-test/suite/innodb/r/restart,64k,innodb.rdiff create mode 100644 mysql-test/suite/innodb/r/restart,8k,innodb.rdiff create mode 100644 mysql-test/suite/innodb/t/restart.opt diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_with_chunks.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_with_chunks.result index 4bf244c9588..efb652091bf 100644 --- a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_with_chunks.result +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_with_chunks.result @@ -1,6 +1,6 @@ select @@innodb_buffer_pool_chunk_size; @@innodb_buffer_pool_chunk_size -2097152 +4194304 create table t1 (id int not null, val int not null default '0', primary key (id)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; create or replace view view0 as select 1 union all select 1; set @`v_id` := 0; @@ -18,9 +18,9 @@ count(val) 262144 drop table t1; drop view view0; -set global innodb_buffer_pool_size = 1048576; +set global innodb_buffer_pool_size = 2*1048576; Warnings: -Warning 1292 Truncated incorrect innodb_buffer_pool_size value: '1048576' +Warning 1292 Truncated incorrect innodb_buffer_pool_size value: '2097152' select @@innodb_buffer_pool_size; @@innodb_buffer_pool_size -6291456 +4194304 diff --git a/mysql-test/suite/innodb/r/restart,16k,innodb.rdiff b/mysql-test/suite/innodb/r/restart,16k,innodb.rdiff new file mode 100644 index 00000000000..b36ed067913 --- /dev/null +++ b/mysql-test/suite/innodb/r/restart,16k,innodb.rdiff @@ -0,0 +1,16 @@ +--- ./suite/innodb/r/restart.result 2022-01-18 20:36:56.054653376 +1100 ++++ suite/innodb/r/restart.reject 2022-01-19 08:12:28.602794678 +1100 +@@ -32,10 +32,10 @@ + SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig; + SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size; + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1); +-ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of '5242879' + SHOW WARNINGS; + Level Code Message +-Warning 1210 innodb_buffer_pool_size must be at least MIN_VAL for innodb_page_size=PAGE_SIZE +-Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++Warning 1210 innodb_buffer_pool_size must be at least 5242880 for innodb_page_size=16384 ++Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of '5242879' + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size); + SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig; diff --git a/mysql-test/suite/innodb/r/restart,32k,innodb.rdiff b/mysql-test/suite/innodb/r/restart,32k,innodb.rdiff new file mode 100644 index 00000000000..8fa057814c4 --- /dev/null +++ b/mysql-test/suite/innodb/r/restart,32k,innodb.rdiff @@ -0,0 +1,16 @@ +--- ./suite/innodb/r/restart.result 2022-01-18 20:36:56.054653376 +1100 ++++ suite/innodb/r/restart.reject 2022-01-19 08:07:57.402230887 +1100 +@@ -32,10 +32,10 @@ + SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig; + SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size; + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1); +-ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of '10485759' + SHOW WARNINGS; + Level Code Message +-Warning 1210 innodb_buffer_pool_size must be at least MIN_VAL for innodb_page_size=PAGE_SIZE +-Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++Warning 1210 innodb_buffer_pool_size must be at least 10485760 for innodb_page_size=32768 ++Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of '10485759' + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size); + SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig; diff --git a/mysql-test/suite/innodb/r/restart,4k,innodb.rdiff b/mysql-test/suite/innodb/r/restart,4k,innodb.rdiff new file mode 100644 index 00000000000..7d0846360e0 --- /dev/null +++ b/mysql-test/suite/innodb/r/restart,4k,innodb.rdiff @@ -0,0 +1,16 @@ +--- ./suite/innodb/r/restart.result 2022-01-18 20:36:56.054653376 +1100 ++++ suite/innodb/r/restart.reject 2022-01-19 08:13:56.397475513 +1100 +@@ -32,10 +32,10 @@ + SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig; + SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size; + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1); +-ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of '2097151' + SHOW WARNINGS; + Level Code Message +-Warning 1210 innodb_buffer_pool_size must be at least MIN_VAL for innodb_page_size=PAGE_SIZE +-Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++Warning 1210 innodb_buffer_pool_size must be at least 2097152 for innodb_page_size=4096 ++Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of '2097151' + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size); + SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig; diff --git a/mysql-test/suite/innodb/r/restart,64k,innodb.rdiff b/mysql-test/suite/innodb/r/restart,64k,innodb.rdiff new file mode 100644 index 00000000000..3ac9f45b196 --- /dev/null +++ b/mysql-test/suite/innodb/r/restart,64k,innodb.rdiff @@ -0,0 +1,16 @@ +--- ./suite/innodb/r/restart.result 2022-01-18 20:36:56.054653376 +1100 ++++ suite/innodb/r/restart.reject 2022-01-19 08:11:32.418759095 +1100 +@@ -32,10 +32,10 @@ + SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig; + SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size; + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1); +-ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of '20971519' + SHOW WARNINGS; + Level Code Message +-Warning 1210 innodb_buffer_pool_size must be at least MIN_VAL for innodb_page_size=PAGE_SIZE +-Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++Warning 1210 innodb_buffer_pool_size must be at least 20971520 for innodb_page_size=65536 ++Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of '20971519' + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size); + SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig; diff --git a/mysql-test/suite/innodb/r/restart,8k,innodb.rdiff b/mysql-test/suite/innodb/r/restart,8k,innodb.rdiff new file mode 100644 index 00000000000..4da55ebfcef --- /dev/null +++ b/mysql-test/suite/innodb/r/restart,8k,innodb.rdiff @@ -0,0 +1,16 @@ +--- ./suite/innodb/r/restart.result 2022-01-18 20:36:56.054653376 +1100 ++++ suite/innodb/r/restart.reject 2022-01-19 08:13:11.027788852 +1100 +@@ -32,10 +32,10 @@ + SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig; + SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size; + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1); +-ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of '3145727' + SHOW WARNINGS; + Level Code Message +-Warning 1210 innodb_buffer_pool_size must be at least MIN_VAL for innodb_page_size=PAGE_SIZE +-Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' ++Warning 1210 innodb_buffer_pool_size must be at least 3145728 for innodb_page_size=8192 ++Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of '3145727' + EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size); + SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig; diff --git a/mysql-test/suite/innodb/r/restart.result b/mysql-test/suite/innodb/r/restart.result index 5e3315be204..606e94d81db 100644 --- a/mysql-test/suite/innodb/r/restart.result +++ b/mysql-test/suite/innodb/r/restart.result @@ -26,3 +26,16 @@ a SELECT * FROM td; a DROP TABLE tr,tc,td; +# +# MDEV-27467 innodb to enfore the minimum innodb_buffer_pool_size in SET (resize) the same as startup +# +SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig; +SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size; +EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1); +ERROR 42000: Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' +SHOW WARNINGS; +Level Code Message +Warning 1210 innodb_buffer_pool_size must be at least MIN_VAL for innodb_page_size=PAGE_SIZE +Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE' +EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size); +SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig; diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.opt b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.opt index b97a3995457..ade197de338 100644 --- a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.opt +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.opt @@ -1,3 +1,3 @@ --innodb-buffer-pool-size=16M ---innodb-buffer-pool-chunk-size=2M +--innodb-buffer-pool-chunk-size=4M --innodb-page-size=4k diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.test index b04b0306bf1..7a26db65d33 100644 --- a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.test +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.test @@ -49,7 +49,7 @@ drop table t1; drop view view0; # Try to shrink buffer pool to smaller than chunk size -set global innodb_buffer_pool_size = 1048576; +set global innodb_buffer_pool_size = 2*1048576; --source include/wait_condition.inc select @@innodb_buffer_pool_size; diff --git a/mysql-test/suite/innodb/t/restart.opt b/mysql-test/suite/innodb/t/restart.opt new file mode 100644 index 00000000000..ce43e89cb2b --- /dev/null +++ b/mysql-test/suite/innodb/t/restart.opt @@ -0,0 +1,2 @@ +--loose-innodb_disable_resize_buffer_pool_debug=0 +--innodb-buffer-pool-chunk-size=1M diff --git a/mysql-test/suite/innodb/t/restart.test b/mysql-test/suite/innodb/t/restart.test index d7582306492..3f28b3976c3 100644 --- a/mysql-test/suite/innodb/t/restart.test +++ b/mysql-test/suite/innodb/t/restart.test @@ -77,3 +77,26 @@ SELECT * FROM tr; SELECT * FROM tc; SELECT * FROM td; DROP TABLE tr,tc,td; + +--echo # +--echo # MDEV-27467 innodb to enfore the minimum innodb_buffer_pool_size in SET (resize) the same as startup +--echo # + +let $wait_timeout = 180; +let $wait_condition = + SELECT SUBSTR(variable_value, 1, 34) = 'Completed resizing buffer pool at ' + FROM information_schema.global_status + WHERE LOWER(variable_name) = 'innodb_buffer_pool_resize_status'; + +SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig; +SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size; +--error ER_WRONG_VALUE_FOR_VAR +EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1); + +SHOW WARNINGS; + +EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size); + +--source include/wait_condition.inc + +SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig; diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index ecc5e9b50bb..a1a59425502 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -300,7 +300,7 @@ DEFAULT_VALUE 134217728 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT VARIABLE_COMMENT The size of the memory buffer InnoDB uses to cache data and indexes of its tables. -NUMERIC_MIN_VALUE 5242880 +NUMERIC_MIN_VALUE 2097152 NUMERIC_MAX_VALUE 9223372036854775807 NUMERIC_BLOCK_SIZE 1048576 ENUM_VALUE_LIST NULL diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 26610337d0d..2beddf4b243 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -191,12 +191,6 @@ static page_cleaner_t page_cleaner; my_bool innodb_page_cleaner_disabled_debug; #endif /* UNIV_DEBUG */ -/** If LRU list of a buf_pool is less than this size then LRU eviction -should not happen. This is because when we do LRU flushing we also put -the blocks on free list. If LRU list is very small then we can end up -in thrashing. */ -#define BUF_LRU_MIN_LEN 256 - /* @} */ /******************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 8fb52b211c6..5d78e64a06b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3639,6 +3639,59 @@ static uint innobase_partition_flags() return (0); } +/** Return the minimum buffer pool size based on page size */ +static inline ulint min_buffer_pool_size() +{ + ulint s= (BUF_LRU_MIN_LEN + BUF_LRU_MIN_LEN / 4) * srv_page_size; + /* buf_pool_chunk_size minimum is 1M, so round up to a multiple */ + ulint alignment= 1U << 20; + return UT_CALC_ALIGN(s, alignment); +} + +/** Validate the requested buffer pool size. Also, reserve the necessary +memory needed for buffer pool resize. +@param[in] thd thread handle +@param[in] var pointer to system variable +@param[out] save immediate result for update function +@param[in] value incoming string +@return 0 on success, 1 on failure. +*/ +static +int +innodb_buffer_pool_size_validate( + THD* thd, + struct st_mysql_sys_var* var, + void* save, + struct st_mysql_value* value); + +/** Update the system variable innodb_buffer_pool_size using the "saved" +value. This function is registered as a callback with MySQL. +@param[in] thd thread handle +@param[in] var pointer to system variable +@param[out] var_ptr where the formal string goes +@param[in] save immediate result from check function */ +static +void +innodb_buffer_pool_size_update( + THD* thd, + struct st_mysql_sys_var* var, + void* var_ptr, + const void* save); + +/* If the default value of innodb_buffer_pool_size is increased to be more than +BUF_POOL_SIZE_THRESHOLD (srv/srv0start.cc), then srv_buf_pool_instances_default +can be removed and 8 used instead. The problem with the current setup is that +with 128MiB default buffer pool size and 8 instances by default we would emit +a warning when no options are specified. */ +static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, + PLUGIN_VAR_RQCMDARG, + "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", + innodb_buffer_pool_size_validate, + innodb_buffer_pool_size_update, + 128LL << 20, + 2LL << 20, + LLONG_MAX, 1024*1024L); + /** Deprecation message about InnoDB file format related parameters */ #define DEPRECATED_FORMAT_PARAMETER(x) \ "Using " x " is deprecated and the parameter" \ @@ -3830,12 +3883,15 @@ innobase_init( /* The buffer pool needs to be able to accommodate enough many pages, even for larger pages */ - if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF - && innobase_buffer_pool_size < (24 * 1024 * 1024)) { + MYSQL_SYSVAR_NAME(buffer_pool_size).min_val= min_buffer_pool_size(); + + if (innobase_buffer_pool_size < MYSQL_SYSVAR_NAME(buffer_pool_size).min_val) { ib::error() << "innodb_page_size=" - << UNIV_PAGE_SIZE << " requires " - << "innodb_buffer_pool_size > 24M current " - << innobase_buffer_pool_size; + << srv_page_size << " requires " + << "innodb_buffer_pool_size >= " + << (MYSQL_SYSVAR_NAME(buffer_pool_size).min_val >> 20) + << "MiB current " << (innobase_buffer_pool_size >> 20) + << "MiB"; goto error; } @@ -20314,36 +20370,6 @@ static MYSQL_SYSVAR_ULONG(autoextend_increment, "Data file autoextend increment in megabytes", NULL, NULL, 64L, 1L, 1000L, 0); -/** Validate the requested buffer pool size. Also, reserve the necessary -memory needed for buffer pool resize. -@param[in] thd thread handle -@param[in] var pointer to system variable -@param[out] save immediate result for update function -@param[in] value incoming string -@return 0 on success, 1 on failure. -*/ -static -int -innodb_buffer_pool_size_validate( - THD* thd, - struct st_mysql_sys_var* var, - void* save, - struct st_mysql_value* value); - -/* If the default value of innodb_buffer_pool_size is increased to be more than -BUF_POOL_SIZE_THRESHOLD (srv/srv0start.cc), then srv_buf_pool_instances_default -can be removed and 8 used instead. The problem with the current setup is that -with 128MiB default buffer pool size and 8 instances by default we would emit -a warning when no options are specified. */ -static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, - PLUGIN_VAR_RQCMDARG, - "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", - innodb_buffer_pool_size_validate, - innodb_buffer_pool_size_update, - static_cast(srv_buf_pool_def_size), - static_cast(srv_buf_pool_min_size), - LLONG_MAX, 1024*1024L); - static MYSQL_SYSVAR_ULONG(buffer_pool_chunk_size, srv_buf_pool_chunk_unit, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "Size of a single memory chunk within each buffer pool instance" @@ -22297,9 +22323,18 @@ innodb_buffer_pool_size_validate( { longlong intbuf; - value->val_int(value, &intbuf); + if (intbuf < MYSQL_SYSVAR_NAME(buffer_pool_size).min_val) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "innodb_buffer_pool_size must be at least" + " %lld for innodb_page_size=%lu", + MYSQL_SYSVAR_NAME(buffer_pool_size).min_val, + srv_page_size); + return(1); + } + if (!srv_was_started) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, @@ -22653,3 +22688,21 @@ ib_push_frm_error( break; } } + +/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit, +if needed. +@param[in] size size in bytes +@return aligned size */ +ulint +buf_pool_size_align( + ulint size) +{ + const ib_uint64_t m = ((ib_uint64_t)srv_buf_pool_instances) * srv_buf_pool_chunk_unit; + size = ut_max((size_t) size, (size_t) MYSQL_SYSVAR_NAME(buffer_pool_size).min_val); + + if (size % m == 0) { + return(size); + } else { + return (ulint)((size / m + 1) * m); + } +} diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 20281040862..04824293c95 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -95,6 +95,12 @@ struct fil_addr_t; #define MAX_PAGE_HASH_LOCKS 1024 /*!< The maximum number of page_hash locks */ +/** If LRU list of a buf_pool is less than this size then LRU eviction +should not happen. This is because when we do LRU flushing we also put +the blocks on free list. If LRU list is very small then we can end up +in thrashing. */ +#define BUF_LRU_MIN_LEN 256 + extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools of the database */ @@ -1373,7 +1379,6 @@ buf_get_nth_chunk_block( if needed. @param[in] size size in bytes @return aligned size */ -UNIV_INLINE ulint buf_pool_size_align( ulint size); diff --git a/storage/innobase/include/buf0buf.inl b/storage/innobase/include/buf0buf.inl index 49b741ab5c8..488a4c2f585 100644 --- a/storage/innobase/include/buf0buf.inl +++ b/storage/innobase/include/buf0buf.inl @@ -1457,22 +1457,3 @@ buf_page_get_frame( return ((buf_block_t*) bpage)->frame; } } - -/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit, -if needed. -@param[in] size size in bytes -@return aligned size */ -UNIV_INLINE -ulint -buf_pool_size_align( - ulint size) -{ - const ib_uint64_t m = ((ib_uint64_t)srv_buf_pool_instances) * srv_buf_pool_chunk_unit; - size = ut_max(size, srv_buf_pool_min_size); - - if (size % m == 0) { - return(size); - } else { - return (ulint)((size / m + 1) * m); - } -} diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 62d7c139ee2..cce90e03b9d 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -389,10 +389,6 @@ extern my_bool srv_load_corrupted; /** Requested size in bytes */ extern ulint srv_buf_pool_size; -/** Minimum pool size in bytes */ -extern const ulint srv_buf_pool_min_size; -/** Default pool size in bytes */ -extern const ulint srv_buf_pool_def_size; /** Requested buffer pool chunk size. Each buffer pool instance consists of one or more chunks. */ extern ulong srv_buf_pool_chunk_unit; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 56c717e142b..f993f5f0f83 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -244,9 +244,6 @@ UNIV_INTERN os_event_t srv_allow_writes_event; /** copy of innodb_buffer_pool_size */ ulint srv_buf_pool_size; -const ulint srv_buf_pool_min_size = 5 * 1024 * 1024; -/** Default pool size in bytes */ -const ulint srv_buf_pool_def_size = 128 * 1024 * 1024; /** Requested buffer pool chunk size. Each buffer pool instance consists of one or more chunks. */ ulong srv_buf_pool_chunk_unit; -- cgit v1.2.1 From 9cd6ecfe501bcbee04d2d203baa81c927664c9e2 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Mon, 17 Jan 2022 16:26:47 +0100 Subject: MDEV-18284: JSON casting using JSON_COMPACT doesn't always work with values from subqueries - Cherry-pick 2fcff310d024cc2201586c568391ba8b039f0bf3 (MDEV-21902) - Closed PR #1145 Reviewed by: holyfoot@mariadb.com --- mysql-test/r/func_json.result | 18 ++++++++++++++++++ mysql-test/t/func_json.test | 15 +++++++++++++++ sql/item.h | 1 + 3 files changed, 34 insertions(+) diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index f8e78c79f5d..b0005b13e45 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -940,5 +940,23 @@ SELECT JSON_REPLACE( JSON_DETAILED('["x"]'), '$.a', 'xx' ); JSON_REPLACE( JSON_DETAILED('["x"]'), '$.a', 'xx' ) ["x"] # +# MDEV-18284 JSON casting using JSON_COMPACT doesn't always work +# with values from subqueries +# +CREATE TABLE json_test(a JSON, b JSON); +INSERT INTO json_test VALUES ("[1,2,3]", '{"a":"foo"}'); +SELECT * FROM json_test; +a b +[1,2,3] {"a":"foo"} +SELECT json_object("a", json_compact(a), "b", b) +FROM (SELECT * FROM json_test) AS json_test_values; +json_object("a", json_compact(a), "b", b) +{"a": [1,2,3], "b": "{\"a\":\"foo\"}"} +SELECT json_object("a", json_compact(a), "b", json_compact(b)) +FROM (SELECT * FROM json_test) AS json_test_values; +json_object("a", json_compact(a), "b", json_compact(b)) +{"a": [1,2,3], "b": {"a":"foo"}} +DROP TABLE json_test; +# # End of 10.2 tests # diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index e4e093225f8..aaba3c21315 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -560,6 +560,21 @@ SELECT SELECT JSON_REPLACE( JSON_DETAILED('["x"]'), '$.a', 'xx' ); +--echo # +--echo # MDEV-18284 JSON casting using JSON_COMPACT doesn't always work +--echo # with values from subqueries +--echo # + +CREATE TABLE json_test(a JSON, b JSON); +INSERT INTO json_test VALUES ("[1,2,3]", '{"a":"foo"}'); +SELECT * FROM json_test; + +SELECT json_object("a", json_compact(a), "b", b) + FROM (SELECT * FROM json_test) AS json_test_values; +SELECT json_object("a", json_compact(a), "b", json_compact(b)) + FROM (SELECT * FROM json_test) AS json_test_values; +DROP TABLE json_test; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/item.h b/sql/item.h index 086d85e989f..290ff11a0f8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4564,6 +4564,7 @@ public: { return ref ? (*ref)->real_item() : this; } + bool is_json_type() { return (*ref)->is_json_type(); } bool walk(Item_processor processor, bool walk_subquery, void *arg) { if (ref && *ref) -- cgit v1.2.1 From 810ef9117a54f8dfbd362d959d46a2322f86a9d0 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Wed, 19 Jan 2022 11:15:22 +0700 Subject: MDEV-24827: MariaDB 10.5.5 crash (sig 11) during a SELECT Running a query using cursor could lead to a server crash on building a temporary table used for handling the query. For example, the following cursor DECLARE cur1 CURSOR FOR SELECT t2.c1 AS c1 FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = -1) ORDER BY c1; declared and executed inside a stored routine could result in server crash on creating a temporary table used for handling the ORDER BY clause. Crash occurred on attempt to create the temporary table's fields based on fields whose data located in a memory root that already freed. It happens inside the function return_zero_rows() where the method Select_materialize::send_result_set_metadata() is invoked for cursor case. This method calls the st_select_lex_unit::get_column_types() in order to get a list of items with types of columns for the temporary table being created. The method st_select_lex_unit::get_column_types() returns first_select()->join->fields in case it is invoked for a cursor. Unfortunately, this memory has been already deallocated bit earlier by calling join->join_free(); inside the function return_zero_rows(). In case the query listed in the example is run in conventional way (without using cursor) the method st_select_lex_unit::get_column_types() returns first_select()->item_list that is not touched by invocation of the method join->join_free() so everything is fine for that. So, to fix the issue the resources allocated for the JOIN class should be released after any activities with the JOIN class has been completed, that is as the last statement before returning from the function return_zero_rows(). This patch includes tests both for the case when a cursor is run explicitly from within a stored routine and for the case when a cursor is opened implicitly as prescribed by the STMT_ATTR_CURSOR_TYPE attribute of binary protocol (the case of prepared statement). --- mysql-test/r/sp.result | 28 ++++++++++++++ mysql-test/t/mysql_client_test-master.opt | 1 + mysql-test/t/mysql_client_test_comp-master.opt | 1 + mysql-test/t/sp.test | 42 ++++++++++++++++++++ sql/sql_select.cc | 4 +- tests/mysql_client_test.c | 53 ++++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 25675a11f4a..4a905553fba 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -8501,4 +8501,32 @@ b-c 0 drop procedure p1| drop function f1| +# +# MDEV-24827: MariaDB 10.5.5 crash (sig 11) during a SELECT +# +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT); +CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 INT, KEY idx_c2(c2)); +INSERT INTO t1 (c1, c2) SELECT seq, seq FROM seq_1_to_10000; +INSERT INTO t2 (c1, c2) SELECT seq, seq FROM seq_1_to_20000; +CREATE OR REPLACE PROCEDURE p1() +begin +DECLARE done INT DEFAULT FALSE; +DECLARE a INT; +DECLARE cur1 CURSOR FOR +SELECT t2.c1 AS c1 FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 +WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = -1) ORDER BY c1; +DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; +OPEN cur1; +read_loop: LOOP +FETCH cur1 INTO a; +IF done THEN +LEAVE read_loop; +END IF; +END LOOP; +CLOSE cur1; +END $ +CALL p1(); +DROP PROCEDURE p1; +DROP TABLE t1; +DROP TABLE t2; #End of 10.2 tests diff --git a/mysql-test/t/mysql_client_test-master.opt b/mysql-test/t/mysql_client_test-master.opt index fcaf2b69fbc..478e62e308f 100644 --- a/mysql-test/t/mysql_client_test-master.opt +++ b/mysql-test/t/mysql_client_test-master.opt @@ -2,3 +2,4 @@ --general-log-file=$MYSQLTEST_VARDIR/log/master.log --log-output=FILE,TABLE --max-allowed-packet=32000000 +--sequence=on diff --git a/mysql-test/t/mysql_client_test_comp-master.opt b/mysql-test/t/mysql_client_test_comp-master.opt index 783093c900b..aa8a3382d09 100644 --- a/mysql-test/t/mysql_client_test_comp-master.opt +++ b/mysql-test/t/mysql_client_test_comp-master.opt @@ -1,2 +1,3 @@ --loose-enable-performance-schema --max-allowed-packet=32000000 +--sequence=on diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 40a1e873ab9..fbd97739a65 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1,4 +1,6 @@ --source include/have_partition.inc +--source include/have_sequence.inc + # # Basic stored PROCEDURE tests # @@ -10044,5 +10046,45 @@ drop procedure p1| drop function f1| delimiter ;| +--echo # +--echo # MDEV-24827: MariaDB 10.5.5 crash (sig 11) during a SELECT +--echo # + +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT); +CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 INT, KEY idx_c2(c2)); + +INSERT INTO t1 (c1, c2) SELECT seq, seq FROM seq_1_to_10000; +INSERT INTO t2 (c1, c2) SELECT seq, seq FROM seq_1_to_20000; + +--delimiter $ + +CREATE OR REPLACE PROCEDURE p1() +begin + DECLARE done INT DEFAULT FALSE; + DECLARE a INT; + + DECLARE cur1 CURSOR FOR + SELECT t2.c1 AS c1 FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 + WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = -1) ORDER BY c1; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + OPEN cur1; + read_loop: LOOP + FETCH cur1 INTO a; + IF done THEN + LEAVE read_loop; + END IF; + END LOOP; + CLOSE cur1; +END $ + +--delimiter ; + +CALL p1(); + +DROP PROCEDURE p1; +DROP TABLE t1; +DROP TABLE t2; --echo #End of 10.2 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a7e2ac4e374..abdc79c1bf3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12914,8 +12914,6 @@ return_zero_rows(JOIN *join, select_result *result, List &tables, DBUG_RETURN(0); } - join->join_free(); - if (send_row) { /* @@ -12962,6 +12960,8 @@ return_zero_rows(JOIN *join, select_result *result, List &tables, if (!send_error) result->send_eof(); // Should be safe } + join->join_free(); + DBUG_RETURN(0); } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index ac9c06ac94b..acd9b61327b 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -19962,6 +19962,58 @@ static void test_mdev_26145() myquery(rc); } +static void test_mdev24827() +{ + int rc; + MYSQL_STMT *stmt; + unsigned long cursor = CURSOR_TYPE_READ_ONLY; + + myheader("test_mdev24827"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 INT, " + "KEY idx_c2(c2))"); + myquery(rc); + + rc= mysql_query(mysql, "INSERT INTO t1 (c1, c2) " + "SELECT seq, seq FROM seq_1_to_10000"); + myquery(rc); + + rc= mysql_query(mysql, "INSERT INTO t2 (c1, c2) " + "SELECT seq, seq FROM seq_1_to_20000"); + myquery(rc); + + const char* query= + "SELECT t2.c1 AS c1 FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 " + "WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = -1) ORDER BY c1"; + + stmt= mysql_stmt_init(mysql); + check_stmt(stmt); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); + + rc= mysql_query(mysql, "DROP TABLE t2"); + myquery(rc); +} + #ifndef EMBEDDED_LIBRARY #define MDEV19838_MAX_PARAM_COUNT 32 #define MDEV19838_FIELDS_COUNT 17 @@ -20112,6 +20164,7 @@ static void test_mdev19838() #endif // EMBEDDED_LIBRARY static struct my_tests_st my_tests[]= { + { "test_mdev24827", test_mdev24827 }, { "test_mdev_26145", test_mdev_26145 }, { "disable_query_logs", disable_query_logs }, { "test_view_sp_list_fields", test_view_sp_list_fields }, -- cgit v1.2.1 From 1d27b5789aaa353175f5331d3a8b104b22dd1fce Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 20 Jan 2022 09:10:44 +1100 Subject: MDEV-27544 database() function should return 64 characters Database names are 64 utf8 characters per the system tables that refer to them. The current database() function is returning 34 characters. The result of limiting this function results to max length of 34 became apparent when used in a UNION ALL where the results are truncated to 34 characters. For (uninvestigated) reasons, SELECT DATABASE() on its own would always return the right number of characters. Thanks Alexander Barkov for the review. Thanks dave for noticing the bug in the stackexchange post https://dba.stackexchange.com/questions/306183/why-is-my-database-name-truncated --- mysql-test/r/func_system.result | 20 +++++++++++++++++++- mysql-test/t/func_system.test | 20 ++++++++++++++++++++ sql/item_strfunc.h | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result index 06fb7e44cf0..688f4a30b50 100644 --- a/mysql-test/r/func_system.result +++ b/mysql-test/r/func_system.result @@ -46,7 +46,7 @@ create table t1 (version char(60)) select database(), user(), version() as 'vers show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `database()` varchar(34) CHARACTER SET utf8 DEFAULT NULL, + `database()` varchar(64) CHARACTER SET utf8 DEFAULT NULL, `user()` varchar(141) CHARACTER SET utf8 DEFAULT NULL, `version` char(60) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 @@ -95,3 +95,21 @@ select left(concat(a,version()),1) from t1; left(concat(a,version()),1) a drop table t1; +# +# Start of 10.2 tests +# + +MDEV-27544 database() function under UNION ALL truncates results to 34 characters + + +SET NAMES utf8; +create database betäubungsmittelverschreibungsverordnung; +use betäubungsmittelverschreibungsverordnung; +select database() as "database" union all select database(); +database +betäubungsmittelverschreibungsverordnung +betäubungsmittelverschreibungsverordnung +drop database betäubungsmittelverschreibungsverordnung; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test index fa09e81a300..d9f2bda750a 100644 --- a/mysql-test/t/func_system.test +++ b/mysql-test/t/func_system.test @@ -55,3 +55,23 @@ select left(concat(a,version()),1) from t1; drop table t1; # End of 4.1 tests + +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo +--echo MDEV-27544 database() function under UNION ALL truncates results to 34 characters +--echo +--echo + +SET NAMES utf8; +create database betäubungsmittelverschreibungsverordnung; +use betäubungsmittelverschreibungsverordnung; +select database() as "database" union all select database(); +drop database betäubungsmittelverschreibungsverordnung; + + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 0bf21b63ac9..30464ddadb3 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -717,7 +717,7 @@ public: String *val_str(String *); bool fix_length_and_dec() { - max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen; + max_length= NAME_CHAR_LEN * system_charset_info->mbmaxlen; maybe_null=1; return FALSE; } -- cgit v1.2.1 From 7dcef6504620114f503dea92eadbb0e0fe95eb17 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Thu, 20 Jan 2022 16:25:43 +0700 Subject: MDEV-24827: Follow-up patch to fix compilation warning Mixed declarations and code is not allowed for C90 so fix it to avoid compilation break on some platforms. --- sql/sql_select.cc | 6 ++++++ tests/mysql_client_test.c | 7 +++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index abdc79c1bf3..db8a63eeb48 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12960,6 +12960,12 @@ return_zero_rows(JOIN *join, select_result *result, List &tables, if (!send_error) result->send_eof(); // Should be safe } + /* + JOIN::join_free() must be called after the virtual method + select::send_result_set_metadata() returned control since + implementation of this method could use data strutcures + that are released by the method JOIN::join_free(). + */ join->join_free(); DBUG_RETURN(0); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index acd9b61327b..69e451c3019 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -19967,6 +19967,9 @@ static void test_mdev24827() int rc; MYSQL_STMT *stmt; unsigned long cursor = CURSOR_TYPE_READ_ONLY; + const char* query= + "SELECT t2.c1 AS c1 FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 " + "WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = -1) ORDER BY c1"; myheader("test_mdev24827"); @@ -19991,10 +19994,6 @@ static void test_mdev24827() "SELECT seq, seq FROM seq_1_to_20000"); myquery(rc); - const char* query= - "SELECT t2.c1 AS c1 FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 " - "WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = -1) ORDER BY c1"; - stmt= mysql_stmt_init(mysql); check_stmt(stmt); -- cgit v1.2.1 From 474c6df804e74949a573d1d80013ae98378df479 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 18 Jan 2022 13:38:08 +0530 Subject: MDEV-27417 InnoDB spatial index updates change buffer bitmap page - InnoDB change buffer doesn't support spatial index. Spatial index should avoid change the buffer bitmap page when the page split happens. --- mysql-test/suite/innodb_gis/r/rtree_split.result | 7 +++++++ mysql-test/suite/innodb_gis/t/rtree_split.test | 8 ++++++++ storage/innobase/gis/gis0rtree.cc | 9 --------- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/innodb_gis/r/rtree_split.result b/mysql-test/suite/innodb_gis/r/rtree_split.result index df88960ba3d..2d6e8a1dfbe 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_split.result +++ b/mysql-test/suite/innodb_gis/r/rtree_split.result @@ -61,3 +61,10 @@ select count(*) from t1 where MBRWithin(t1.c2, @g1); count(*) 57344 drop table t1; +# +# MDEV-27417 Spatial index tries to update +# change buffer bookkeeping page +# +CREATE TEMPORARY TABLE t1 (c POINT NOT NULL, SPATIAL(c)) ENGINE=InnoDB; +INSERT INTO t1 SELECT PointFromText('POINT(0 0)') FROM seq_1_to_366; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_gis/t/rtree_split.test b/mysql-test/suite/innodb_gis/t/rtree_split.test index af626dba6b7..dd46d1ecc4d 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_split.test +++ b/mysql-test/suite/innodb_gis/t/rtree_split.test @@ -72,3 +72,11 @@ select count(*) from t1 where MBRWithin(t1.c2, @g1); # Clean up. drop table t1; + +--echo # +--echo # MDEV-27417 Spatial index tries to update +--echo # change buffer bookkeeping page +--echo # +CREATE TEMPORARY TABLE t1 (c POINT NOT NULL, SPATIAL(c)) ENGINE=InnoDB; +INSERT INTO t1 SELECT PointFromText('POINT(0 0)') FROM seq_1_to_366; +DROP TABLE t1; diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index e3d5a09f736..50071bcfae4 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -1262,15 +1262,6 @@ after_insert: page_zip = buf_block_get_page_zip(root_block); page_set_ssn_id(root_block, page_zip, next_ssn, mtr); - /* Insert fit on the page: update the free bits for the - left and right pages in the same mtr */ - - if (page_is_leaf(page)) { - ibuf_update_free_bits_for_two_pages_low( - block, new_block, mtr); - } - - /* If the new res insert fail, we need to do another split again. */ if (!rec) { -- cgit v1.2.1 From d28d3aee10801ec8fb4cc484a3a7bcb108cf7da3 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Thu, 20 Jan 2022 18:39:36 +0700 Subject: MDEV-24827: Follow-up patch to fix the test main.mysql_client_test_nonblock --- mysql-test/t/mysql_client_test_nonblock-master.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/mysql_client_test_nonblock-master.opt b/mysql-test/t/mysql_client_test_nonblock-master.opt index 5775e707c5f..fe6d56d81d0 100644 --- a/mysql-test/t/mysql_client_test_nonblock-master.opt +++ b/mysql-test/t/mysql_client_test_nonblock-master.opt @@ -1,2 +1,2 @@ --general-log --general-log-file=$MYSQLTEST_VARDIR/log/master.log --log-output=FILE,TABLE ---max-allowed-packet=32000000 +--max-allowed-packet=32000000 --sequence=on -- cgit v1.2.1 From 0fd4d6d3bb77b9072305f0b1d5bebfb914ad55cc Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 4 Jan 2022 20:09:40 +0200 Subject: MDEV-27068 running mariadb-upgrade in parallel make it hangs forever MDEV-27107 prevent two mariadb-upgrade running in parallel MDEV-27279 mariadb_upgrade add --check-if-upgrade-is-needed / restrict tests to major version Code is based of pull request from Daniel Black, but with a several extensions. - mysql_upgrade now locks the mysql_upgrade file with my_lock() (Advisory record locking). This ensures that two mysql_upgrades cannot be run in parallel. - Added --check-if-upgrade-is-needed to mysql_upgrade. This will return 0 if one has to run mysql_upgrade. Other changes: - mysql_upgrade will now immediately exit if the major version and minor version (two first numbers in the version string) is same as last run. Before this change mysql_upgrade was run if the version string was different from last run. - Better messages when there is no need to run mysql_upgrade. - mysql_upgrade --verbose now prints out a lot more information about the version checking. - mysql_upgrade --debug now uses default debug arguments if there is no option to --debug - "MySQL" is renamed to MariaDB in the messages - mysql_upgrade version increased to 2.0 Notes Verifying "prevent two mariadb-upgrade running in parallel" was done in a debugger as it would be a bit complex to do that in mtr. Reviewer: Danial Black --- client/client_priv.h | 1 + client/mysql_upgrade.c | 313 ++++++++++++++++++++--------- man/mysql_upgrade.1 | 15 ++ mysql-test/r/mysql_upgrade.result | 42 +++- mysql-test/r/mysql_upgrade_noengine.result | 4 + mysql-test/r/mysql_upgrade_view.result | 4 +- mysql-test/t/mysql_upgrade-6984.test | 4 + mysql-test/t/mysql_upgrade.test | 81 +++++++- mysql-test/t/mysql_upgrade_noengine.test | 9 +- 9 files changed, 372 insertions(+), 101 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index 5f2d62024a3..ffc564a90d1 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -99,6 +99,7 @@ enum options_client OPT_SKIP_ANNOTATE_ROWS_EVENTS, OPT_SSL_CRL, OPT_SSL_CRLPATH, OPT_IGNORE_DATA, + OPT_CHECK_IF_UPGRADE_NEEDED, OPT_MAX_CLIENT_OPTION /* should be always the last */ }; diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 2c55251c71b..8c186b521c1 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -22,7 +22,7 @@ #include /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ -#define VER "1.4" +#define VER "2.0" #ifdef HAVE_SYS_WAIT_H #include @@ -37,13 +37,15 @@ #endif static int phase = 0; +static int info_file= -1; static const int phases_total = 7; static char mysql_path[FN_REFLEN]; static char mysqlcheck_path[FN_REFLEN]; -static my_bool opt_force, opt_verbose, debug_info_flag, debug_check_flag, +static my_bool debug_info_flag, debug_check_flag, opt_systables_only, opt_version_check; -static my_bool opt_not_used, opt_silent; +static my_bool opt_not_used, opt_silent, opt_check_upgrade; +static uint opt_force, opt_verbose; static uint my_end_arg= 0; static char *opt_user= (char*)"root"; @@ -69,7 +71,7 @@ static char **defaults_argv; static my_bool not_used; /* Can't use GET_BOOL without a value pointer */ -char upgrade_from_version[sizeof("10.20.456-MariaDB")+1]; +char upgrade_from_version[sizeof("10.20.456-MariaDB")+30]; static my_bool opt_write_binlog; @@ -95,8 +97,8 @@ static struct my_option my_long_options[]= {"debug", '#', "This is a non-debug version. Catch this and exit.", 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log.", &default_dbug_option, - &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", &debug_check_flag, &debug_check_flag, @@ -110,9 +112,13 @@ static struct my_option my_long_options[]= "Default authentication client-side plugin to use.", &opt_default_auth, &opt_default_auth, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"check-if-upgrade-is-needed", OPT_CHECK_IF_UPGRADE_NEEDED, + "Exits with status 0 if an upgrades is required, 1 otherwise.", + &opt_check_upgrade, &opt_check_upgrade, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade " - "has already been executed for the current version of MySQL.", - &opt_force, &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + "has already been executed for the current version of MariaDB.", + &opt_not_used, &opt_not_used, 0 , GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Connect to host.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #define PASSWORD_OPT 12 @@ -193,6 +199,12 @@ static void free_used_memory(void) dynstr_free(&conn_args); if (cnf_file_path) my_delete(cnf_file_path, MYF(MY_WME)); + if (info_file >= 0) + { + (void) my_lock(info_file, F_UNLCK, 0, 1, MYF(0)); + my_close(info_file, MYF(MY_WME)); + info_file= -1; + } } @@ -238,6 +250,13 @@ static void verbose(const char *fmt, ...) } +static void print_error(const char *error_msg, DYNAMIC_STRING *output) +{ + fprintf(stderr, "%s\n", error_msg); + fprintf(stderr, "%s", output->str); +} + + /* Add one option - passed to mysql_upgrade on command line or by defaults file(my.cnf) - to a dynamic string, in @@ -271,6 +290,7 @@ static void add_one_option_cnf_file(DYNAMIC_STRING *ds, dynstr_append(ds, "\n"); } + static my_bool get_one_option(int optid, const struct my_option *opt, char *argument) @@ -339,11 +359,17 @@ get_one_option(int optid, const struct my_option *opt, my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); die(0); break; + case 'f': /* --force */ + opt_force++; + if (argument == disabled_my_option) + opt_force= 0; + add_option= 0; + break; case OPT_SILENT: opt_verbose= 0; add_option= 0; break; - case 'f': /* --force */ + case OPT_CHECK_IF_UPGRADE_NEEDED: /* --check-if-upgrade-needed */ case 's': /* --upgrade-system-tables */ case OPT_WRITE_BINLOG: /* --write-binlog */ add_option= FALSE; @@ -374,6 +400,18 @@ get_one_option(int optid, const struct my_option *opt, } +/* Convert the specified version string into the numeric format. */ + +static ulong STDCALL calc_server_version(char *some_version) +{ + uint major, minor, version; + char *point= some_version, *end_point; + major= (uint) strtoul(point, &end_point, 10); point=end_point+1; + minor= (uint) strtoul(point, &end_point, 10); point=end_point+1; + version= (uint) strtoul(point, &end_point, 10); + return (ulong) major * 10000L + (ulong)(minor * 100 + version); +} + /** Run a command using the shell, storing its output in the supplied dynamic string. @@ -572,7 +610,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, if (my_write(fd, sql_log_bin, sizeof(sql_log_bin)-1, MYF(MY_FNABP | MY_WME))) { - my_close(fd, MYF(0)); + my_close(fd, MYF(MY_WME)); my_delete(query_file_path, MYF(0)); die("Failed to write to '%s'", query_file_path); } @@ -581,7 +619,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, if (my_write(fd, (uchar*) query, strlen(query), MYF(MY_FNABP | MY_WME))) { - my_close(fd, MYF(0)); + my_close(fd, MYF(MY_WME)); my_delete(query_file_path, MYF(0)); die("Failed to write to '%s'", query_file_path); } @@ -598,7 +636,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, "2>&1", NULL); - my_close(fd, MYF(0)); + my_close(fd, MYF(MY_WME)); my_delete(query_file_path, MYF(0)); DBUG_RETURN(ret); @@ -645,6 +683,9 @@ static int get_upgrade_info_file_name(char* name) &ds_datadir, FALSE) || extract_variable_from_show(&ds_datadir, name)) { + print_error("Reading datadir from the MariaDB server failed. Got the " + "following error when executing the 'mysql' command line client", + &ds_datadir); dynstr_free(&ds_datadir); DBUG_RETURN(1); /* Query failed */ } @@ -656,6 +697,83 @@ static int get_upgrade_info_file_name(char* name) DBUG_RETURN(0); } +static char upgrade_info_file[FN_REFLEN]= {0}; + + +/* + Open or create mysql_upgrade_info file in servers data dir. + + Take a lock to ensure there cannot be any other mysql_upgrades + runninc concurrently +*/ + +const char *create_error_message= + "%sCould not open or create the upgrade info file '%s' in " + "the MariaDB Servers data directory, errno: %d (%s)\n"; + + + +static void open_mysql_upgrade_file() +{ + char errbuff[80]; + if (get_upgrade_info_file_name(upgrade_info_file)) + { + die("Upgrade failed"); + } + if ((info_file= my_create(upgrade_info_file, 0, + O_RDWR | O_NOFOLLOW, + MYF(0))) < 0) + { + if (opt_force >= 2) + { + fprintf(stdout, create_error_message, + "", upgrade_info_file, errno, + my_strerror(errbuff, sizeof(errbuff)-1, errno)); + fprintf(stdout, + "--force --force used, continuing without using the %s file.\n" + "Note that this means that there is no protection against " + "concurrent mysql_upgrade executions and next mysql_upgrade run " + "will do a full upgrade again!\n", + upgrade_info_file); + return; + } + fprintf(stdout, create_error_message, + "FATAL ERROR: ", + upgrade_info_file, errno, + my_strerror(errbuff, sizeof(errbuff)-1, errno)); + if (errno == EACCES) + { + fprintf(stderr, + "Note that mysql_upgrade should be run as the same user as the " + "MariaDB server binary, normally 'mysql' or 'root'.\n" + "Alternatively you can use mysql_upgrade --force --force. " + "Please check the documentation if you decide to use the force " + "option!\n"); + } + fflush(stderr); + die(0); + } + if (my_lock(info_file, F_WRLCK, 0, 1, MYF(0))) + { + die("Could not exclusively lock on file '%s'. Error %d: %s\n", + upgrade_info_file, my_errno, + my_strerror(errbuff, sizeof(errbuff)-1, my_errno)); + } +} + + +/** + Place holder for versions that require a major upgrade + + @return 0 upgrade has alredy been run on this version + @return 1 upgrade has to be run + +*/ + +static int faulty_server_versions(const char *version) +{ + return 0; +} /* Read the content of mysql_upgrade_info file and @@ -665,79 +783,111 @@ static int get_upgrade_info_file_name(char* name) NOTE This is an optimization to avoid running mysql_upgrade when it's already been performed for the particular - version of MySQL. + version of MariaDB. - In case the MySQL server can't return the upgrade info + In case the MariaDBL server can't return the upgrade info file it's always better to report that the upgrade hasn't been performed. + @return 0 Upgrade has alredy been run on this version + @return > 0 Upgrade has to be run */ -static int upgrade_already_done(void) +static int upgrade_already_done(int silent) { - FILE *in; - char upgrade_info_file[FN_REFLEN]= {0}; - - if (get_upgrade_info_file_name(upgrade_info_file)) - return 0; /* Could not get filename => not sure */ - - if (!(in= my_fopen(upgrade_info_file, O_RDONLY, MYF(0)))) - return 0; /* Could not open file => not sure */ + const char *version = MYSQL_SERVER_VERSION; + const char *s; + char *pos; + my_off_t length; - bzero(upgrade_from_version, sizeof(upgrade_from_version)); - if (!fgets(upgrade_from_version, sizeof(upgrade_from_version), in)) + if (info_file < 0) { - /* Ignore, will be detected by strncmp() below */ + DBUG_ASSERT(opt_force > 1); + return 1; /* No info file and --force */ } - my_fclose(in, MYF(0)); - - return (strncmp(upgrade_from_version, MYSQL_SERVER_VERSION, - sizeof(MYSQL_SERVER_VERSION)-1)==0); -} - + bzero(upgrade_from_version, sizeof(upgrade_from_version)); -/* - Write mysql_upgrade_info file in servers data dir indicating that - upgrade has been done for this version + (void) my_seek(info_file, 0, SEEK_SET, MYF(0)); + /* We have -3 here to make calc_server_version() safe */ + length= my_read(info_file, (uchar*) upgrade_from_version, + sizeof(upgrade_from_version)-3, + MYF(MY_WME)); - NOTE - This might very well fail but since it's just an optimization - to run mysql_upgrade only when necessary the error can be - ignored. + if (!length) + { + if (opt_verbose) + verbose("Empty or non existent %s. Assuming mysql_upgrade has to be run!", + upgrade_info_file); + return 1; + } -*/ + /* Remove possible \ŋ that may end in output */ + if ((pos= strchr(upgrade_from_version, '\n'))) + *pos= 0; -static void create_mysql_upgrade_info_file(void) -{ - FILE *out; - char upgrade_info_file[FN_REFLEN]= {0}; + if (faulty_server_versions(upgrade_from_version)) + { + if (opt_verbose) + verbose("Upgrading from version %s requires mysql_upgrade to be run!", + upgrade_from_version); + return 2; + } - if (get_upgrade_info_file_name(upgrade_info_file)) - return; /* Could not get filename => skip */ + s= strchr(version, '.'); + s= strchr(s + 1, '.'); - if (!(out= my_fopen(upgrade_info_file, O_TRUNC | O_WRONLY, MYF(0)))) + if (strncmp(upgrade_from_version, version, + (size_t)(s - version + 1))) { - fprintf(stderr, - "Could not create the upgrade info file '%s' in " - "the MySQL Servers datadir, errno: %d\n", - upgrade_info_file, errno); - return; + if (calc_server_version(upgrade_from_version) <= MYSQL_VERSION_ID) + { + verbose("Major version upgrade detected from %s to %s. Check required!", + upgrade_from_version, version); + return 3; + } + die("Version mismatch (%s -> %s): Trying to downgrade from a higher to " + "lower version is not supported!", + upgrade_from_version, version); } + if (!silent) + { + verbose("This installation of MariaDB is already upgraded to %s.\n" + "There is no need to run mysql_upgrade again for %s.", + upgrade_from_version, version); + if (!opt_check_upgrade) + verbose("You can use --force if you still want to run mysql_upgrade", + upgrade_from_version, version); + } + return 0; +} + +static void finish_mysql_upgrade_info_file(void) +{ + if (info_file < 0) + return; /* Write new version to file */ - fputs(MYSQL_SERVER_VERSION, out); - my_fclose(out, MYF(0)); + (void) my_seek(info_file, 0, SEEK_CUR, MYF(0)); + (void) my_chsize(info_file, 0, 0, MYF(0)); + (void) my_seek(info_file, 0, 0, MYF(0)); + (void) my_write(info_file, (uchar*) MYSQL_SERVER_VERSION, + sizeof(MYSQL_SERVER_VERSION)-1, MYF(MY_WME)); + (void) my_write(info_file, (uchar*) "\n", 1, MYF(MY_WME)); + (void) my_lock(info_file, F_UNLCK, 0, 1, MYF(0)); /* - Check if the upgrad_info_file was properly created/updated + Check if the upgrade_info_file was properly created/updated It's not a fatal error -> just print a message if it fails */ - if (!upgrade_already_done()) + if (upgrade_already_done(1)) fprintf(stderr, "Could not write to the upgrade info file '%s' in " - "the MySQL Servers datadir, errno: %d\n", + "the MariaDB Servers datadir, errno: %d\n", upgrade_info_file, errno); + + my_close(info_file, MYF(MY_WME)); + info_file= -1; return; } @@ -808,7 +958,7 @@ static my_bool is_mysql() strstr(ds_events_struct.str, "IGNORE_BAD_TABLE_OPTIONS") != NULL) ret= FALSE; else - verbose("MySQL upgrade detected"); + verbose("MariaDB upgrade detected"); dynstr_free(&ds_events_struct); return(ret); @@ -1059,7 +1209,7 @@ static int check_slave_repositories(void) } /* - Update all system tables in MySQL Server to current + Update all system tables in MariaDB Server to current version using "mysql" to execute all the SQL commands compiled into the mysql_fix_privilege_tables array */ @@ -1128,24 +1278,6 @@ static int run_sql_fix_privilege_tables(void) } -static void print_error(const char *error_msg, DYNAMIC_STRING *output) -{ - fprintf(stderr, "%s\n", error_msg); - fprintf(stderr, "%s", output->str); -} - - -/* Convert the specified version string into the numeric format. */ -static ulong STDCALL calc_server_version(char *some_version) -{ - uint major, minor, version; - char *point= some_version, *end_point; - major= (uint) strtoul(point, &end_point, 10); point=end_point+1; - minor= (uint) strtoul(point, &end_point, 10); point=end_point+1; - version= (uint) strtoul(point, &end_point, 10); - return (ulong) major * 10000L + (ulong)(minor * 100 + version); -} - /** Check if the server version matches with the server version mysql_upgrade was compiled with. @@ -1181,8 +1313,7 @@ static int check_version_match(void) "check.\n", version_str, MYSQL_SERVER_VERSION); return 1; } - else - return 0; + return 0; } @@ -1191,6 +1322,8 @@ int main(int argc, char **argv) char self_name[FN_REFLEN + 1]; MY_INIT(argv[0]); + DBUG_PROCESS(argv[0]); + load_defaults_or_exit("my", load_default_groups, &argc, &argv); defaults_argv= argv; /* Must be freed by 'free_defaults' */ @@ -1231,12 +1364,17 @@ int main(int argc, char **argv) die(NULL); my_write(fd, USTRING_WITH_LEN( "[client]\n"), MYF(MY_FAE)); my_write(fd, (uchar*)ds_args.str, ds_args.length, MYF(MY_FAE)); - my_close(fd, MYF(0)); + my_close(fd, MYF(MY_WME)); } /* Find mysql */ find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name); + open_mysql_upgrade_file(); + + if (opt_check_upgrade) + exit(upgrade_already_done(0) == 0); + /* Find mysqlcheck */ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name); @@ -1245,15 +1383,10 @@ int main(int argc, char **argv) /* Read the mysql_upgrade_info file to check if mysql_upgrade - already has been run for this installation of MySQL + already has been run for this installation of MariaDB */ - if (!opt_force && upgrade_already_done()) - { - printf("This installation of MySQL is already upgraded to %s, " - "use --force if you still need to run mysql_upgrade\n", - MYSQL_SERVER_VERSION); - goto end; - } + if (!opt_force && !upgrade_already_done(0)) + goto end; /* Upgrade already done */ if (opt_version_check && check_version_match()) die("Upgrade failed"); @@ -1278,8 +1411,8 @@ int main(int argc, char **argv) verbose("OK"); - /* Create a file indicating upgrade has been performed */ - create_mysql_upgrade_info_file(); + /* Finish writing indicating upgrade has been performed */ + finish_mysql_upgrade_info_file(); DBUG_ASSERT(phase == phases_total); diff --git a/man/mysql_upgrade.1 b/man/mysql_upgrade.1 index 29e9478781c..5ea4b254a98 100644 --- a/man/mysql_upgrade.1 +++ b/man/mysql_upgrade.1 @@ -239,6 +239,21 @@ Old option accepted for backward compatibility but ignored\&. .sp -1 .IP \(bu 2.3 .\} +.\" mysql_upgrade: check-if-upgrade-is-needed option +.\" check-if-upgrade-is-needed option: mysql_upgrade +\fB\-\-check\-if\-upgrade\-is\-needed\fR +.sp +Exit with a status code indicating if an upgrade is needed\&. Returns 0 if upgrade needed or current version couldn't be determined, 1 when no action required\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} .\" mysql_upgrade: datadir option .\" datadir option: mysql_upgrade \fB\-\-datadir=\fR\fB\fIpath\fR\fR diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 79c15984a12..90134914a63 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -46,7 +46,9 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK Run it again - should say already completed -This installation of MySQL is already upgraded to VERSION, use --force if you still need to run mysql_upgrade +This installation of MariaDB is already upgraded to VERSION. +There is no need to run mysql_upgrade again for VERSION. +You can use --force if you still want to run mysql_upgrade Force should run it regardless of whether it has been run before Phase 1/7: Checking and upgrading mysql database Processing databases @@ -142,11 +144,12 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK DROP USER mysqltest1@'%'; -Version check failed. Got the following error when calling the 'mysql' command line client +Reading datadir from the MariaDB server failed. Got the following error when executing the 'mysql' command line client ERROR 1045 (28000): Access denied for user 'mysqltest1'@'localhost' (using password: YES) FATAL ERROR: Upgrade failed Run mysql_upgrade with a non existing server socket -mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (errno) when trying to connect +Reading datadir from the MariaDB server failed. Got the following error when executing the 'mysql' command line client +ERROR 2005 (HY000): Unknown MySQL server host 'not_existing_host' (errno) FATAL ERROR: Upgrade failed set GLOBAL sql_mode='STRICT_ALL_TABLES,ANSI_QUOTES,NO_ZERO_DATE'; Phase 1/7: Checking and upgrading mysql database @@ -405,9 +408,12 @@ OK # Bug #21489398: MYSQL_UPGRADE: FATAL ERROR: UPGRADE FAILED - IMPROVE ERROR # Run mysql_upgrade with unauthorized access -Version check failed. Got the following error when calling the 'mysql' command line client +Reading datadir from the MariaDB server failed. Got the following error when executing the 'mysql' command line client ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) FATAL ERROR: Upgrade failed +Reading datadir from the MariaDB server failed. Got the following error when executing the 'mysql' command line client +ERROR 1045 (errno): Access denied for user 'root'@'localhost' (using password: YES) +FATAL ERROR: Upgrade failed # # MDEV-4332 Increase username length from 16 characters # MDEV-6068, MDEV-6178 mysql_upgrade breaks databases with long user names @@ -854,4 +860,32 @@ GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION GRANT USAGE ON *.* TO 'aRole' DROP ROLE `aRole`; FLUSH PRIVILEGES; +# +# MDEV-27279: mariadb_upgrade add --check-if-upgrade-is-needed +# +This installation of MariaDB is already upgraded to MariaDB . +There is no need to run mysql_upgrade again for MariaDB . +Looking for 'mysql' as: mysql +This installation of MariaDB is already upgraded to MariaDB . +There is no need to run mysql_upgrade again for MariaDB . +# +# MDEV-27279: mariadb_upgrade check-if-upgrade absence is do it +# +Looking for 'mysql' as: mysql +Empty or non existent ...mysql_upgrade_info. Assuming mysql_upgrade has to be run! +# +# MDEV-27279: mariadb_upgrade check-if-upgrade with minor version change +# +Looking for 'mysql' as: mysql +This installation of MariaDB is already upgraded to MariaDB . +There is no need to run mysql_upgrade again for MariaDB . +This installation of MariaDB is already upgraded to MariaDB . +There is no need to run mysql_upgrade again for MariaDB . +You can use --force if you still want to run mysql_upgrade +# +# MDEV-27279: mariadb_upgrade check-if-upgrade with major version change +# +Major version upgrade detected from MariaDB to MariaDB . Check required! +Looking for 'mysql' as: mysql +Major version upgrade detected from MariaDB to MariaDB . Check required! End of 10.2 tests diff --git a/mysql-test/r/mysql_upgrade_noengine.result b/mysql-test/r/mysql_upgrade_noengine.result index 09e705abb69..1b6cfd34232 100644 --- a/mysql-test/r/mysql_upgrade_noengine.result +++ b/mysql-test/r/mysql_upgrade_noengine.result @@ -50,6 +50,7 @@ Message Unknown storage engine 'BLACKHOLE' Level Warning Code 1286 Message Unknown storage engine 'ARCHIVE' +# upgrade from 10.1 - engines aren't enabled Phase 1/7: Checking and upgrading mysql database Processing databases mysql @@ -136,6 +137,8 @@ Level Warning Code 1286 Message Unknown storage engine 'ARCHIVE' alter table mysql.user drop column default_role, drop column max_statement_time; +# still upgrade from 10.1 +Major version upgrade detected from MariaDB to MariaDB . Check required! Phase 1/7: Checking and upgrading mysql database Processing databases mysql @@ -222,6 +225,7 @@ Level Warning Code 1286 Message Unknown storage engine 'ARCHIVE' alter table mysql.user drop column default_role, drop column max_statement_time; +# upgrade from 10.0 - engines are enabled Phase 1/7: Checking and upgrading mysql database Processing databases mysql diff --git a/mysql-test/r/mysql_upgrade_view.result b/mysql-test/r/mysql_upgrade_view.result index dc31592566a..7dbe71ba699 100644 --- a/mysql-test/r/mysql_upgrade_view.result +++ b/mysql-test/r/mysql_upgrade_view.result @@ -205,7 +205,7 @@ v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI show create view v4; View Create View character_set_client collation_connection v4 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS select `t1`.`a` AS `a` from `t1` latin1 latin1_swedish_ci -MySQL upgrade detected +MariaDB upgrade detected Phase 1/7: Checking and upgrading mysql database Processing databases mysql @@ -324,7 +324,7 @@ drop view v1,v2,v3,v4; rename table mysql.event to mysql.ev_bk; flush tables; The --upgrade-system-tables option was used, user tables won't be touched. -MySQL upgrade detected +MariaDB upgrade detected Phase 1/7: Checking and upgrading mysql database Processing databases mysql diff --git a/mysql-test/t/mysql_upgrade-6984.test b/mysql-test/t/mysql_upgrade-6984.test index 9bbfbeb3f87..89ebd46e3ba 100644 --- a/mysql-test/t/mysql_upgrade-6984.test +++ b/mysql-test/t/mysql_upgrade-6984.test @@ -13,6 +13,7 @@ update mysql.user set password=password("foo") where user='root'; +--replace_regex /[^ ]*mysql_upgrade_info/...mysql_upgrade_info/ --exec $MYSQL_UPGRADE connect(con1,localhost,root,foo,,,); @@ -21,3 +22,6 @@ update mysql.user set password='' where user='root'; flush privileges; # Load event table set global event_scheduler=OFF; + +let MYSQLD_DATADIR= `select @@datadir`; +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index c116af860a6..b58e72a3797 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -17,7 +17,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; file_exists $MYSQLD_DATADIR/mysql_upgrade_info; --echo Run it again - should say already completed ---replace_result $MYSQL_SERVER_VERSION VERSION +--replace_regex /upgraded to [^\n]*/upgraded to VERSION./ /again for [^\n]*/again for VERSION./ --exec $MYSQL_UPGRADE 2>&1 # It should have created a file in the MySQL Servers datadir @@ -126,7 +126,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; --remove_file $MYSQLD_DATADIR/mysql_upgrade_info --echo # Running mysql_upgrade with --skip-write-binlog.. ---replace_result $MYSQLTEST_VARDIR var +--replace_regex /[^ ]*mysql_upgrade_info/...mysql_upgrade_info/ --exec $MYSQL_UPGRADE --skip-write-binlog # mysql_upgrade must have created mysql_upgrade_info file, @@ -140,6 +140,9 @@ let $MYSQLD_DATADIR= `select @@datadir`; --echo Run mysql_upgrade with unauthorized access --error 1 --exec $MYSQL_UPGRADE --skip-verbose --user=root --password=wrong_password 2>&1 +--replace_regex /.*mysqlcheck.*: Got/mysqlcheck: Got/ /\([0-9|-]*\)/(errno)/ +--error 1 +--exec $MYSQL_UPGRADE --skip-verbose --skip-version-check --user=root --password=wrong_password 2>&1 --echo # --echo # MDEV-4332 Increase username length from 16 characters @@ -235,6 +238,7 @@ FLUSH TABLES mysql.user; FLUSH PRIVILEGES; SHOW CREATE TABLE mysql.user; +--replace_result $MYSQLTEST_VARDIR var --exec $MYSQL_UPGRADE --force 2>&1 SHOW CREATE TABLE mysql.user; @@ -279,6 +283,79 @@ SHOW GRANTS; DROP ROLE `aRole`; --exec $MYSQL mysql < $MYSQLTEST_VARDIR/tmp/user.sql FLUSH PRIVILEGES; + +--echo # +--echo # MDEV-27279: mariadb_upgrade add --check-if-upgrade-is-needed +--echo # + +--error 1 +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed --silent +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / +--error 1 +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / /'mysql.* as:[^\n]*/'mysql' as: mysql/ +--error 1 +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed --verbose + +--echo # +--echo # MDEV-27279: mariadb_upgrade check-if-upgrade absence is do it +--echo # + +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +--replace_regex /[^ ]*mysql_upgrade_info/...mysql_upgrade_info/ +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed + +--replace_regex /'mysql.* as:[^\n]*/'mysql' as: mysql/ /open .* Assuming/open XXX. Assuming/ /[^ ]*mysql_upgrade_info/...mysql_upgrade_info/ +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed --verbose + +--echo # +--echo # MDEV-27279: mariadb_upgrade check-if-upgrade with minor version change +--echo # + +# take 3rd number of version and change to 0 + +let DATADIR= $MYSQLD_DATADIR; + +perl; + my $ver= $ENV{'MYSQL_SERVER_VERSION'} or die "MYSQL_SERVER_VERSION not set"; + my $file= $ENV{'DATADIR'} or die "MYSQLD_DATADIR not set"; + $ver =~ s/^(\d*)\.(\d*).(\d*)(.*)/$1.$2.0$4/; + open(FILE, ">$file/mysql_upgrade_info") or die "Failed to open $file"; + print FILE "$ver\n"; + close(FILE); +EOF + +--error 1 +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed --silent +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / /'mysql.* as:[^\n]*/'mysql' as: mysql/ +--error 1 +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed --verbose +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / +--exec $MYSQL_UPGRADE +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info + +--echo # +--echo # MDEV-27279: mariadb_upgrade check-if-upgrade with major version change +--echo # + +# take 2rd number of version and change to 0 + +let DATADIR= $MYSQLD_DATADIR; + +perl; + my $ver= $ENV{'MYSQL_SERVER_VERSION'} or die "MYSQL_SERVER_VERSION not set"; + my $file= $ENV{'DATADIR'} or die "MYSQLD_DATADIR not set"; + $ver =~ s/^(\d*)\.(\d*).(\d*)(.*)/$1.0.$3$4/; + open(FILE, ">$file/mysql_upgrade_info") or die "Failed to open $file"; + print FILE "$ver\n"; + close(FILE); +EOF + +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed --silent +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / /'mysql.* as:[^\n]*/'mysql' as: mysql/ +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed --verbose --remove_file $MYSQLD_DATADIR/mysql_upgrade_info --echo End of 10.2 tests diff --git a/mysql-test/t/mysql_upgrade_noengine.test b/mysql-test/t/mysql_upgrade_noengine.test index cfc3a1dc406..c8bfe577eb2 100644 --- a/mysql-test/t/mysql_upgrade_noengine.test +++ b/mysql-test/t/mysql_upgrade_noengine.test @@ -26,7 +26,8 @@ uninstall plugin blackhole; uninstall plugin archive; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test'; -# upgrade from 10.1 - engines aren't enabled +--echo # upgrade from 10.1 - engines aren't enabled +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / exec $MYSQL_UPGRADE 2>&1; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test'; @@ -39,14 +40,16 @@ write_file $datadir/mysql_upgrade_info; 10.1.10-MariaDB EOF -# still upgrade from 10.1 +--echo # still upgrade from 10.1 +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / exec $MYSQL_UPGRADE 2>&1; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test'; alter table mysql.user drop column default_role, drop column max_statement_time; remove_file $datadir/mysql_upgrade_info; -# upgrade from 10.0 - engines are enabled +--echo # upgrade from 10.0 - engines are enabled +--replace_regex /\d\d\.\d*\.\d*[^ .\n]*/MariaDB / exec $MYSQL_UPGRADE 2>&1; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test'; -- cgit v1.2.1 From 9d4c0a6cabc67dca6a5044ef7ae82e4198a8aab4 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 5 Jan 2022 16:37:47 +0200 Subject: Fixed compiler error in auth_pam plugin Code copied from 10.6 --- plugin/auth_pam/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugin/auth_pam/CMakeLists.txt b/plugin/auth_pam/CMakeLists.txt index 1f58c7567b3..0f8be704f0c 100644 --- a/plugin/auth_pam/CMakeLists.txt +++ b/plugin/auth_pam/CMakeLists.txt @@ -1,3 +1,7 @@ +IF(WIN32) + RETURN() +ENDIF() + INCLUDE (CheckIncludeFiles) INCLUDE (CheckFunctionExists) @@ -15,8 +19,8 @@ CHECK_C_SOURCE_COMPILES( #include #include int main() { - char *arg_1; - gid_t arg_2, arg_3; + char *arg_1= 0; + gid_t arg_2=0, arg_3; int arg_4; (void)getgrouplist(arg_1,arg_2,&arg_3,&arg_4); return 0; -- cgit v1.2.1 From d3143ef8a8655975a00d6333823a820cb72c195d Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 11 Jan 2022 14:41:37 +0200 Subject: Improve --help and remove not-free warnings for mysql_tzinfo_to_sql --- sql/tztime.cc | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/sql/tztime.cc b/sql/tztime.cc index 067348dccab..47bc44f3386 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2630,24 +2630,33 @@ static struct my_option my_long_options[] = {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF - {"debug", '#', "This is a non-debug version. Catch this and exit", + {"debug", '#', "This is a non-debug version. Catch this and exit.", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"leap", 'l', "Print the leap second information from the given time zone file. By convention, when --leap is used the next argument is the timezonefile", + {"leap", 'l', "Print the leap second information from the given time zone file. By convention, when --leap is used the next argument is the timezonefile.", &opt_leap, &opt_leap, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Write non critical warnings", + {"verbose", 'v', "Write non critical warnings.", &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-write-binlog", 'S', "Do not replicate changes to time zone tables to other nodes in a Galera cluster", + {"skip-write-binlog", 'S', "Do not replicate changes to time zone tables to other nodes in a Galera cluster.", &opt_skip_write_binlog,&opt_skip_write_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; +static char **default_argv; + +static void free_allocated_data() +{ + free_defaults(default_argv); + my_end(0); +} + + C_MODE_START static my_bool get_one_option(int optid, const struct my_option *, char *argument); @@ -2659,11 +2668,21 @@ static void print_version(void) MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); } +static const char *default_timezone_dir= "/usr/share/zoneinfo/"; + + static void print_usage(void) { - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s [options] timezonedir\n", my_progname); - fprintf(stderr, " %s [options] timezonefile timezonename\n", my_progname); + fprintf(stdout, "Create SQL commands for loading system timezeone data for " + "MariaDB\n\n"); + fprintf(stdout, "Usage:\n"); + fprintf(stdout, " %s [options] timezonedir\n", my_progname); + fprintf(stdout, "or\n"); + fprintf(stdout, " %s [options] timezonefile timezonename\n", my_progname); + + fprintf(stdout, "\nA typical place for the system timezone directory is " + "\"%s\"\n", default_timezone_dir); + print_defaults("my",load_default_groups); puts(""); my_print_help(my_long_options); @@ -2684,9 +2703,11 @@ get_one_option(int optid, const struct my_option *opt, char *argument) print_version(); puts(""); print_usage(); + free_allocated_data(); exit(0); case 'V': print_version(); + free_allocated_data(); exit(0); } return 0; @@ -2696,7 +2717,6 @@ get_one_option(int optid, const struct my_option *opt, char *argument) int main(int argc, char **argv) { - char **default_argv; MY_INIT(argv[0]); load_defaults_or_exit("my", load_default_groups, &argc, &argv); @@ -2708,7 +2728,7 @@ main(int argc, char **argv) if ((argc != 1 && argc != 2) || (opt_leap && argc != 1)) { print_usage(); - free_defaults(default_argv); + free_allocated_data(); return 1; } -- cgit v1.2.1 From ad88c428c50e86cd78da2a9ecd027add2f9d6ff9 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 20 Jan 2022 22:32:55 +0300 Subject: Avoid a crash on MyRocks data inconsistency. In ha_rocksdb::open(), check if the number of indexes seen from the SQL layer matches the number of indexes in the internal MyRocks data dictionary. Produce an error if there is a mismatch. (If we don't produce this error, we are likely to crash as soon as we attempt to use an index) --- storage/rocksdb/ha_rocksdb.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 8d2080187ef..1cb1a3517c5 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -6668,6 +6668,17 @@ int ha_rocksdb::open(const char *const name, int mode, uint test_if_locked) { "dictionary"); DBUG_RETURN(HA_ERR_ROCKSDB_INVALID_TABLE); } + if (m_tbl_def->m_key_count != table->s->keys + has_hidden_pk(table)? 1:0) + { + sql_print_error("MyRocks: DDL mismatch: .frm file has %u indexes, " + "MyRocks has %u (%s hidden pk)", + table->s->keys, m_tbl_def->m_key_count, + has_hidden_pk(table)? "1" : "no"); + my_error(ER_INTERNAL_ERROR, MYF(0), + "MyRocks: DDL mismatch. Check the error log for details"); + DBUG_RETURN(HA_ERR_ROCKSDB_INVALID_TABLE); + } + m_lock_rows = RDB_LOCK_NONE; m_key_descr_arr = m_tbl_def->m_key_descr_arr; -- cgit v1.2.1 From fa7a67ff499582fad6e4f1ff8198689325dee0dd Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 20 Jan 2022 22:52:41 +0300 Subject: MDEV-27149: Add rocksdb_ignore_datadic_errors Add a --rocksdb_ignore_datadic_errors plugin option for MyRocks. The default is 0, and this means MyRocks will call abort() if it detects a DDL mismatch. Setting rocksdb_ignore_datadic_errors=1 makes MyRocks to try to ignore the errors and allow to start the server for repairs. --- storage/rocksdb/ha_rocksdb.cc | 50 ++++++++++++++++++++-- storage/rocksdb/ha_rocksdb.h | 2 + .../rocksdb/mysql-test/rocksdb/r/rocksdb.result | 1 + .../r/rocksdb_ignore_datadic_errors_basic.result | 7 +++ .../t/rocksdb_ignore_datadic_errors_basic.test | 6 +++ storage/rocksdb/rdb_datadic.cc | 6 +++ 6 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 storage/rocksdb/mysql-test/rocksdb_sys_vars/r/rocksdb_ignore_datadic_errors_basic.result create mode 100644 storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_ignore_datadic_errors_basic.test diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 1cb1a3517c5..b39db830323 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -637,6 +637,8 @@ static my_bool rocksdb_large_prefix = 0; static my_bool rocksdb_allow_to_start_after_corruption = 0; static char* rocksdb_git_hash; +uint32_t rocksdb_ignore_datadic_errors = 0; + char *compression_types_val= const_cast(get_rocksdb_supported_compression_types()); static unsigned long rocksdb_write_policy = @@ -1907,6 +1909,15 @@ static MYSQL_SYSVAR_UINT( nullptr, nullptr, 1 /* default value */, 0 /* min value */, 2 /* max value */, 0); +static MYSQL_SYSVAR_UINT( + ignore_datadic_errors, rocksdb_ignore_datadic_errors, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Ignore MyRocks' data directory errors. " + "(CAUTION: Use only to start the server and perform repairs. Do NOT use " + "for regular operation)", + nullptr, nullptr, 0 /* default value */, 0 /* min value */, + 1 /* max value */, 0); + static MYSQL_SYSVAR_STR(datadir, rocksdb_datadir, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, "RocksDB data directory", nullptr, nullptr, @@ -2142,6 +2153,8 @@ static struct st_mysql_sys_var *rocksdb_system_variables[] = { MYSQL_SYSVAR(rollback_on_timeout), MYSQL_SYSVAR(enable_insert_with_update_caching), + + MYSQL_SYSVAR(ignore_datadic_errors), nullptr}; static rocksdb::WriteOptions rdb_get_rocksdb_write_options( @@ -5176,6 +5189,13 @@ static int rocksdb_init_func(void *const p) { DBUG_RETURN(1); } + if (rocksdb_ignore_datadic_errors) + { + sql_print_information( + "CAUTION: Running with rocksdb_ignore_datadic_errors=1. " + " This should only be used to perform repairs"); + } + if (rdb_check_rocksdb_corruption()) { // NO_LINT_DEBUG sql_print_error( @@ -5607,7 +5627,14 @@ static int rocksdb_init_func(void *const p) { if (ddl_manager.init(&dict_manager, &cf_manager, rocksdb_validate_tables)) { // NO_LINT_DEBUG sql_print_error("RocksDB: Failed to initialize DDL manager."); - DBUG_RETURN(HA_EXIT_FAILURE); + + if (rocksdb_ignore_datadic_errors) + { + sql_print_error("RocksDB: rocksdb_ignore_datadic_errors=1, " + "trying to continue"); + } + else + DBUG_RETURN(HA_EXIT_FAILURE); } Rdb_sst_info::init(rdb); @@ -6674,9 +6701,18 @@ int ha_rocksdb::open(const char *const name, int mode, uint test_if_locked) { "MyRocks has %u (%s hidden pk)", table->s->keys, m_tbl_def->m_key_count, has_hidden_pk(table)? "1" : "no"); - my_error(ER_INTERNAL_ERROR, MYF(0), - "MyRocks: DDL mismatch. Check the error log for details"); - DBUG_RETURN(HA_ERR_ROCKSDB_INVALID_TABLE); + + if (rocksdb_ignore_datadic_errors) + { + sql_print_error("MyRocks: rocksdb_ignore_datadic_errors=1, " + "trying to continue"); + } + else + { + my_error(ER_INTERNAL_ERROR, MYF(0), + "MyRocks: DDL mismatch. Check the error log for details"); + DBUG_RETURN(HA_ERR_ROCKSDB_INVALID_TABLE); + } } @@ -11558,6 +11594,12 @@ void Rdb_drop_index_thread::run() { "from cf id %u. MyRocks data dictionary may " "get corrupted.", d.cf_id); + if (rocksdb_ignore_datadic_errors) + { + sql_print_error("RocksDB: rocksdb_ignore_datadic_errors=1, " + "trying to continue"); + continue; + } abort(); } rocksdb::ColumnFamilyHandle *cfh = cf_manager.get_cf(d.cf_id); diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h index 4a379cd638a..b53ac851f4f 100644 --- a/storage/rocksdb/ha_rocksdb.h +++ b/storage/rocksdb/ha_rocksdb.h @@ -1059,6 +1059,8 @@ const int MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL= MariaDB_PLUGIN_MATURITY_STABLE; extern bool prevent_myrocks_loading; +extern uint32_t rocksdb_ignore_datadic_errors; + void sql_print_verbose_info(const char *format, ...); } // namespace myrocks diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result index 11cffac070f..71ec4d2344d 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result @@ -932,6 +932,7 @@ rocksdb_force_flush_memtable_now OFF rocksdb_force_index_records_in_range 0 rocksdb_git_hash # rocksdb_hash_index_allow_collision ON +rocksdb_ignore_datadic_errors 0 rocksdb_ignore_unknown_options ON rocksdb_index_type kBinarySearch rocksdb_info_log_level error_level diff --git a/storage/rocksdb/mysql-test/rocksdb_sys_vars/r/rocksdb_ignore_datadic_errors_basic.result b/storage/rocksdb/mysql-test/rocksdb_sys_vars/r/rocksdb_ignore_datadic_errors_basic.result new file mode 100644 index 00000000000..daa70a80683 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb_sys_vars/r/rocksdb_ignore_datadic_errors_basic.result @@ -0,0 +1,7 @@ +SET @start_global_value = @@global.ROCKSDB_IGNORE_DATADIC_ERRORS; +SELECT @start_global_value; +@start_global_value +0 +"Trying to set variable @@global.ROCKSDB_IGNORE_DATADIC_ERRORS to 444. It should fail because it is readonly." +SET @@global.ROCKSDB_IGNORE_DATADIC_ERRORS = 444; +ERROR HY000: Variable 'rocksdb_ignore_datadic_errors' is a read only variable diff --git a/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_ignore_datadic_errors_basic.test b/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_ignore_datadic_errors_basic.test new file mode 100644 index 00000000000..b412a018869 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_ignore_datadic_errors_basic.test @@ -0,0 +1,6 @@ +--source include/have_rocksdb.inc + +--let $sys_var=ROCKSDB_IGNORE_DATADIC_ERRORS +--let $read_only=1 +--let $session=0 +--source include/rocksdb_sys_var.inc diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc index 31bc40b1df9..45bb665654c 100644 --- a/storage/rocksdb/rdb_datadic.cc +++ b/storage/rocksdb/rdb_datadic.cc @@ -5240,6 +5240,12 @@ void Rdb_dict_manager::log_start_drop_index(GL_INDEX_ID gl_index_id, "from index id (%u,%u). MyRocks data dictionary may " "get corrupted.", gl_index_id.cf_id, gl_index_id.index_id); + if (rocksdb_ignore_datadic_errors) + { + sql_print_error("RocksDB: rocksdb_ignore_datadic_errors=1, " + "trying to continue"); + return; + } abort(); } } -- cgit v1.2.1 From c1d7b4575e67bd0ef458457859cdf7de32b3d4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 21 Jan 2022 14:43:59 +0200 Subject: MDEV-26870 --skip-symbolic-links does not disallow .isl file creation The InnoDB DATA DIRECTORY attribute is not implemented via symbolic links but something similar, *.isl files that contain the names of data files. InnoDB failed to ignore the DATA DIRECTORY attribute even though the server was started with --skip-symbolic-links. Native ALTER TABLE in InnoDB will retain the DATA DIRECTORY attribute of the table, no matter if the table will be rebuilt or not. Generic ALTER TABLE (with ALGORITHM=COPY) as well as TRUNCATE TABLE will discard the DATA DIRECTORY attribute. All tests have been run with and without the ./mtr option --mysqld=--skip-symbolic-links and some tests that use the InnoDB DATA DIRECTORY attribute have been adjusted for this. --- include/my_sys.h | 4 +- mysql-test/r/information_schema_inno.result | 1 - .../suite/encryption/t/innodb-first-page-read.test | 1 + .../suite/innodb/r/skip_symbolic_links.result | 54 ++++++++++++++++++++++ mysql-test/suite/innodb/t/101_compatibility.test | 1 + .../suite/innodb/t/create_isl_with_direct.test | 1 + mysql-test/suite/innodb/t/innodb-wl5980-alter.test | 1 + mysql-test/suite/innodb/t/innodb-wl5980-debug.test | 1 + mysql-test/suite/innodb/t/restart.test | 1 + mysql-test/suite/innodb/t/skip_symbolic_links.opt | 1 + mysql-test/suite/innodb/t/skip_symbolic_links.test | 51 ++++++++++++++++++++ mysql-test/suite/innodb_zip/t/restart.test | 1 + .../create_with_data_directory_during_backup.test | 1 + mysql-test/suite/mariabackup/data_directory.test | 1 + .../suite/mariabackup/partition_datadir.test | 1 + .../suite/parts/t/alter_data_directory_innodb.test | 1 + .../suite/parts/t/reorganize_partition_innodb.test | 1 + mysql-test/t/information_schema_inno.test | 4 +- storage/innobase/handler/ha_innodb.cc | 19 +++++--- 19 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 mysql-test/suite/innodb/r/skip_symbolic_links.result create mode 100644 mysql-test/suite/innodb/t/skip_symbolic_links.opt create mode 100644 mysql-test/suite/innodb/t/skip_symbolic_links.test diff --git a/include/my_sys.h b/include/my_sys.h index 1d2fff0e476..d2411223841 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2010, 2021, MariaDB Corporation. + Copyright (c) 2010, 2022, 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 @@ -276,7 +276,7 @@ extern int my_umask_dir, my_recived_signals, /* Signals we have got */ my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */ my_dont_interrupt; /* call remember_intr when set */ -extern my_bool my_use_symdir; +extern MYSQL_PLUGIN_IMPORT my_bool my_use_symdir; extern ulong my_default_record_cache_size; extern MYSQL_PLUGIN_IMPORT my_bool my_disable_locking; diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result index 7755d112f8e..fa81e4ef307 100644 --- a/mysql-test/r/information_schema_inno.result +++ b/mysql-test/r/information_schema_inno.result @@ -1,4 +1,3 @@ -DROP TABLE IF EXISTS t1,t2,t3; CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id, id), FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE CASCADE, diff --git a/mysql-test/suite/encryption/t/innodb-first-page-read.test b/mysql-test/suite/encryption/t/innodb-first-page-read.test index d661e4565d2..a0b3ca3f0ff 100644 --- a/mysql-test/suite/encryption/t/innodb-first-page-read.test +++ b/mysql-test/suite/encryption/t/innodb-first-page-read.test @@ -1,6 +1,7 @@ -- source include/have_innodb.inc -- source include/have_file_key_management_plugin.inc -- source include/not_embedded.inc +-- source include/have_symlink.inc --disable_warnings SET GLOBAL innodb_file_format = `Barracuda`; diff --git a/mysql-test/suite/innodb/r/skip_symbolic_links.result b/mysql-test/suite/innodb/r/skip_symbolic_links.result new file mode 100644 index 00000000000..4dc036765a0 --- /dev/null +++ b/mysql-test/suite/innodb/r/skip_symbolic_links.result @@ -0,0 +1,54 @@ +SELECT @@have_symlink; +@@have_symlink +DISABLED +CREATE TABLE t1(a INT) ENGINE=InnoDB DATA DIRECTORY 'MYSQL_TMP_DIR'; +Warnings: +Warning 1618 option ignored +DROP TABLE t1; +CREATE TABLE t1(a INT) ENGINE=InnoDB; +ALTER TABLE t1 DATA DIRECTORY 'MYSQL_TMP_DIR'; +Warnings: +Warning 1618 option ignored +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(a INT PRIMARY KEY, b INT) ENGINE=InnoDB +DATA DIRECTORY 'MYSQL_TMP_DIR'; +CREATE TABLE t2(a INT PRIMARY KEY, b INT) ENGINE=InnoDB +DATA DIRECTORY 'MYSQL_TMP_DIR'; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +ALTER TABLE t1 FORCE, ALGORITHM=INPLACE; +Warnings: +Warning 1618 option ignored +ALTER TABLE t2 FORCE, ALGORITHM=COPY; +Warnings: +Warning 1618 option ignored +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +Warnings: +Warning 1618 option ignored +t1.ibd +DROP TABLE t2; +RENAME TABLE t1 TO t2; +ALTER TABLE t2 ADD UNIQUE INDEX(b), RENAME TO t3; +Warnings: +Warning 1618 option ignored +ALTER TABLE t3 RENAME TO t2; +ALTER TABLE t2 DROP INDEX b, RENAME TO t1; +Warnings: +Warning 1618 option ignored +ALTER TABLE t1 CHANGE b c INT; +Warnings: +Warning 1618 option ignored +ALTER TABLE t1 CHANGE c b INT NOT NULL; +Warnings: +Warning 1618 option ignored +t1.ibd +TRUNCATE TABLE t1; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/101_compatibility.test b/mysql-test/suite/innodb/t/101_compatibility.test index eb3d3b0c014..8b6c971c3a4 100644 --- a/mysql-test/suite/innodb/t/101_compatibility.test +++ b/mysql-test/suite/innodb/t/101_compatibility.test @@ -1,5 +1,6 @@ --source include/innodb_page_size.inc --source include/not_embedded.inc +--source include/have_symlink.inc -- echo # -- echo # MDEV-11623 MariaDB 10.1 fails to start datadir created with diff --git a/mysql-test/suite/innodb/t/create_isl_with_direct.test b/mysql-test/suite/innodb/t/create_isl_with_direct.test index 1427264e13e..2092d03b72f 100644 --- a/mysql-test/suite/innodb/t/create_isl_with_direct.test +++ b/mysql-test/suite/innodb/t/create_isl_with_direct.test @@ -1,5 +1,6 @@ --source include/not_embedded.inc --source include/have_innodb.inc +--source include/have_symlink.inc --disable_query_log CALL mtr.add_suppression(".*Failed to set O_DIRECT on file.*"); diff --git a/mysql-test/suite/innodb/t/innodb-wl5980-alter.test b/mysql-test/suite/innodb/t/innodb-wl5980-alter.test index a0d80ea8374..9b51612854f 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5980-alter.test +++ b/mysql-test/suite/innodb/t/innodb-wl5980-alter.test @@ -4,6 +4,7 @@ --echo # --source include/have_innodb.inc +--source include/have_symlink.inc --disable_query_log # These values can change during the test diff --git a/mysql-test/suite/innodb/t/innodb-wl5980-debug.test b/mysql-test/suite/innodb/t/innodb-wl5980-debug.test index 2c5e2b48870..dbb8ad33676 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5980-debug.test +++ b/mysql-test/suite/innodb/t/innodb-wl5980-debug.test @@ -8,6 +8,7 @@ --source include/not_embedded.inc --source include/have_debug.inc --source include/have_innodb.inc +--source include/have_symlink.inc # These messages are expected in the log call mtr.add_suppression("Cannot find space id [0-9]+ in the tablespace memory cache"); diff --git a/mysql-test/suite/innodb/t/restart.test b/mysql-test/suite/innodb/t/restart.test index 3f28b3976c3..16c6d20f621 100644 --- a/mysql-test/suite/innodb/t/restart.test +++ b/mysql-test/suite/innodb/t/restart.test @@ -1,5 +1,6 @@ --source include/innodb_page_size.inc --source include/not_embedded.inc +--source include/have_symlink.inc let datadir= `select @@datadir`; let page_size= `select @@innodb_page_size`; diff --git a/mysql-test/suite/innodb/t/skip_symbolic_links.opt b/mysql-test/suite/innodb/t/skip_symbolic_links.opt new file mode 100644 index 00000000000..c7844699cdb --- /dev/null +++ b/mysql-test/suite/innodb/t/skip_symbolic_links.opt @@ -0,0 +1 @@ +--skip-symbolic-links diff --git a/mysql-test/suite/innodb/t/skip_symbolic_links.test b/mysql-test/suite/innodb/t/skip_symbolic_links.test new file mode 100644 index 00000000000..b5274d220c8 --- /dev/null +++ b/mysql-test/suite/innodb/t/skip_symbolic_links.test @@ -0,0 +1,51 @@ +--source include/have_innodb.inc +--source include/not_windows.inc + +SELECT @@have_symlink; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval CREATE TABLE t1(a INT) ENGINE=InnoDB DATA DIRECTORY '$MYSQL_TMP_DIR'; +DROP TABLE t1; +CREATE TABLE t1(a INT) ENGINE=InnoDB; + +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval ALTER TABLE t1 DATA DIRECTORY '$MYSQL_TMP_DIR'; +SHOW CREATE TABLE t1; + +DROP TABLE t1; + +--let $restart_parameters=--symbolic-links +--source include/restart_mysqld.inc + +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval CREATE TABLE t1(a INT PRIMARY KEY, b INT) ENGINE=InnoDB +DATA DIRECTORY '$MYSQL_TMP_DIR'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval CREATE TABLE t2(a INT PRIMARY KEY, b INT) ENGINE=InnoDB +DATA DIRECTORY '$MYSQL_TMP_DIR'; + +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; + +--let $restart_parameters= +--source include/restart_mysqld.inc + +# Native ALTER will retain DATA DIRECTORY +ALTER TABLE t1 FORCE, ALGORITHM=INPLACE; +ALTER TABLE t2 FORCE, ALGORITHM=COPY; +OPTIMIZE TABLE t1; +--list_files $MYSQL_TMP_DIR/test +DROP TABLE t2; + +RENAME TABLE t1 TO t2; +ALTER TABLE t2 ADD UNIQUE INDEX(b), RENAME TO t3; + +ALTER TABLE t3 RENAME TO t2; +ALTER TABLE t2 DROP INDEX b, RENAME TO t1; +ALTER TABLE t1 CHANGE b c INT; +ALTER TABLE t1 CHANGE c b INT NOT NULL; + +--list_files $MYSQL_TMP_DIR/test +# TRUNCATE TABLE will discard DATA DIRECTORY. +TRUNCATE TABLE t1; +--list_files $MYSQL_TMP_DIR/test +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_zip/t/restart.test b/mysql-test/suite/innodb_zip/t/restart.test index 05ac8274278..1c4af461dfc 100644 --- a/mysql-test/suite/innodb_zip/t/restart.test +++ b/mysql-test/suite/innodb_zip/t/restart.test @@ -4,6 +4,7 @@ --source include/innodb_page_size_small.inc --source include/have_partition.inc --source include/not_embedded.inc +--source include/have_symlink.inc SET default_storage_engine=InnoDB; LET $MYSQLD_DATADIR = `select @@datadir`; LET $INNODB_PAGE_SIZE = `select @@innodb_page_size`; diff --git a/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.test b/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.test index d0cb83d069f..f01028b6494 100644 --- a/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.test +++ b/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.test @@ -1,4 +1,5 @@ --source include/have_debug.inc +--source include/have_symlink.inc let $table_data_dir=$MYSQLTEST_VARDIR/tmp/ddir; let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; mkdir $table_data_dir; diff --git a/mysql-test/suite/mariabackup/data_directory.test b/mysql-test/suite/mariabackup/data_directory.test index 50789a34c78..a89b7bdccc4 100644 --- a/mysql-test/suite/mariabackup/data_directory.test +++ b/mysql-test/suite/mariabackup/data_directory.test @@ -1,3 +1,4 @@ +--source include/have_symlink.inc let $table_data_dir=$MYSQLTEST_VARDIR/ddir; mkdir $table_data_dir; --replace_result $table_data_dir table_data_dir diff --git a/mysql-test/suite/mariabackup/partition_datadir.test b/mysql-test/suite/mariabackup/partition_datadir.test index c525d34a02c..36520d331bf 100644 --- a/mysql-test/suite/mariabackup/partition_datadir.test +++ b/mysql-test/suite/mariabackup/partition_datadir.test @@ -1,4 +1,5 @@ --source include/have_partition.inc +--source include/have_symlink.inc let $targetdir=$MYSQLTEST_VARDIR/backup; mkdir $targetdir; mkdir $MYSQLTEST_VARDIR/partitdata; diff --git a/mysql-test/suite/parts/t/alter_data_directory_innodb.test b/mysql-test/suite/parts/t/alter_data_directory_innodb.test index ac15e9bec6c..def04e14173 100644 --- a/mysql-test/suite/parts/t/alter_data_directory_innodb.test +++ b/mysql-test/suite/parts/t/alter_data_directory_innodb.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_partition.inc +--source include/have_symlink.inc --echo # --echo # MDEV-15953 Alter InnoDB Partitioned Table Moves Files (which were originally not in the datadir) to the datadir diff --git a/mysql-test/suite/parts/t/reorganize_partition_innodb.test b/mysql-test/suite/parts/t/reorganize_partition_innodb.test index db73650c54b..77109c38c96 100644 --- a/mysql-test/suite/parts/t/reorganize_partition_innodb.test +++ b/mysql-test/suite/parts/t/reorganize_partition_innodb.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_partition.inc +--source include/have_symlink.inc --echo # --echo # MDEV-15953 Alter InnoDB Partitioned Table Moves Files (which were originally not in the datadir) to the datadir diff --git a/mysql-test/t/information_schema_inno.test b/mysql-test/t/information_schema_inno.test index 9a9658e9027..89a2a8cc08e 100644 --- a/mysql-test/t/information_schema_inno.test +++ b/mysql-test/t/information_schema_inno.test @@ -1,8 +1,6 @@ -- source include/testdb_only.inc -- source include/have_innodb.inc ---disable_warnings -DROP TABLE IF EXISTS t1,t2,t3; ---enable_warnings +-- source include/have_symlink.inc # # Test for KEY_COLUMN_USAGE & TABLE_CONSTRAINTS tables diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5d78e64a06b..889aee0d47e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2020, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -11710,9 +11710,12 @@ create_table_info_t::create_options_are_invalid() break; } - if (m_create_info->data_file_name - && m_create_info->data_file_name[0] != '\0' - && !create_option_data_directory_is_valid()) { + if (!m_create_info->data_file_name + || !m_create_info->data_file_name[0]) { + } else if (!my_use_symdir) { + my_error(WARN_OPTION_IGNORED, MYF(ME_JUST_WARNING), + "DATA DIRECTORY"); + } else if (!create_option_data_directory_is_valid()) { ret = "DATA DIRECTORY"; } @@ -11986,7 +11989,8 @@ create_table_info_t::parse_table_name( CREATE TABLE ... DATA DIRECTORY={path} TABLESPACE={name}... ; we ignore the DATA DIRECTORY. */ if (m_create_info->data_file_name - && m_create_info->data_file_name[0] != '\0') { + && m_create_info->data_file_name[0] + && my_use_symdir) { if (!create_option_data_directory_is_valid()) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, @@ -12457,8 +12461,9 @@ create_table_info_t::set_tablespace_type( used with TEMPORARY tables. */ m_use_data_dir = m_use_file_per_table - && (m_create_info->data_file_name != NULL) - && (m_create_info->data_file_name[0] != '\0'); + && m_create_info->data_file_name + && m_create_info->data_file_name[0] + && my_use_symdir; } /** Initialize the create_table_info_t object. -- cgit v1.2.1 From c9beef43154a199bfcd9f71049c011a2ed77ca74 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 15 Jan 2022 17:33:28 +0100 Subject: don't build with OpenSSL 3.0, it doesn't work before MDEV-25785 --- cmake/ssl.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake index 1b238826311..707aa4a017f 100644 --- a/cmake/ssl.cmake +++ b/cmake/ssl.cmake @@ -127,7 +127,7 @@ MACRO (MYSQL_CHECK_SSL) ENDIF() FIND_PACKAGE(OpenSSL) SET_PACKAGE_PROPERTIES(OpenSSL PROPERTIES TYPE RECOMMENDED) - IF(OPENSSL_FOUND) + IF(OPENSSL_FOUND AND OPENSSL_VERSION AND OPENSSL_VERSION VERSION_LESS "3.0.0") SET(OPENSSL_LIBRARY ${OPENSSL_SSL_LIBRARY}) SET(SSL_SOURCES "") SET(SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) -- cgit v1.2.1 From 4504e6d14e71f53043c75b80e83f25938ac63bb1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 21 Jan 2022 12:40:20 +0100 Subject: test cases for MySQL bugs also fix a comment, and update a macro just in case --- include/errmsg.h | 5 +++-- mysql-test/r/alter_user.result | 10 ++++++++++ mysql-test/r/trigger.result | 7 +++++++ mysql-test/suite/federated/rpl.result | 18 ++++++++++++++++++ mysql-test/suite/federated/rpl.test | 19 +++++++++++++++++++ mysql-test/suite/vcol/r/not_supported.result | 8 ++++++++ mysql-test/suite/vcol/t/not_supported.test | 10 ++++++++++ mysql-test/t/alter_user.test | 11 +++++++++++ mysql-test/t/trigger.test | 8 ++++++++ sql/sql_show.cc | 2 +- 10 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 mysql-test/suite/federated/rpl.result create mode 100644 mysql-test/suite/federated/rpl.test diff --git a/include/errmsg.h b/include/errmsg.h index c0c4cfc58be..bd086bba05b 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -36,8 +36,9 @@ extern const char *client_errors[]; /* Error messages */ #define CR_MIN_ERROR 2000 /* For easier client code */ #define CR_MAX_ERROR 2999 #if !defined(ER) -#define ER(X) (((X) >= CR_ERROR_FIRST && (X) <= CR_ERROR_LAST)? \ - client_errors[(X)-CR_ERROR_FIRST]: client_errors[CR_UNKNOWN_ERROR]) +#define ER(X) (((X) >= CR_ERROR_FIRST && (X) <= CR_ERROR_LAST) \ + ? client_errors[(X)-CR_ERROR_FIRST] \ + : client_errors[CR_UNKNOWN_ERROR-CR_ERROR_FIRST]) #endif #define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ diff --git a/mysql-test/r/alter_user.result b/mysql-test/r/alter_user.result index b67705c4fc4..a9141cc3dba 100644 --- a/mysql-test/r/alter_user.result +++ b/mysql-test/r/alter_user.result @@ -91,3 +91,13 @@ select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time % foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 10 20 30 40 N N 0.000000 drop user foo; +# +# Bug #29882299: ALTER USER ... IDENTIFIED WITH ... BY ... SHOULD BE A PRIVILEGED OPERATION +# +create user foo@localhost; +connect x,localhost,foo; +alter user current_user identified with 'something'; +ERROR 42000: Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation +connection default; +disconnect x; +drop user foo@localhost; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index b08139a346b..c22531f7e72 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -2425,5 +2425,12 @@ CREATE TRIGGER t1_trigger BEFORE INSERT ON t1 FOR EACH ROW BEGIN END; INSERT INTO t1 () VALUES (); DROP TABLE t1; # +# Bug#33141958 - THE FIRST ASAN UAF ISSUE OF MYSQL SERVER +# +create table t1 (a int); +create trigger tr1 after insert on t1 for each row alter table t1 tablespace s2; +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger +drop table t1; +# # End of 10.2 tests # diff --git a/mysql-test/suite/federated/rpl.result b/mysql-test/suite/federated/rpl.result new file mode 100644 index 00000000000..71821411c91 --- /dev/null +++ b/mysql-test/suite/federated/rpl.result @@ -0,0 +1,18 @@ +include/master-slave.inc +[connection master] +create table t1 (a int primary key, b int); +connection slave; +rename table t1 to t2; +create table t1 (a int primary key, b int) engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t2'; +connection master; +insert t1 values (1,1),(2,2),(3,1); +delete from t1 where a=2; +connection slave; +select * from t1; +a b +1 1 +3 1 +drop table t2; +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/federated/rpl.test b/mysql-test/suite/federated/rpl.test new file mode 100644 index 00000000000..6ec4bec5a1a --- /dev/null +++ b/mysql-test/suite/federated/rpl.test @@ -0,0 +1,19 @@ +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +create table t1 (a int primary key, b int); + +sync_slave_with_master; +rename table t1 to t2; +evalp create table t1 (a int primary key, b int) engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t2'; +connection master; + +insert t1 values (1,1),(2,2),(3,1); +delete from t1 where a=2; +sync_slave_with_master; +select * from t1; +drop table t2; + +connection master; +drop table t1; +source include/rpl_end.inc; diff --git a/mysql-test/suite/vcol/r/not_supported.result b/mysql-test/suite/vcol/r/not_supported.result index c804cf220d2..d8703f755da 100644 --- a/mysql-test/suite/vcol/r/not_supported.result +++ b/mysql-test/suite/vcol/r/not_supported.result @@ -34,3 +34,11 @@ select * from t8; a b v 1234567890 2 2009-02-14 00:31:30 drop table t1, t3_ok, t8; +# +# Bug#33141966 - INCONSISTENT BEHAVIOR IF A COLUMN OF TYPE SERIAL IS SET AS GENERATED +# +create table t1 (a int, b serial as (a+1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'as (a+1))' at line 1 +# +# End of 10.2 tests +# diff --git a/mysql-test/suite/vcol/t/not_supported.test b/mysql-test/suite/vcol/t/not_supported.test index 1ea7970523a..2b5baf4ff4b 100644 --- a/mysql-test/suite/vcol/t/not_supported.test +++ b/mysql-test/suite/vcol/t/not_supported.test @@ -39,3 +39,13 @@ select * from t1; select * from t8; drop table t1, t3_ok, t8; + +--echo # +--echo # Bug#33141966 - INCONSISTENT BEHAVIOR IF A COLUMN OF TYPE SERIAL IS SET AS GENERATED +--echo # +--error ER_PARSE_ERROR +create table t1 (a int, b serial as (a+1)); + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/t/alter_user.test b/mysql-test/t/alter_user.test index 3a1052a98f6..e71fba271b1 100644 --- a/mysql-test/t/alter_user.test +++ b/mysql-test/t/alter_user.test @@ -77,3 +77,14 @@ alter user foo with MAX_QUERIES_PER_HOUR 10 MAX_USER_CONNECTIONS 40; select * from mysql.user where user = 'foo'; drop user foo; + +--echo # +--echo # Bug #29882299: ALTER USER ... IDENTIFIED WITH ... BY ... SHOULD BE A PRIVILEGED OPERATION +--echo # +create user foo@localhost; +--connect x,localhost,foo +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +alter user current_user identified with 'something'; +--connection default +--disconnect x +drop user foo@localhost; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 78ee212d848..774b7e0dc2f 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -2757,6 +2757,14 @@ CREATE TRIGGER t1_trigger BEFORE INSERT ON t1 FOR EACH ROW BEGIN END; INSERT INTO t1 () VALUES (); DROP TABLE t1; +--echo # +--echo # Bug#33141958 - THE FIRST ASAN UAF ISSUE OF MYSQL SERVER +--echo # +create table t1 (a int); +--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger tr1 after insert on t1 for each row alter table t1 tablespace s2; +drop table t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9483db9eff9..c708849d049 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2683,6 +2683,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) tmp_sctx->host_or_ip : tmp_sctx->host ? tmp_sctx->host : ""); thd_info->command=(int) tmp->get_command(); + /* Lock THD mutex that protects its data when looking at it. */ mysql_mutex_lock(&tmp->LOCK_thd_data); if ((thd_info->db= tmp->db)) // Safe test thd_info->db= thd->strdup(thd_info->db); @@ -2694,7 +2695,6 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) if (mysys_var) mysql_mutex_unlock(&mysys_var->mutex); - /* Lock THD mutex that protects its data when looking at it. */ if (tmp->query()) { uint length= MY_MIN(max_query_length, tmp->query_length()); -- cgit v1.2.1 From 991d5dce323c4e22357f614afc1b9dfed4000567 Mon Sep 17 00:00:00 2001 From: Maheedhar PV Date: Sat, 13 Nov 2021 16:12:05 +0530 Subject: Bug#31374305 - FORMAT() NOT DISPLAYING WHOLE NUMBER SIDE CORRECTLY FOR ES_MX AND ES_ES LOCALES Changed the grouping and decimal separator for spanish locales as per ICU. Change-Id: I5d80fa59d3e66372d904e17c22c532d4dd2c565b --- mysql-test/r/func_str.result | 53 ++++++++++++++++++++++ mysql-test/suite/plugins/r/locales.result | 36 +++++++-------- mysql-test/t/func_str.test | 36 +++++++++++++++ sql/sql_locale.cc | 74 +++++++++++++++---------------- 4 files changed, 144 insertions(+), 55 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index f9346a25151..207f9650abb 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -4845,5 +4845,58 @@ SELECT NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux'); NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux') NULL # +# Bug#31374305 - FORMAT() NOT DISPLAYING WHOLE NUMBER SIDE CORRECTLY +# FOR ES_MX AND ES_ES LOCALES +# +CREATE PROCEDURE load_locale_format_table() +BEGIN +DECLARE locale_list VARCHAR(1000) DEFAULT ' + es_AR,es_BO,es_CL,es_CO,es_CR,es_DO,es_EC,es_ES,es_GT,es_HN, + es_MX,es_NI,es_PA,es_PE,es_PR,es_PY,es_SV,es_US,es_UY,es_VE'; +SET @fmt_stmt = 'INSERT INTO locale_format VALUES + (?, FORMAT(12131254123412541,2,?));'; +PREPARE stmt FROM @fmt_stmt; +WHILE locale_list != '' DO +/* get the first locale from the list */ +SET @locale = +TRIM(REPLACE((SUBSTRING_INDEX(locale_list, ',', 1)), '\n','')); +EXECUTE stmt USING @locale, @locale; +/* remove the first locale from the list */ +IF LOCATE(',', locale_list) > 0 THEN +SET locale_list = +SUBSTRING(locale_list, LOCATE(',', locale_list) + 1); +ELSE +SET locale_list = ''; +END IF; +END WHILE; +DEALLOCATE PREPARE stmt; +END| +CREATE TABLE locale_format(locale VARCHAR(10), formatted_string VARCHAR(100)); +CALL load_locale_format_table(); +SELECT * FROM locale_format; +locale formatted_string +es_AR 12.131.254.123.412.541,00 +es_BO 12.131.254.123.412.541,00 +es_CL 12.131.254.123.412.541,00 +es_CO 12.131.254.123.412.541,00 +es_CR 12 131 254 123 412 541,00 +es_DO 12,131,254,123,412,541.00 +es_EC 12.131.254.123.412.541,00 +es_ES 12.131.254.123.412.541,00 +es_GT 12,131,254,123,412,541.00 +es_HN 12,131,254,123,412,541.00 +es_MX 12,131,254,123,412,541.00 +es_NI 12,131,254,123,412,541.00 +es_PA 12,131,254,123,412,541.00 +es_PE 12,131,254,123,412,541.00 +es_PR 12,131,254,123,412,541.00 +es_PY 12.131.254.123.412.541,00 +es_SV 12,131,254,123,412,541.00 +es_US 12,131,254,123,412,541.00 +es_UY 12.131.254.123.412.541,00 +es_VE 12.131.254.123.412.541,00 +DROP PROCEDURE load_locale_format_table; +DROP TABLE locale_format; +# # End of 10.2 tests # diff --git a/mysql-test/suite/plugins/r/locales.result b/mysql-test/suite/plugins/r/locales.result index 106bf22923c..2ea88493705 100644 --- a/mysql-test/suite/plugins/r/locales.result +++ b/mysql-test/suite/plugins/r/locales.result @@ -17,7 +17,7 @@ ID NAME DESCRIPTION MAX_MONTH_NAME_LENGTH MAX_DAY_NAME_LENGTH DECIMAL_POINT THOU 14 cs_CZ Czech - Czech Republic 8 7 , czech 15 da_DK Danish - Denmark 9 7 , . danish 16 de_AT German - Austria 9 10 , german -17 es_ES Spanish - Spain 10 9 , spanish +17 es_ES Spanish - Spain 10 9 , . spanish 18 et_EE Estonian - Estonia 9 9 , estonian 19 eu_ES Basque - Basque 9 10 , english 20 fi_FI Finnish - Finland 9 11 , english @@ -82,24 +82,24 @@ ID NAME DESCRIPTION MAX_MONTH_NAME_LENGTH MAX_DAY_NAME_LENGTH DECIMAL_POINT THOU 79 en_ZA English - South Africa 9 9 . , english 80 en_ZW English - Zimbabwe 9 9 . , english 81 es_AR Spanish - Argentina 10 9 , . spanish -82 es_BO Spanish - Bolivia 10 9 , spanish -83 es_CL Spanish - Chile 10 9 , spanish -84 es_CO Spanish - Columbia 10 9 , spanish -85 es_CR Spanish - Costa Rica 10 9 . spanish -86 es_DO Spanish - Dominican Republic 10 9 . spanish -87 es_EC Spanish - Ecuador 10 9 , spanish -88 es_GT Spanish - Guatemala 10 9 . spanish -89 es_HN Spanish - Honduras 10 9 . spanish -90 es_MX Spanish - Mexico 10 9 . spanish -91 es_NI Spanish - Nicaragua 10 9 . spanish -92 es_PA Spanish - Panama 10 9 . spanish -93 es_PE Spanish - Peru 10 9 . spanish -94 es_PR Spanish - Puerto Rico 10 9 . spanish -95 es_PY Spanish - Paraguay 10 9 , spanish -96 es_SV Spanish - El Salvador 10 9 . spanish +82 es_BO Spanish - Bolivia 10 9 , . spanish +83 es_CL Spanish - Chile 10 9 , . spanish +84 es_CO Spanish - Columbia 10 9 , . spanish +85 es_CR Spanish - Costa Rica 10 9 , spanish +86 es_DO Spanish - Dominican Republic 10 9 . , spanish +87 es_EC Spanish - Ecuador 10 9 , . spanish +88 es_GT Spanish - Guatemala 10 9 . , spanish +89 es_HN Spanish - Honduras 10 9 . , spanish +90 es_MX Spanish - Mexico 10 9 . , spanish +91 es_NI Spanish - Nicaragua 10 9 . , spanish +92 es_PA Spanish - Panama 10 9 . , spanish +93 es_PE Spanish - Peru 10 9 . , spanish +94 es_PR Spanish - Puerto Rico 10 9 . , spanish +95 es_PY Spanish - Paraguay 10 9 , . spanish +96 es_SV Spanish - El Salvador 10 9 . , spanish 97 es_US Spanish - United States 10 9 . , spanish -98 es_UY Spanish - Uruguay 10 9 , spanish -99 es_VE Spanish - Venezuela 10 9 , spanish +98 es_UY Spanish - Uruguay 10 9 , . spanish +99 es_VE Spanish - Venezuela 10 9 , . spanish 100 fr_BE French - Belgium 9 8 , . french 101 fr_CA French - Canada 9 8 , french 102 fr_CH French - Switzerland 9 8 , french diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 366aacb1945..06c62d1b902 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1944,6 +1944,42 @@ DROP TABLE t1; SELECT NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux'); +--echo # +--echo # Bug#31374305 - FORMAT() NOT DISPLAYING WHOLE NUMBER SIDE CORRECTLY +--echo # FOR ES_MX AND ES_ES LOCALES +--echo # + +DELIMITER |; +CREATE PROCEDURE load_locale_format_table() +BEGIN + DECLARE locale_list VARCHAR(1000) DEFAULT ' + es_AR,es_BO,es_CL,es_CO,es_CR,es_DO,es_EC,es_ES,es_GT,es_HN, + es_MX,es_NI,es_PA,es_PE,es_PR,es_PY,es_SV,es_US,es_UY,es_VE'; + SET @fmt_stmt = 'INSERT INTO locale_format VALUES + (?, FORMAT(12131254123412541,2,?));'; + PREPARE stmt FROM @fmt_stmt; + WHILE locale_list != '' DO + /* get the first locale from the list */ + SET @locale = + TRIM(REPLACE((SUBSTRING_INDEX(locale_list, ',', 1)), '\n','')); + EXECUTE stmt USING @locale, @locale; + /* remove the first locale from the list */ + IF LOCATE(',', locale_list) > 0 THEN + SET locale_list = + SUBSTRING(locale_list, LOCATE(',', locale_list) + 1); + ELSE + SET locale_list = ''; + END IF; + END WHILE; + DEALLOCATE PREPARE stmt; +END| +DELIMITER ;| + +CREATE TABLE locale_format(locale VARCHAR(10), formatted_string VARCHAR(100)); +CALL load_locale_format_table(); +SELECT * FROM locale_format; +DROP PROCEDURE load_locale_format_table; +DROP TABLE locale_format; --echo # --echo # End of 10.2 tests diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc index cc4bc0c175d..39ef6b22d13 100644 --- a/sql/sql_locale.cc +++ b/sql/sql_locale.cc @@ -564,8 +564,8 @@ MY_LOCALE my_locale_es_ES 10, 9, ',', /* decimal point es_ES */ - '\0', /* thousands_sep es_ES */ - "\x80\x80", /* grouping es_ES */ + '.', /* thousands_sep es_ES */ + "\x03\x03", /* grouping es_ES */ &global_errmsgs[es_ES] ); /***** LOCALE END es_ES *****/ @@ -2650,8 +2650,8 @@ MY_LOCALE my_locale_es_BO 10, 9, ',', /* decimal point es_BO */ - '\0', /* thousands_sep es_BO */ - "\x80\x80", /* grouping es_BO */ + '.', /* thousands_sep es_BO */ + "\x03\x03", /* grouping es_BO */ &global_errmsgs[es_ES] ); /***** LOCALE END es_BO *****/ @@ -2670,8 +2670,8 @@ MY_LOCALE my_locale_es_CL 10, 9, ',', /* decimal point es_CL */ - '\0', /* thousands_sep es_CL */ - "\x80\x80", /* grouping es_CL */ + '.', /* thousands_sep es_CL */ + "\x03\x03", /* grouping es_CL */ &global_errmsgs[es_ES] ); /***** LOCALE END es_CL *****/ @@ -2690,8 +2690,8 @@ MY_LOCALE my_locale_es_CO 10, 9, ',', /* decimal point es_CO */ - '\0', /* thousands_sep es_CO */ - "\x80\x80", /* grouping es_CO */ + '.', /* thousands_sep es_CO */ + "\x03\x03", /* grouping es_CO */ &global_errmsgs[es_ES] ); /***** LOCALE END es_CO *****/ @@ -2709,9 +2709,9 @@ MY_LOCALE my_locale_es_CR &my_locale_typelib_ab_day_names_es_ES, 10, 9, - '.', /* decimal point es_CR */ - '\0', /* thousands_sep es_CR */ - "\x80\x80", /* grouping es_CR */ + ',', /* decimal point es_CR */ + ' ', /* thousands_sep es_CR */ + "\x03\x03", /* grouping es_CR */ &global_errmsgs[es_ES] ); /***** LOCALE END es_CR *****/ @@ -2730,8 +2730,8 @@ MY_LOCALE my_locale_es_DO 10, 9, '.', /* decimal point es_DO */ - '\0', /* thousands_sep es_DO */ - "\x80\x80", /* grouping es_DO */ + ',', /* thousands_sep es_DO */ + "\x03\x03", /* grouping es_DO */ &global_errmsgs[es_ES] ); /***** LOCALE END es_DO *****/ @@ -2750,8 +2750,8 @@ MY_LOCALE my_locale_es_EC 10, 9, ',', /* decimal point es_EC */ - '\0', /* thousands_sep es_EC */ - "\x80\x80", /* grouping es_EC */ + '.', /* thousands_sep es_EC */ + "\x03\x03", /* grouping es_EC */ &global_errmsgs[es_ES] ); /***** LOCALE END es_EC *****/ @@ -2770,8 +2770,8 @@ MY_LOCALE my_locale_es_GT 10, 9, '.', /* decimal point es_GT */ - '\0', /* thousands_sep es_GT */ - "\x80\x80", /* grouping es_GT */ + ',', /* thousands_sep es_GT */ + "\x03\x03", /* grouping es_GT */ &global_errmsgs[es_ES] ); /***** LOCALE END es_GT *****/ @@ -2790,8 +2790,8 @@ MY_LOCALE my_locale_es_HN 10, 9, '.', /* decimal point es_HN */ - '\0', /* thousands_sep es_HN */ - "\x80\x80", /* grouping es_HN */ + ',', /* thousands_sep es_HN */ + "\x03\x03", /* grouping es_HN */ &global_errmsgs[es_ES] ); /***** LOCALE END es_HN *****/ @@ -2810,8 +2810,8 @@ MY_LOCALE my_locale_es_MX 10, 9, '.', /* decimal point es_MX */ - '\0', /* thousands_sep es_MX */ - "\x80\x80", /* grouping es_MX */ + ',', /* thousands_sep es_MX */ + "\x03\x03", /* grouping es_MX */ &global_errmsgs[es_ES] ); /***** LOCALE END es_MX *****/ @@ -2830,8 +2830,8 @@ MY_LOCALE my_locale_es_NI 10, 9, '.', /* decimal point es_NI */ - '\0', /* thousands_sep es_NI */ - "\x80\x80", /* grouping es_NI */ + ',', /* thousands_sep es_NI */ + "\x03\x03", /* grouping es_NI */ &global_errmsgs[es_ES] ); /***** LOCALE END es_NI *****/ @@ -2850,8 +2850,8 @@ MY_LOCALE my_locale_es_PA 10, 9, '.', /* decimal point es_PA */ - '\0', /* thousands_sep es_PA */ - "\x80\x80", /* grouping es_PA */ + ',', /* thousands_sep es_PA */ + "\x03\x03", /* grouping es_PA */ &global_errmsgs[es_ES] ); /***** LOCALE END es_PA *****/ @@ -2870,8 +2870,8 @@ MY_LOCALE my_locale_es_PE 10, 9, '.', /* decimal point es_PE */ - '\0', /* thousands_sep es_PE */ - "\x80\x80", /* grouping es_PE */ + ',', /* thousands_sep es_PE */ + "\x03\x03", /* grouping es_PE */ &global_errmsgs[es_ES] ); /***** LOCALE END es_PE *****/ @@ -2890,8 +2890,8 @@ MY_LOCALE my_locale_es_PR 10, 9, '.', /* decimal point es_PR */ - '\0', /* thousands_sep es_PR */ - "\x80\x80", /* grouping es_PR */ + ',', /* thousands_sep es_PR */ + "\x03\x03", /* grouping es_PR */ &global_errmsgs[es_ES] ); /***** LOCALE END es_PR *****/ @@ -2910,8 +2910,8 @@ MY_LOCALE my_locale_es_PY 10, 9, ',', /* decimal point es_PY */ - '\0', /* thousands_sep es_PY */ - "\x80\x80", /* grouping es_PY */ + '.', /* thousands_sep es_PY */ + "\x03\x03", /* grouping es_PY */ &global_errmsgs[es_ES] ); /***** LOCALE END es_PY *****/ @@ -2930,8 +2930,8 @@ MY_LOCALE my_locale_es_SV 10, 9, '.', /* decimal point es_SV */ - '\0', /* thousands_sep es_SV */ - "\x80\x80", /* grouping es_SV */ + ',', /* thousands_sep es_SV */ + "\x03\x03", /* grouping es_SV */ &global_errmsgs[es_ES] ); /***** LOCALE END es_SV *****/ @@ -2970,8 +2970,8 @@ MY_LOCALE my_locale_es_UY 10, 9, ',', /* decimal point es_UY */ - '\0', /* thousands_sep es_UY */ - "\x80\x80", /* grouping es_UY */ + '.', /* thousands_sep es_UY */ + "\x03\x03", /* grouping es_UY */ &global_errmsgs[es_ES] ); /***** LOCALE END es_UY *****/ @@ -2990,8 +2990,8 @@ MY_LOCALE my_locale_es_VE 10, 9, ',', /* decimal point es_VE */ - '\0', /* thousands_sep es_VE */ - "\x80\x80", /* grouping es_VE */ + '.', /* thousands_sep es_VE */ + "\x03\x03", /* grouping es_VE */ &global_errmsgs[es_ES] ); /***** LOCALE END es_VE *****/ -- cgit v1.2.1 From faaecc8fcfa922df3b9c33ec96f4998ffee4b0a6 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Fri, 21 Jan 2022 16:51:03 +0300 Subject: MDEV-27273 Confusing column count in IMPORT TABLESPACE error message It's misleading to compare and write to user number of columns and fields. Thus, it would be better to remove that check and let use see a subsequent error message about missing or mispaced column. row_import::match_schema(): remove misleading check --- mysql-test/suite/innodb/r/innodb-wl5522.result | 18 +++++++++++- mysql-test/suite/innodb/t/innodb-wl5522.test | 38 +++++++++++++++++++++++++ mysql-test/suite/innodb_zip/r/wl5522_zip.result | 2 +- storage/innobase/row/row0import.cc | 8 ------ 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-wl5522.result b/mysql-test/suite/innodb/r/innodb-wl5522.result index 27a93922fbf..3097a7660ef 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522.result @@ -331,7 +331,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Number of columns don't match, table has 6 columns but the tablespace meta-data file has 5 columns) +ERROR HY000: Schema mismatch (Column c3 not found in tablespace.) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -916,6 +916,22 @@ c1 c2 15 1 16 1 DROP TABLE t1; +CREATE TABLE t1 ( id INT NOT NULL, i1 INT, i2 INT, i3 INT, PRIMARY KEY (id)) engine=innodb; +CREATE TABLE t2 ( id INT NOT NULL, i1 INT, i2 INT, PRIMARY KEY (id)) engine=innodb; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLES t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Column DB_ROW_ID ordinal value mismatch, it's at 3 in the table and 4 in the tablespace meta-data file) +DROP TABLE t1, t2; +CREATE TABLE t1 ( id INT NOT NULL, i1 INT, i2 INT, PRIMARY KEY (id)) engine=innodb; +CREATE TABLE t2 ( id INT NOT NULL, i1 INT, i2 INT, i3 INT, PRIMARY KEY (id)) engine=innodb; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLES t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Column i3 not found in tablespace.) +DROP TABLE t1, t2; call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); diff --git a/mysql-test/suite/innodb/t/innodb-wl5522.test b/mysql-test/suite/innodb/t/innodb-wl5522.test index 906246ebf07..c503756e3ad 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522.test @@ -1057,6 +1057,44 @@ SELECT * FROM t1; DROP TABLE t1; + +CREATE TABLE t1 ( id INT NOT NULL, i1 INT, i2 INT, i3 INT, PRIMARY KEY (id)) engine=innodb; +CREATE TABLE t2 ( id INT NOT NULL, i1 INT, i2 INT, PRIMARY KEY (id)) engine=innodb; + +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLES t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t2 IMPORT TABLESPACE; + +DROP TABLE t1, t2; + + +CREATE TABLE t1 ( id INT NOT NULL, i1 INT, i2 INT, PRIMARY KEY (id)) engine=innodb; +--remove_file $MYSQLD_DATADIR/test/t2.ibd +CREATE TABLE t2 ( id INT NOT NULL, i1 INT, i2 INT, i3 INT, PRIMARY KEY (id)) engine=innodb; + +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLES t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t2 IMPORT TABLESPACE; + +--remove_file $MYSQLD_DATADIR/test/t2.ibd +--remove_file $MYSQLD_DATADIR/test/t2.cfg + + +DROP TABLE t1, t2; + + call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); diff --git a/mysql-test/suite/innodb_zip/r/wl5522_zip.result b/mysql-test/suite/innodb_zip/r/wl5522_zip.result index 40b357e1b7f..e85223574d7 100644 --- a/mysql-test/suite/innodb_zip/r/wl5522_zip.result +++ b/mysql-test/suite/innodb_zip/r/wl5522_zip.result @@ -317,7 +317,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Number of columns don't match, table has 6 columns but the tablespace meta-data file has 5 columns) +ERROR HY000: Schema mismatch (Column c3 not found in tablespace.) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index b7f73bc8e19..37a12b13bd1 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1320,14 +1320,6 @@ uncompressed: " .cfg file uses %s", m_table->flags, m_flags, msg); - return(DB_ERROR); - } else if (m_table->n_cols != m_n_cols) { - ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Number of columns don't match, table has %u " - "columns but the tablespace meta-data file has " - ULINTPF " columns", - m_table->n_cols, m_n_cols); - return(DB_ERROR); } else if (UT_LIST_GET_LEN(m_table->indexes) != m_n_indexes) { -- cgit v1.2.1 From f99d141cd26359acd188858a78f3fed607e7a90c Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Sat, 22 Jan 2022 12:46:06 +0700 Subject: MDEV-20516: Assertion `!lex->proc_list.first && !lex->result && !lex->param_list.elements' failed in mysql_create_view Execution of the CREATE VIEW statement sent via binary protocol where the flags of the COM_STMT_EXECUTE request a cursor to be opened before running the statement results in an assert failure. This assert fails since the data member thd->lex->result has not null value pointing to an instance of the class Select_materialize. The data member thd->lex->result is assigned a pointer to the class Select_materialize in the function mysql_open_cursor() that invoked in case the packet COM_STMT_EXECUTE requests a cursor to be opened. After thd->lex->result is assigned a pointer to an instance of the class Select_materialize the function mysql_create_view() is called (indirectly via the function mysql_execute_statement()) and the assert fails. The assert DBUG_ASSERT(!lex->proc_list.first && !lex->result && !lex->param_list.elements); was added by the commit 591c06d4b771124cc2cf453fbf51d5d99a4ad95e. Unfortunately , the condition !lex->result was specified incorrect. It was supposed that the thd->lex->result is set only by parser on handling the clauses SELECT ... INTO but indeed it is also set inside mysql_open_cursor() and that fact was missed by the assert's condition. So, the fix for this issue is to just remove the condition !lex->result from the failing assert. --- sql/sql_view.cc | 14 ++++++++++++-- tests/mysql_client_test.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 39744fe5704..e7286ae8e84 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -408,8 +408,18 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, bool res= FALSE; DBUG_ENTER("mysql_create_view"); - /* This is ensured in the parser. */ - DBUG_ASSERT(!lex->proc_list.first && !lex->result && + /* + This is ensured in the parser. + NOTE: Originally, the assert below contained the extra condition + && !lex->result + but in this form the assert is failed in case CREATE VIEW run under + cursor (the case when the byte 'flags' in the COM_STMT_EXECUTE packet has + the flag CURSOR_TYPE_READ_ONLY set). For the cursor use case + thd->lex->result is assigned a pointer to the class Select_materialize + inside the function mysql_open_cursor() just before handling of a statement + will be started and the function mysql_create_view() called. + */ + DBUG_ASSERT(!lex->proc_list.first && !lex->param_list.elements); /* diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 69e451c3019..db5c9a8688a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -20013,6 +20013,39 @@ static void test_mdev24827() myquery(rc); } +static void test_mdev_20516() +{ + MYSQL_STMT *stmt; + int rc; + unsigned long cursor= CURSOR_TYPE_READ_ONLY; + + myheader("test_mdev_20516"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1(a INT)"); + myquery(rc); + + const char* query= + "CREATE VIEW v1 AS SELECT * FROM t1"; + + stmt= mysql_stmt_init(mysql); + check_stmt(stmt); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); +} + #ifndef EMBEDDED_LIBRARY #define MDEV19838_MAX_PARAM_COUNT 32 #define MDEV19838_FIELDS_COUNT 17 @@ -20163,6 +20196,7 @@ static void test_mdev19838() #endif // EMBEDDED_LIBRARY static struct my_tests_st my_tests[]= { + { "test_mdev_20516", test_mdev_20516 }, { "test_mdev24827", test_mdev24827 }, { "test_mdev_26145", test_mdev_26145 }, { "disable_query_logs", disable_query_logs }, -- cgit v1.2.1 From 2b6f235ae0ee779c65b99326c33c1c780d24383d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 21 Jan 2022 13:02:08 +0200 Subject: MDEV-21308 : WSREP: binlog ... cache not empty warnings on server with WSREP disabled Remove output if wsrep is not enabled. --- sql/log.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index d94f87b90b5..e7a82b2f005 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1650,7 +1650,7 @@ static int binlog_close_connection(handlerton *hton, THD *thd) binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); #ifdef WITH_WSREP - if (cache_mngr && !cache_mngr->trx_cache.empty()) { + if (WSREP(thd) && cache_mngr && !cache_mngr->trx_cache.empty()) { IO_CACHE* cache= get_trans_log(thd); uchar *buf; size_t len=0; -- cgit v1.2.1 From 2c16fd9bafa1945463dadc9c7bc8f7d455791d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 22 Jan 2022 10:17:05 +0200 Subject: MDEV-24827, MDEV-20516 fixup: Use C90, plug memory leaks --- tests/mysql_client_test.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index db5c9a8688a..65eb502420d 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -1,5 +1,5 @@ /* Copyright (c) 2002, 2014, Oracle and/or its affiliates. - Copyright (c) 2008, 2020, MariaDB + Copyright (c) 2008, 2022, 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 @@ -20005,6 +20005,7 @@ static void test_mdev24827() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + mysql_stmt_close(stmt); rc= mysql_query(mysql, "DROP TABLE t1"); myquery(rc); @@ -20018,6 +20019,8 @@ static void test_mdev_20516() MYSQL_STMT *stmt; int rc; unsigned long cursor= CURSOR_TYPE_READ_ONLY; + const char* query= + "CREATE VIEW v1 AS SELECT * FROM t1"; myheader("test_mdev_20516"); @@ -20027,9 +20030,6 @@ static void test_mdev_20516() rc= mysql_query(mysql, "CREATE TABLE t1(a INT)"); myquery(rc); - const char* query= - "CREATE VIEW v1 AS SELECT * FROM t1"; - stmt= mysql_stmt_init(mysql); check_stmt(stmt); @@ -20041,6 +20041,7 @@ static void test_mdev_20516() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + mysql_stmt_close(stmt); rc= mysql_query(mysql, "DROP TABLE t1"); myquery(rc); -- cgit v1.2.1 From 8acc7fb39c711309c73bfd1816422a36437dfffe Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 9 Jan 2022 19:35:43 +0100 Subject: MDEV-24088 Assertion in InnoDB's FTS code may be triggered by a repeated words fed to simple_parser plugin increment `position` for every word, because the plugin doesn't (FTS API doesn't use positions that InnoDB FTS relies on) --- mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result | 1 + mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test | 2 ++ storage/innobase/fts/fts0fts.cc | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result b/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result index b7688e9ef0f..0b98a9c5a2d 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result @@ -161,6 +161,7 @@ id title body SELECT COUNT(*) FROM articles; COUNT(*) 5 +INSERT INTO articles (title, body) VALUES ('111', '1234 1234 1234'); DROP TABLE articles; # Test Part 5: Test Uninstall Plugin After Index is Built CREATE TABLE articles ( diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test b/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test index cd31500b23f..b22ac456668 100644 --- a/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test +++ b/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test @@ -158,6 +158,8 @@ SELECT * FROM articles WHERE SELECT * FROM articles WHERE MATCH(title, body) AGAINST('full text search'); SELECT COUNT(*) FROM articles; + +INSERT INTO articles (title, body) VALUES ('111', '1234 1234 1234'); DROP TABLE articles; -- echo # Test Part 5: Test Uninstall Plugin After Index is Built diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 37ab561c1ba..c005c3c52c0 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -4691,7 +4691,7 @@ fts_tokenize_add_word_for_parser( ut_ad(boolean_info->position >= 0); position = boolean_info->position + fts_param->add_pos; */ - position = fts_param->add_pos; + position = fts_param->add_pos++; fts_add_token(result_doc, str, position); -- cgit v1.2.1 From 50e66db018d0d0ee49fd2b7196f30ed4594dc2b3 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sat, 22 Jan 2022 06:59:40 +0400 Subject: MDEV-25917 create table like fails if source table is partitioned and engine is myisam or aria with data directory. Create table like removes data_file_path/index_file_path from the thd->work_partition_info. --- mysql-test/r/partition_symlink.result | 94 +++++++++++++++++++++++++++++++++++ mysql-test/t/partition_symlink.test | 55 ++++++++++++++++++++ sql/partition_element.h | 4 +- sql/partition_info.cc | 13 +++-- sql/partition_info.h | 2 +- sql/sql_table.cc | 11 +++- 6 files changed, 170 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/partition_symlink.result b/mysql-test/r/partition_symlink.result index 90048eb3438..b5a976e3a9e 100644 --- a/mysql-test/r/partition_symlink.result +++ b/mysql-test/r/partition_symlink.result @@ -177,3 +177,97 @@ partition by key (a) (partition p0, partition p1 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data'); Got one of the listed errors +# +# MDEV-25917 create table like fails if source table is partitioned and engine is myisam or aria with data directory. +# +CREATE TABLE t1 (a INT) +ENGINE = MyISAM +PARTITION BY LIST (a) +(PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/tmp', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/tmp', +PARTITION p2 VALUES IN (2)); +CREATE TABLE t2 LIKE t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + PARTITION BY LIST (`a`) +(PARTITION `p0` VALUES IN (0) DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/tmp' ENGINE = MyISAM, + PARTITION `p1` VALUES IN (1) DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/tmp' ENGINE = MyISAM, + PARTITION `p2` VALUES IN (2) ENGINE = MyISAM) +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + PARTITION BY LIST (`a`) +(PARTITION `p0` VALUES IN (0) ENGINE = MyISAM, + PARTITION `p1` VALUES IN (1) ENGINE = MyISAM, + PARTITION `p2` VALUES IN (2) ENGINE = MyISAM) +DROP TABLE t1, t2; +CREATE TABLE t1 ( +ID int(11) NOT NULL, +type int(11)) Engine=MyISAM +PARTITION BY RANGE(ID) +SUBPARTITION BY HASH(type) +( +PARTITION p01 VALUES LESS THAN(100) +(SUBPARTITION s11 +DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/tmp', +SUBPARTITION s12 +DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/tmp' + ), +PARTITION p11 VALUES LESS THAN(200) +(SUBPARTITION s21, SUBPARTITION s22), +PARTITION p21 VALUES LESS THAN MAXVALUE +(SUBPARTITION s31 +DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/tmp', +SUBPARTITION s32 +DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/tmp' + ) +); +CREATE TABLE t2 LIKE t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `ID` int(11) NOT NULL, + `type` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + PARTITION BY RANGE (`ID`) +SUBPARTITION BY HASH (`type`) +(PARTITION `p01` VALUES LESS THAN (100) + (SUBPARTITION `s11` DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/tmp' ENGINE = MyISAM, + SUBPARTITION `s12` DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/tmp' ENGINE = MyISAM), + PARTITION `p11` VALUES LESS THAN (200) + (SUBPARTITION `s21` ENGINE = MyISAM, + SUBPARTITION `s22` ENGINE = MyISAM), + PARTITION `p21` VALUES LESS THAN MAXVALUE + (SUBPARTITION `s31` DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/tmp' ENGINE = MyISAM, + SUBPARTITION `s32` DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/tmp' ENGINE = MyISAM)) +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `ID` int(11) NOT NULL, + `type` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + PARTITION BY RANGE (`ID`) +SUBPARTITION BY HASH (`type`) +(PARTITION `p01` VALUES LESS THAN (100) + (SUBPARTITION `s11` ENGINE = MyISAM, + SUBPARTITION `s12` ENGINE = MyISAM), + PARTITION `p11` VALUES LESS THAN (200) + (SUBPARTITION `s21` ENGINE = MyISAM, + SUBPARTITION `s22` ENGINE = MyISAM), + PARTITION `p21` VALUES LESS THAN MAXVALUE + (SUBPARTITION `s31` ENGINE = MyISAM, + SUBPARTITION `s32` ENGINE = MyISAM)) +DROP TABLE t1, t2; diff --git a/mysql-test/t/partition_symlink.test b/mysql-test/t/partition_symlink.test index 8f6e837299a..7e09c7d0642 100644 --- a/mysql-test/t/partition_symlink.test +++ b/mysql-test/t/partition_symlink.test @@ -220,3 +220,58 @@ ENGINE = MyISAM partition by key (a) (partition p0, partition p1 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data'); + +--echo # +--echo # MDEV-25917 create table like fails if source table is partitioned and engine is myisam or aria with data directory. +--echo # +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval CREATE TABLE t1 (a INT) +ENGINE = MyISAM +PARTITION BY LIST (a) +(PARTITION p0 VALUES IN (0) + DATA DIRECTORY '$MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/tmp', + PARTITION p1 VALUES IN (1) + DATA DIRECTORY '$MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/tmp', + PARTITION p2 VALUES IN (2)); + +CREATE TABLE t2 LIKE t1; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval CREATE TABLE t1 ( + ID int(11) NOT NULL, + type int(11)) Engine=MyISAM +PARTITION BY RANGE(ID) +SUBPARTITION BY HASH(type) +( + PARTITION p01 VALUES LESS THAN(100) + (SUBPARTITION s11 + DATA DIRECTORY '$MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/tmp', + SUBPARTITION s12 + DATA DIRECTORY '$MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/tmp' + ), + PARTITION p11 VALUES LESS THAN(200) + (SUBPARTITION s21, SUBPARTITION s22), + PARTITION p21 VALUES LESS THAN MAXVALUE + (SUBPARTITION s31 + DATA DIRECTORY '$MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/tmp', + SUBPARTITION s32 + DATA DIRECTORY '$MYSQLTEST_VARDIR/tmp' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/tmp' + ) +); + +CREATE TABLE t2 LIKE t1; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +DROP TABLE t1, t2; diff --git a/sql/partition_element.h b/sql/partition_element.h index 5241d00989f..81a14b4d75e 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -132,7 +132,9 @@ public: connect_string(null_lex_str), part_state(part_elem->part_state), nodegroup_id(part_elem->nodegroup_id), - has_null_value(FALSE) + has_null_value(FALSE), + signed_flag(part_elem->signed_flag), + max_value(part_elem->max_value) { } ~partition_element() {} diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 503b523a66c..c9156108e2e 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -35,7 +35,7 @@ #include "ha_partition.h" -partition_info *partition_info::get_clone(THD *thd) +partition_info *partition_info::get_clone(THD *thd, bool empty_data_and_index_file) { MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("partition_info::get_clone"); @@ -57,25 +57,28 @@ partition_info *partition_info::get_clone(THD *thd) { List_iterator subpart_it(part->subpartitions); partition_element *subpart; - partition_element *part_clone= new (mem_root) partition_element(); + partition_element *part_clone= new (mem_root) partition_element(*part); if (!part_clone) { mem_alloc_error(sizeof(partition_element)); DBUG_RETURN(NULL); } - *part_clone= *part; part_clone->subpartitions.empty(); while ((subpart= (subpart_it++))) { - partition_element *subpart_clone= new (mem_root) partition_element(); + partition_element *subpart_clone= new (mem_root) partition_element(*subpart); if (!subpart_clone) { mem_alloc_error(sizeof(partition_element)); DBUG_RETURN(NULL); } - *subpart_clone= *subpart; + if (empty_data_and_index_file) + subpart_clone->data_file_name= subpart_clone->index_file_name= NULL; part_clone->subpartitions.push_back(subpart_clone, mem_root); } + + if (empty_data_and_index_file) + part_clone->data_file_name= part_clone->index_file_name= NULL; clone->partitions.push_back(part_clone, mem_root); part_clone->list_val_list.empty(); List_iterator list_val_it(part->list_val_list); diff --git a/sql/partition_info.h b/sql/partition_info.h index d42ef380c8c..edd1e610df5 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -281,7 +281,7 @@ public: } ~partition_info() {} - partition_info *get_clone(THD *thd); + partition_info *get_clone(THD *thd, bool empty_data_and_index_file= FALSE); bool set_named_partition_bitmap(const char *part_name, uint length); bool set_partition_bitmaps(TABLE_LIST *table_list); /* Answers the question if subpartitioning is used for a certain table */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 33daa15b9b7..e1f752191ae 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5547,8 +5547,15 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, #ifdef WITH_PARTITION_STORAGE_ENGINE /* Partition info is not handled by mysql_prepare_alter_table() call. */ if (src_table->table->part_info) - thd->work_part_info= src_table->table->part_info->get_clone(thd); -#endif + { + /* + The CREATE TABLE LIKE should not inherit the DATA DIRECTORY + and INDEX DIRECTORY from the base table. + So that TRUE argument for the get_clone. + */ + thd->work_part_info= src_table->table->part_info->get_clone(thd, TRUE); + } +#endif /*WITH_PARTITION_STORAGE_ENGINE*/ /* Adjust description of source table before using it for creation of -- cgit v1.2.1 From 8b15d0d4e019e1c9e0cd88d4fb8efe3a8c6fcd72 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 24 Jan 2022 15:09:31 -0700 Subject: MDEV-16091: Seconds_Behind_Master spikes to millions of seconds This patch addresses two problems with rpl.rpl_seconds_behind_master_spike First, --sync_slave_with_master / select master_pos_wait seems to have a bug where it will hang after all master events have been executed. This patch removes the sync_slave_with_master command from the test, where it not required anyway as it is used to declare explicit cleanup Second, the test uses timestamps to ensure that the Seconds_Behind_Master value does not point to a time too far in the past. The checks of these timestamps were too strict, because they could be slightly inconsistent with the master and the SBM would be counted as invalid when it was actually correct. To fix this, a slight buffer was added to the check to ensure the value is valid but still does not point too far in the past Reviewed By: =========== Andrei Elkin --- mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result | 1 - mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test | 8 +++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result index d164ea5434f..be18f95c2c0 100644 --- a/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result +++ b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result @@ -36,6 +36,5 @@ SET DEBUG_SYNC='RESET'; connection master; DROP TABLE t1; connection slave; -connection slave; SET @@global.debug_dbug=$save_dbug; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test index 36ddbd0dc9f..029625a09ad 100644 --- a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test +++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test @@ -61,7 +61,11 @@ select count(*)=1 from t1; let $sbm= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1); --let $t_now= `SELECT UNIX_TIMESTAMP()` -if(`select $sbm > $t_now - $t_master_events_logged`) +# Ensure Seconds_Behind_Master does not point beyond when we have proven the +# events we have proven to have executed. The extra second is needed as a +# buffer because the recorded times are not exact with when the events were +# recorded on the master. +if(`select $sbm > $t_now - $t_master_events_logged + 1`) { die "A relay log event was incorrectly used to set Seconds_Behind_Master"; } @@ -77,8 +81,6 @@ SET DEBUG_SYNC='RESET'; # Cleanup --connection master DROP TABLE t1; ---save_master_pos ---sync_slave_with_master --connection slave SET @@global.debug_dbug=$save_dbug; -- cgit v1.2.1 From b9623383ccfb0b40f03390c3dbafcd6372a5ea59 Mon Sep 17 00:00:00 2001 From: Lena Startseva Date: Tue, 25 Jan 2022 17:31:59 +0700 Subject: MDEV-8652: Partitioned table creation problem when creating from procedure context twice in same session The problem was solved in in MDEV-7990, this commit contains only test --- mysql-test/r/partition_sp.result | 22 ++++++++++++++++++++++ mysql-test/t/partition_sp.test | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 mysql-test/r/partition_sp.result create mode 100644 mysql-test/t/partition_sp.test diff --git a/mysql-test/r/partition_sp.result b/mysql-test/r/partition_sp.result new file mode 100644 index 00000000000..585e2c7ab9d --- /dev/null +++ b/mysql-test/r/partition_sp.result @@ -0,0 +1,22 @@ +# +# MDEV-8652: Partitioned table creation problem when +# creating from procedure context twice in same session +# +CREATE PROCEDURE p1() +BEGIN +DROP TABLE IF EXISTS t1 ; +CREATE TABLE t1 ( +id INT PRIMARY KEY +) +PARTITION BY RANGE (id) ( +PARTITION P1 VALUES LESS THAN (2), +PARTITION P2 VALUES LESS THAN (3) +); +END | +call p1(); +call p1(); +drop procedure p1; +drop table t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/partition_sp.test b/mysql-test/t/partition_sp.test new file mode 100644 index 00000000000..1d3d1d707c7 --- /dev/null +++ b/mysql-test/t/partition_sp.test @@ -0,0 +1,35 @@ +--source include/have_partition.inc + +--echo # +--echo # MDEV-8652: Partitioned table creation problem when +--echo # creating from procedure context twice in same session +--echo # + + +DELIMITER |; + +CREATE PROCEDURE p1() +BEGIN + DROP TABLE IF EXISTS t1 ; + + CREATE TABLE t1 ( + id INT PRIMARY KEY + ) + PARTITION BY RANGE (id) ( + PARTITION P1 VALUES LESS THAN (2), + PARTITION P2 VALUES LESS THAN (3) + ); +END | + +DELIMITER ;| + +call p1(); +call p1(); + +drop procedure p1; +drop table t1; + +--echo # +--echo # End of 10.2 tests +--echo # + -- cgit v1.2.1 From 2925d0f2ee9847c1dcec9c3650ab2c71697a1f62 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 25 Jan 2022 10:34:13 +0100 Subject: MDEV-27612 Connect : check buffer sizes, fix string format errors --- storage/connect/bsonudf.cpp | 2 +- storage/connect/ha_connect.cc | 4 +- storage/connect/jsonudf.cpp | 2 +- storage/connect/myconn.cpp | 10 +- storage/connect/mysql-test/connect/r/misc.result | 54 +++++++++ storage/connect/mysql-test/connect/t/misc.test | 141 +++++++++++++++++++++++ storage/connect/plugutil.cpp | 6 + storage/connect/reldef.cpp | 7 +- storage/connect/tabbson.cpp | 2 +- storage/connect/tabext.cpp | 52 ++++++++- storage/connect/tabjson.cpp | 2 +- storage/connect/tabmysql.cpp | 5 + storage/connect/tabxml.cpp | 10 +- 13 files changed, 280 insertions(+), 17 deletions(-) create mode 100644 storage/connect/mysql-test/connect/r/misc.result create mode 100644 storage/connect/mysql-test/connect/t/misc.test diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index ed795edb363..7ae38bc65de 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -201,7 +201,7 @@ my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm) p[--n] = 0; } else if (!IsNum(p)) { // Wrong array specification - sprintf(g->Message, "Invalid array specification %s", p); + snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s", p); return true; } // endif p diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 5493f3b6730..ac3769c399e 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -5707,10 +5707,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (ttp == TAB_UNDEF && !topt->http) { topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; ttp= GetTypeID(topt->type); - sprintf(g->Message, "No table_type. Was set to %s", topt->type); + snprintf(g->Message, sizeof(g->Message), "No table_type. Was set to %s", topt->type); push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message); } else if (ttp == TAB_NIY) { - sprintf(g->Message, "Unsupported table type %s", topt->type); + snprintf(g->Message, sizeof(g->Message), "Unsupported table type %s", topt->type); rc= HA_ERR_INTERNAL_ERROR; goto err; #if defined(REST_SUPPORT) diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 82492cab6ef..363a853cfa7 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -123,7 +123,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) p[--n] = 0; } else if (!IsNum(p)) { // Wrong array specification - sprintf(g->Message, "Invalid array specification %s", p); + snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s", p); return true; } // endif p diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 945c4e698be..438f0ff2b9a 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -399,15 +399,19 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db, int w; MYSQLC myc; PQRYRES qrp = NULL; + const char *p; if (!port) port = mysqld_port; if (!strnicmp(srcdef, "select ", 7) || strstr(srcdef, "%s")) { - query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 10); + query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 10); - if (strstr(srcdef, "%s")) - sprintf(query, srcdef, "1=1"); // dummy where clause + if ((p= strstr(srcdef, "%s"))) + { + /* Replace %s with 1=1 */ + sprintf(query, "%.*s1=1%s", (int) (p - srcdef), srcdef, p + 2); // dummy where clause + } else strcpy(query, srcdef); diff --git a/storage/connect/mysql-test/connect/r/misc.result b/storage/connect/mysql-test/connect/r/misc.result new file mode 100644 index 00000000000..6b6372f6e41 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/misc.result @@ -0,0 +1,54 @@ +execute immediate concat('create table t engine=CONNECT table_type=JSON',REPEAT('1',5000), +' FILE_NAME=''users.json'' HTTP=''http://localhost:4142'' URI=''/users'''); +ERROR HY000: Unsupported table type JSON1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 +execute immediate concat('create table t engine=CONNECT table_type=OEM module=''libname'' +Option_list=''Myopt=foo'' subtype=''MYTYPE',REPEAT('1', 10000), ''''); +ERROR HY000: Subtype string too long +execute immediate concat('create table t engine=CONNECT table_type=DBF file_name=''', +REPLACE(@@secure_file_priv,'\\','/'),'cust.dbf', REPEAT('1', 10000), ''''); +ERROR HY000: Cannot open +create table t engine=connect table_type=mysql +CONNECTION='mysql://root@localhost:MASTER_MYPORT/test/foobar' + SRCDEF='SELECT 1,''%n'' FROM DUAL WHERE %s'; +select *from t; +ERROR HY000: Got error 174 'MakeSQL: Wrong place holders specification' from CONNECT +drop table t; +create table t engine=connect table_type=mysql +CONNECTION='mysql://root@localhost:MASTER_MYPORT/test/foobar' + SRCDEF='SELECT 1,%n FROM DUAL WHERE %s'; +ERROR HY000: (1064) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '%n FROM DUAL WHERE 1=1 LIMIT 0' at line 1 [SELECT 1,%n FROM DUAL WHERE 1=1 LIMIT 0] +create table t engine=connect table_type=mysql +CONNECTION='mysql://root@localhost:MASTER_MYPORT/test/foobar' + SRCDEF='SELECT 1 FROM DUAL WHERE %s'; +select *from t; +1 +1 +drop table t; +create table beers ( +`Name` char(16) xpath='brandName', +`Origin` char(16) xpath='origin', +`Description` char(32) xpath='details') +engine=CONNECT table_type=XML file_name='MYSQLTEST_VARDIR/tmp/beer.xml' +tabname='table' option_list='rownode=tr,colnode=td%n'; +select * from beers; +Name Origin Description +NULL NULL NULL +NULL NULL NULL +drop table beers; +create table beers ( +`Name` char(16) xpath='brandName', +`Origin` char(16) xpath='origin', +`Description` char(32) xpath='details') +engine=CONNECT table_type=XML file_name='MYSQLTEST_VARDIR/tmp/beer.xml' +tabname='table' option_list='rownode=tr,colnode=td'; +insert into beers values('11','22','33'); +drop table beers; +execute immediate CONCAT('create table jsampall +(Author char(128) jpath=''$.AUTHOR["', REPEAT('a',10000),'"]'') +engine=CONNECT table_type=JSON +file_name=''',REPLACE(@@secure_file_priv,'\\','/'),'tmp/test.json'''); +select author from jsampall; +author +Jean-Christophe Bernadacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +William J. Pardi +drop table jsampall; diff --git a/storage/connect/mysql-test/connect/t/misc.test b/storage/connect/mysql-test/connect/t/misc.test new file mode 100644 index 00000000000..4dc8dded651 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/misc.test @@ -0,0 +1,141 @@ + +# Overlong table type +--error ER_UNKNOWN_ERROR +execute immediate concat('create table t engine=CONNECT table_type=JSON',REPEAT('1',5000), +' FILE_NAME=''users.json'' HTTP=''http://localhost:4142'' URI=''/users'''); + +# Overlong subtype +--error ER_UNKNOWN_ERROR +execute immediate concat('create table t engine=CONNECT table_type=OEM module=''libname'' +Option_list=''Myopt=foo'' subtype=''MYTYPE',REPEAT('1', 10000), ''''); + + +# Overlong filename +--error ER_UNKNOWN_ERROR +execute immediate concat('create table t engine=CONNECT table_type=DBF file_name=''', + REPLACE(@@secure_file_priv,'\\','/'),'cust.dbf', REPEAT('1', 10000), ''''); + + +# Format string in SRCDEF +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval create table t engine=connect table_type=mysql + CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/foobar' + SRCDEF='SELECT 1,''%n'' FROM DUAL WHERE %s'; +--error ER_GET_ERRMSG +select *from t; +drop table t; + +--replace_result $MASTER_MYPORT MASTER_MYPORT +--error ER_UNKNOWN_ERROR +eval create table t engine=connect table_type=mysql + CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/foobar' + SRCDEF='SELECT 1,%n FROM DUAL WHERE %s'; + +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval create table t engine=connect table_type=mysql + CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/foobar' + SRCDEF='SELECT 1 FROM DUAL WHERE %s'; +select *from t; +drop table t; + +write_file $MYSQLTEST_VARDIR/tmp/beer.xml; + + + + + + + + + + + + + + +
NameOriginDescription
HuntsmanBath, UK
Wonderful hop, light alcohol
TuborgDanmark
In small bottles
+
+EOF + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +# Format string in colnode +eval create table beers ( +`Name` char(16) xpath='brandName', +`Origin` char(16) xpath='origin', +`Description` char(32) xpath='details') +engine=CONNECT table_type=XML file_name='$MYSQLTEST_VARDIR/tmp/beer.xml' +tabname='table' option_list='rownode=tr,colnode=td%n'; +select * from beers; +drop table beers; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval create table beers ( +`Name` char(16) xpath='brandName', +`Origin` char(16) xpath='origin', +`Description` char(32) xpath='details') +engine=CONNECT table_type=XML file_name='$MYSQLTEST_VARDIR/tmp/beer.xml' +tabname='table' option_list='rownode=tr,colnode=td'; +insert into beers values('11','22','33'); +drop table beers; + +remove_file $MYSQLTEST_VARDIR/tmp/beer.xml; + +write_file $MYSQLTEST_VARDIR/tmp/test.json; +[ + { + "ISBN": "9782212090819", + "LANG": "fr", + "SUBJECT": "applications", + "AUTHOR": [ + { + "FIRSTNAME": "Jean-Christophe", + "LASTNAME": "Bernadac" + }, + { + "FIRSTNAME": "François", + "LASTNAME": "Knab" + } + ], + "TITLE": "Construire une application XML", + "PUBLISHER": { + "NAME": "Eyrolles", + "PLACE": "Paris" + }, + "DATEPUB": 1999 + }, + { + "ISBN": "9782840825685", + "LANG": "fr", + "SUBJECT": "applications", + "AUTHOR": [ + { + "FIRSTNAME": "William J.", + "LASTNAME": "Pardi" + } + ], + "TITLE": "XML en Action", + "TRANSLATED": { + "PREFIX": "adapté de l'anglais par", + "TRANSLATOR": { + "FIRSTNAME": "James", + "LASTNAME": "Guerin" + } + }, + "PUBLISHER": { + "NAME": "Microsoft Press", + "PLACE": "Paris" + }, + "DATEPUB": 1999 + } +] +EOF + +execute immediate CONCAT('create table jsampall +(Author char(128) jpath=''$.AUTHOR["', REPEAT('a',10000),'"]'') +engine=CONNECT table_type=JSON +file_name=''',REPLACE(@@secure_file_priv,'\\','/'),'tmp/test.json'''); + +select author from jsampall; +drop table jsampall; +remove_file $MYSQLTEST_VARDIR/tmp/test.json; + diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp index 4aecbadfc6a..db62ad5bb2c 100644 --- a/storage/connect/plugutil.cpp +++ b/storage/connect/plugutil.cpp @@ -259,6 +259,12 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) if (trace(2)) htrc("prefix=%s fn=%s path=%s\n", prefix, FileName, defpath); + if (strlen(FileName) >= _MAX_PATH) + { + *pBuff= 0; /* Hope this is treated as error of some kind*/ + return FileName; + } + if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) { strcpy(pBuff, FileName); // Remote file return pBuff; diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index d7715a2ea9f..8be3a013e8c 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -93,7 +93,12 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) if (check_valid_path(module, strlen(module))) { strcpy(g->Message, "Module cannot contain a path"); return NULL; - } else + } + else if (strlen(subtype)+1+3 >= sizeof(getname)) { + strcpy(g->Message, "Subtype string too long"); + return NULL; + } + else PlugSetPath(soname, module, GetPluginDir()); // The exported name is always in uppercase diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index 8569e39f678..59d2b7ed1b0 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -1788,7 +1788,7 @@ bool BSONCOL::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm) p[--n] = 0; } else if (!IsNum(p)) { // Wrong array specification - sprintf(g->Message, "Invalid array specification %s for %s", p, Name); + snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s for %s", p, Name); return true; } // endif p diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index 9e8154cd233..1e0f6254f87 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -286,6 +286,37 @@ int TDBEXT::Decode(PCSZ txt, char *buf, size_t n) return 0; } // end of Decode +/* + Count number of %s placeholders in string. + Returns -1 if other sprintf placeholders are found, .g %d +*/ +static int count_placeholders(const char *fmt) +{ + int cnt= 0; + for (const char *p=fmt; *p; p++) + { + if (*p == '%') + { + switch (p[1]) + { + case 's': + /* %s found */ + cnt++; + p++; + break; + case '%': + /* masking char for % found */ + p++; + break; + default: + /* some other placeholder found */ + return -1; + } + } + } + return cnt; +} + /***********************************************************************/ /* MakeSrcdef: make the SQL statement from SRDEF option. */ /***********************************************************************/ @@ -310,16 +341,29 @@ bool TDBEXT::MakeSrcdef(PGLOBAL g) ? To_CondFil->Having : PlugDup(g, "1=1"); } // endif ph - if (!stricmp(ph, "W")) { + int n_placeholders = count_placeholders(Srcdef); + if (n_placeholders < 0) + { + strcpy(g->Message, "MakeSQL: Wrong place holders specification"); + return true; + } + + if (!stricmp(ph, "W") && n_placeholders <= 1) { Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1)); Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1)); - } else if (!stricmp(ph, "WH")) { + } + else if (!stricmp(ph, "WH") && n_placeholders <= 2) + { Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2)); Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1, fil2)); - } else if (!stricmp(ph, "H")) { + } + else if (!stricmp(ph, "H") && n_placeholders <= 1) + { Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil2)); Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2)); - } else if (!stricmp(ph, "HW")) { + } + else if (!stricmp(ph, "HW") && n_placeholders <= 2) + { Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2)); Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2, fil1)); } else { diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 7eff0a68c4b..8cd452ee570 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1384,7 +1384,7 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) p[--n] = 0; } else if (!IsNum(p)) { // Wrong array specification - sprintf(g->Message, "Invalid array specification %s for %s", p, Name); + snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s for %s", p, Name); return true; } // endif p diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index f8f995f211e..a701db1e8e9 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -904,6 +904,11 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) /*********************************************************************/ if (Mode == MODE_READ || Mode == MODE_READX) { MakeSelect(g, Mode == MODE_READX); + if (Mode == MODE_READ && !Query) + { + Myc.Close(); + return true; + } m_Rc = (Mode == MODE_READ) ? Myc.ExecSQL(g, Query->GetStr()) : RC_OK; diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index cb428f5a94c..7357d2373c8 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -1511,9 +1511,13 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode) if (!mode) // Take care of an eventual extra column node a la html if (Tdbp->Colname) { - sprintf(pbuf, Tdbp->Colname, Rank + ((Tdbp->Usedom) ? 0 : 1)); - strcat(pbuf, "/"); - } // endif Colname + char *p = strstr(Tdbp->Colname, "%d"); + if (p) + snprintf(pbuf, len + 3, "%.*s%d%s/", (int) (p - Tdbp->Colname), Tdbp->Colname, + Rank + (Tdbp->Usedom ? 0 : 1), p + 2); + else + snprintf(pbuf, len + 3, "%s/", Tdbp->Colname); + } // endif Colname if (Xname) { if (Type == 2) { -- cgit v1.2.1 From 7db489fc7dea2b4c236807035e57f169074c6682 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 25 Jan 2022 09:14:43 +0100 Subject: new CC --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index dde7deee51f..f6c3d9fd2af 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit dde7deee51fb4bab475a3e78b66d5ef0872a8d98 +Subproject commit f6c3d9fd2af5d17db64cc996574aa312efd70fcf -- cgit v1.2.1 From 2cbf92522b51390819ab5013ac9195382bd5d409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 26 Jan 2022 12:19:48 +0200 Subject: Cleanup: Remove an unused parameter of fts_add_doc_by_id() --- storage/innobase/fts/fts0fts.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index c005c3c52c0..3cb15d64e91 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2021, Oracle and/or its affiliates. -Copyright (c) 2016, 2021, MariaDB Corporation. +Copyright (c) 2016, 2022, 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 @@ -230,9 +230,7 @@ ulint fts_add_doc_by_id( /*==============*/ fts_trx_table_t*ftt, /*!< in: FTS trx table */ - doc_id_t doc_id, /*!< in: doc id */ - ib_vector_t* fts_indexes MY_ATTRIBUTE((unused))); - /*!< in: affected fts indexes */ + doc_id_t doc_id); /*!< in: doc id */ /******************************************************************//** Update the last document id. This function could create a new transaction to update the last document id. @@ -2860,7 +2858,7 @@ fts_add( ut_a(row->state == FTS_INSERT || row->state == FTS_MODIFY); - fts_add_doc_by_id(ftt, doc_id, row->fts_indexes); + fts_add_doc_by_id(ftt, doc_id); mutex_enter(&table->fts->cache->deleted_lock); ++table->fts->cache->added; @@ -3434,9 +3432,7 @@ ulint fts_add_doc_by_id( /*==============*/ fts_trx_table_t*ftt, /*!< in: FTS trx table */ - doc_id_t doc_id, /*!< in: doc id */ - ib_vector_t* fts_indexes MY_ATTRIBUTE((unused))) - /*!< in: affected fts indexes */ + doc_id_t doc_id) /*!< in: doc id */ { mtr_t mtr; mem_heap_t* heap; -- cgit v1.2.1 From 2e81eab29fed25655c57235c307c64383056bbe9 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 25 Jan 2022 13:59:41 +1100 Subject: MDEV-27607: mysql_install_db to install mysql_upgrade_info For compatibility this is under an extra option --upgrade-info The goal here is to install a data directory with the required info to let mysql_upgrade know that an upgrade isn't required. --- debian/mariadb-server-10.2.postinst | 2 +- man/mysql_install_db.1 | 15 +++++++++++++++ scripts/mysql_install_db.sh | 7 +++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/debian/mariadb-server-10.2.postinst b/debian/mariadb-server-10.2.postinst index 14b2053b3a0..3fe5a04fbc3 100644 --- a/debian/mariadb-server-10.2.postinst +++ b/debian/mariadb-server-10.2.postinst @@ -144,7 +144,7 @@ EOF # Debian: beware of the bashisms... # Debian: can safely run on upgrades with existing databases set +e - bash /usr/bin/mysql_install_db --rpm --cross-bootstrap --user=mysql --disable-log-bin 2>&1 | $ERR_LOGGER + bash /usr/bin/mysql_install_db --rpm --cross-bootstrap --user=mysql --disable-log-bin --upgrade-info 2>&1 | $ERR_LOGGER set -e ## On every reconfiguration the maintenance user is recreated. diff --git a/man/mysql_install_db.1 b/man/mysql_install_db.1 index 3406c9605b7..229a6f8df99 100644 --- a/man/mysql_install_db.1 +++ b/man/mysql_install_db.1 @@ -276,6 +276,21 @@ This must be given as the first argument\&. .sp -1 .IP \(bu 2.3 .\} +.\" mysql_install_db: upgrade-info option +.\" upgrade-info option: mysql_install_db +\fB\-\-upgrade\-info\fR +.sp +This places a mysql_upgrade_info file containing the server version in the data directory\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} .\" mysql_install_db: rpm option .\" rpm option: mysql_install_db \fB\-\-rpm\fR diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 6a415f4fa11..fdd3a42d77f 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -41,6 +41,7 @@ create database if not exists test; use mysql;" auth_root_authentication_method=normal auth_root_socket_user='root' +upgrade_info=0 dirname0=`dirname $0 2>/dev/null` dirname0=`dirname $dirname0 2>/dev/null` @@ -97,6 +98,7 @@ Usage: $0 [OPTIONS] user. You must be root to use this option. By default mysqld runs using your current login name and files and directories that it creates will be owned by you. + --upgrade-info Store mysql_upgrade_info in the installed data directory. All other options are passed to the mysqld program @@ -152,6 +154,7 @@ parse_arguments() --skip-name-resolve) ip_only=1 ;; --verbose) verbose=1 ; silent_startup="" ;; --rpm) in_rpm=1 ;; + --upgrade-info) upgrade_info=1 ;; --help) usage ;; --no-defaults|--defaults-file=*|--defaults-extra-file=*) defaults="$arg" ;; @@ -509,6 +512,10 @@ SET @auth_root_socket='$auth_root_socket_user';" ;; esac if { echo "$install_params"; cat "$create_system_tables" "$create_system_tables2" "$fill_system_tables" "$fill_help_tables" "$maria_add_gis_sp"; } | eval "$filter_cmd_line" | mysqld_install_cmd_line > /dev/null then + if test "$upgrade_info" -eq 1 + then + printf "@VERSION@-MariaDB" > "$ldata/mysql_upgrade_info" + fi s_echo "OK" else echo -- cgit v1.2.1 From 68b3fa8865aad65eaaac84cb1f48426aa05a1deb Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 16 Dec 2021 20:11:48 +1100 Subject: MDEV-27289: mtr test for WITH_SERVER_EMBEDDED=ON reenable mtr is checking the wrong path for the embedded executable on out of tree builds. The is_embedded.inc tests are also checking the version rather than the MTR MYSQL_EMBEDDED environment variable. As a result, a few tests are out of date in the result recordings. --- mysql-test/include/is_embedded.inc | 2 +- mysql-test/include/not_windows_embedded.inc | 4 +- mysql-test/mysql-test-run.pl | 2 +- mysql-test/r/events_embedded.result | 2 +- .../suite/funcs_1/r/is_columns_is_embedded.result | 948 ++++++++++----------- .../sys_vars/r/sysvars_server_embedded,32bit.rdiff | 298 ++++--- .../sys_vars/r/sysvars_server_embedded.result | 646 +++++++++++++- mysql-test/t/events_embedded.test | 2 +- 8 files changed, 1288 insertions(+), 616 deletions(-) diff --git a/mysql-test/include/is_embedded.inc b/mysql-test/include/is_embedded.inc index b20f21953f0..ee2fefa51da 100644 --- a/mysql-test/include/is_embedded.inc +++ b/mysql-test/include/is_embedded.inc @@ -1,4 +1,4 @@ -if (`SELECT VERSION() NOT LIKE '%embedded%'`) +if(!$MYSQL_EMBEDDED) { --skip Test requires: embedded server } diff --git a/mysql-test/include/not_windows_embedded.inc b/mysql-test/include/not_windows_embedded.inc index 46f5e0ccfce..50ff0f80c7d 100644 --- a/mysql-test/include/not_windows_embedded.inc +++ b/mysql-test/include/not_windows_embedded.inc @@ -1,10 +1,8 @@ let $is_win = `select convert(@@version_compile_os using latin1) IN ("Win32","Win64","Windows")`; -let $is_embedded = `select version() like '%embedded%'`; #echo is_win: $is_win; -#echo is_embedded: $is_embedded; if ($is_win) { - if ($is_embedded) + if(!$MYSQL_EMBEDDED) { skip Not supported with embedded on windows; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 4e00a76422b..aa6a02a4541 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1968,7 +1968,7 @@ sub executable_setup () { $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); $exe_mysql_plugin= mtr_exe_exists("$path_client_bindir/mysql_plugin"); - $exe_mysql_embedded= mtr_exe_maybe_exists("$basedir/libmysqld/examples/mysql_embedded"); + $exe_mysql_embedded= mtr_exe_maybe_exists("$bindir/libmysqld/examples/mysql_embedded"); # Look for mysqltest executable if ( $opt_embedded_server ) diff --git a/mysql-test/r/events_embedded.result b/mysql-test/r/events_embedded.result index 1a02188f2df..5dc48402a88 100644 --- a/mysql-test/r/events_embedded.result +++ b/mysql-test/r/events_embedded.result @@ -1,2 +1,2 @@ set global event_scheduler=ON; -ERROR HY000: Unknown system variable 'event_scheduler' +set global event_scheduler=ORIGINAL; diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result index 9116830e88c..3282d30669e 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result @@ -3,480 +3,480 @@ WHERE table_schema = 'information_schema' AND table_name <> 'profiling' AND table_name not like 'innodb_%' ORDER BY table_schema, table_name, column_name; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE DATETIME_PRECISION CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT IS_GENERATED GENERATION_EXPRESSION -def information_schema ALL_PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema APPLICABLE_ROLES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL -def information_schema APPLICABLE_ROLES IS_DEFAULT 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema APPLICABLE_ROLES IS_GRANTABLE 3 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema APPLICABLE_ROLES ROLE_NAME 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL -def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema CHARACTER_SETS DESCRIPTION 3 '' NO varchar 60 180 NULL NULL NULL utf8 utf8_general_ci varchar(60) NEVER NULL -def information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) NEVER NULL -def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 5 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema CHECK_CONSTRAINTS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL -def information_schema CLIENT_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS CLIENT 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS CONNECTED_TIME 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL -def information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS 2 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema CLIENT_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema CLIENT_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema COLLATIONS CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema COLLATIONS COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(11) NEVER NULL -def information_schema COLLATIONS IS_COMPILED 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema COLLATIONS IS_DEFAULT 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema COLLATIONS SORTLEN 6 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) NEVER NULL -def information_schema COLLATION_CHARACTER_SET_APPLICABILITY CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema COLUMNS CHARACTER_MAXIMUM_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema COLUMNS CHARACTER_OCTET_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema COLUMNS CHARACTER_SET_NAME 14 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema COLUMNS COLLATION_NAME 15 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema COLUMNS COLUMN_COMMENT 20 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) NEVER NULL -def information_schema COLUMNS COLUMN_DEFAULT 6 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema COLUMNS COLUMN_KEY 17 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema COLUMNS COLUMN_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema COLUMNS COLUMN_TYPE 16 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema COLUMNS DATA_TYPE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema COLUMNS DATETIME_PRECISION 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema COLUMNS EXTRA 18 '' NO varchar 30 90 NULL NULL NULL utf8 utf8_general_ci varchar(30) NEVER NULL -def information_schema COLUMNS GENERATION_EXPRESSION 22 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema COLUMNS IS_GENERATED 21 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) NEVER NULL -def information_schema COLUMNS IS_NULLABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema COLUMNS NUMERIC_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema COLUMNS NUMERIC_SCALE 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema COLUMNS ORDINAL_POSITION 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema COLUMNS PRIVILEGES 19 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema COLUMNS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema COLUMNS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema COLUMNS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema COLUMN_PRIVILEGES COLUMN_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema COLUMN_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL -def information_schema COLUMN_PRIVILEGES IS_GRANTABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema COLUMN_PRIVILEGES PRIVILEGE_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema COLUMN_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema COLUMN_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema COLUMN_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ENABLED_ROLES ROLE_NAME 1 NULL YES varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL -def information_schema ENGINES COMMENT 3 '' NO varchar 160 480 NULL NULL NULL utf8 utf8_general_ci varchar(160) NEVER NULL -def information_schema ENGINES ENGINE 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ENGINES SAVEPOINTS 6 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema ENGINES SUPPORT 2 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL -def information_schema ENGINES TRANSACTIONS 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema ENGINES XA 5 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema EVENTS CHARACTER_SET_CLIENT 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema EVENTS COLLATION_CONNECTION 23 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema EVENTS CREATED 17 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema EVENTS DATABASE_COLLATION 24 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema EVENTS DEFINER 4 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL -def information_schema EVENTS ENDS 14 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema EVENTS EVENT_BODY 6 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL -def information_schema EVENTS EVENT_CATALOG 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema EVENTS EVENT_COMMENT 20 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema EVENTS EVENT_DEFINITION 7 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema EVENTS EVENT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema EVENTS EVENT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema EVENTS EVENT_TYPE 8 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL -def information_schema EVENTS EXECUTE_AT 9 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema EVENTS INTERVAL_FIELD 11 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) NEVER NULL -def information_schema EVENTS INTERVAL_VALUE 10 NULL YES varchar 256 768 NULL NULL NULL utf8 utf8_general_ci varchar(256) NEVER NULL -def information_schema EVENTS LAST_ALTERED 18 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema EVENTS LAST_EXECUTED 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema EVENTS ON_COMPLETION 16 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL -def information_schema EVENTS ORIGINATOR 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) NEVER NULL -def information_schema EVENTS SQL_MODE 12 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) NEVER NULL -def information_schema EVENTS STARTS 13 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema EVENTS STATUS 15 '' NO varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) NEVER NULL -def information_schema EVENTS TIME_ZONE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES AUTOEXTEND_SIZE 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES AVG_ROW_LENGTH 28 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES CHECKSUM 36 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES CHECK_TIME 35 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema FILES CREATE_TIME 33 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema FILES CREATION_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema FILES DATA_FREE 32 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES DATA_LENGTH 29 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES DELETED_ROWS 12 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES ENGINE 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES EXTENT_SIZE 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES EXTRA 38 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_general_ci varchar(255) NEVER NULL -def information_schema FILES FILE_ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES FILE_NAME 2 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema FILES FILE_TYPE 3 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema FILES FREE_EXTENTS 14 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES FULLTEXT_KEYS 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES INDEX_LENGTH 31 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES INITIAL_SIZE 17 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES LAST_ACCESS_TIME 22 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema FILES LAST_UPDATE_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema FILES LOGFILE_GROUP_NAME 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES LOGFILE_GROUP_NUMBER 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES MAXIMUM_SIZE 18 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES MAX_DATA_LENGTH 30 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES RECOVER_TIME 23 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES ROW_FORMAT 26 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL -def information_schema FILES STATUS 37 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema FILES TABLESPACE_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES TABLE_CATALOG 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES TABLE_NAME 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES TABLE_ROWS 27 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema FILES TABLE_SCHEMA 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema FILES TOTAL_EXTENTS 15 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES TRANSACTION_COUNTER 24 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES UPDATE_COUNT 13 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema FILES UPDATE_TIME 34 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema FILES VERSION 25 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema GEOMETRY_COLUMNS COORD_DIMENSION 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL -def information_schema GEOMETRY_COLUMNS F_GEOMETRY_COLUMN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GEOMETRY_COLUMNS F_TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema GEOMETRY_COLUMNS F_TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GEOMETRY_COLUMNS F_TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GEOMETRY_COLUMNS GEOMETRY_TYPE 10 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) NEVER NULL -def information_schema GEOMETRY_COLUMNS G_GEOMETRY_COLUMN 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GEOMETRY_COLUMNS G_TABLE_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema GEOMETRY_COLUMNS G_TABLE_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GEOMETRY_COLUMNS G_TABLE_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GEOMETRY_COLUMNS MAX_PPR 12 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL -def information_schema GEOMETRY_COLUMNS SRID 13 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) NEVER NULL -def information_schema GEOMETRY_COLUMNS STORAGE_TYPE 9 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL -def information_schema GLOBAL_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema INDEX_STATISTICS INDEX_NAME 3 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL -def information_schema INDEX_STATISTICS ROWS_READ 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema INDEX_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL -def information_schema INDEX_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL -def information_schema KEYWORDS WORD 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES KEY_CACHE_NAME 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL -def information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES SEGMENTS 2 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned NEVER NULL -def information_schema KEY_CACHES SEGMENT_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned NEVER NULL -def information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_COLUMN_USAGE ORDINAL_POSITION 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) NEVER NULL -def information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(10) NEVER NULL -def information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARAMETERS COLLATION_NAME 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARAMETERS DATA_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARAMETERS DATETIME_PRECISION 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARAMETERS DTD_IDENTIFIER 15 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema PARAMETERS NUMERIC_PRECISION 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema PARAMETERS NUMERIC_SCALE 11 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema PARAMETERS ORDINAL_POSITION 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema PARAMETERS PARAMETER_MODE 5 NULL YES varchar 5 15 NULL NULL NULL utf8 utf8_general_ci varchar(5) NEVER NULL -def information_schema PARAMETERS PARAMETER_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARAMETERS ROUTINE_TYPE 16 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL -def information_schema PARAMETERS SPECIFIC_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema PARAMETERS SPECIFIC_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARAMETERS SPECIFIC_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARTITIONS AVG_ROW_LENGTH 14 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS CHECKSUM 22 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS CHECK_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema PARTITIONS CREATE_TIME 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema PARTITIONS DATA_FREE 18 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS DATA_LENGTH 15 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS INDEX_LENGTH 17 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS MAX_DATA_LENGTH 16 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS NODEGROUP 24 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL -def information_schema PARTITIONS PARTITION_COMMENT 23 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema PARTITIONS PARTITION_DESCRIPTION 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema PARTITIONS PARTITION_EXPRESSION 10 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema PARTITIONS PARTITION_METHOD 8 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) NEVER NULL -def information_schema PARTITIONS PARTITION_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARTITIONS PARTITION_ORDINAL_POSITION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS SUBPARTITION_EXPRESSION 11 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema PARTITIONS SUBPARTITION_METHOD 9 NULL YES varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL -def information_schema PARTITIONS SUBPARTITION_NAME 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARTITIONS SUBPARTITION_ORDINAL_POSITION 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS TABLESPACE_NAME 25 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARTITIONS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema PARTITIONS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARTITIONS TABLE_ROWS 13 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema PARTITIONS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PARTITIONS UPDATE_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL -def information_schema PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL -def information_schema PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL -def information_schema PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL -def information_schema PROCESSLIST COMMAND 5 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL -def information_schema PROCESSLIST DB 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PROCESSLIST EXAMINED_ROWS 14 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) NEVER NULL -def information_schema PROCESSLIST HOST 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PROCESSLIST ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema PROCESSLIST INFO 8 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema PROCESSLIST INFO_BINARY 16 NULL YES blob 65535 65535 NULL NULL NULL NULL NULL blob NEVER NULL -def information_schema PROCESSLIST MAX_STAGE 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL -def information_schema PROCESSLIST MEMORY_USED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(7) NEVER NULL -def information_schema PROCESSLIST PROGRESS 12 0.000 NO decimal NULL NULL 7 3 NULL NULL NULL decimal(7,3) NEVER NULL -def information_schema PROCESSLIST QUERY_ID 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema PROCESSLIST STAGE 10 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL -def information_schema PROCESSLIST STATE 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema PROCESSLIST TID 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema PROCESSLIST TIME 6 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) NEVER NULL -def information_schema PROCESSLIST TIME_MS 9 0.000 NO decimal NULL NULL 22 3 NULL NULL NULL decimal(22,3) NEVER NULL -def information_schema PROCESSLIST USER 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UPDATE_RULE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES CHARACTER_MAXIMUM_LENGTH 7 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema ROUTINES CHARACTER_OCTET_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema ROUTINES CHARACTER_SET_CLIENT 29 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema ROUTINES CHARACTER_SET_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES COLLATION_CONNECTION 30 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema ROUTINES COLLATION_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES CREATED 24 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema ROUTINES DATABASE_COLLATION 31 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema ROUTINES DATA_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES DATETIME_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema ROUTINES DEFINER 28 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL -def information_schema ROUTINES DTD_IDENTIFIER 14 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema ROUTINES EXTERNAL_LANGUAGE 18 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES EXTERNAL_NAME 17 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES IS_DETERMINISTIC 20 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema ROUTINES LAST_ALTERED 25 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema ROUTINES NUMERIC_PRECISION 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema ROUTINES NUMERIC_SCALE 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL -def information_schema ROUTINES PARAMETER_STYLE 19 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL -def information_schema ROUTINES ROUTINE_BODY 15 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL -def information_schema ROUTINES ROUTINE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema ROUTINES ROUTINE_COMMENT 27 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema ROUTINES ROUTINE_DEFINITION 16 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema ROUTINES ROUTINE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES ROUTINE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES ROUTINE_TYPE 5 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL -def information_schema ROUTINES SECURITY_TYPE 23 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) NEVER NULL -def information_schema ROUTINES SPECIFIC_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES SQL_DATA_ACCESS 21 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema ROUTINES SQL_MODE 26 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) NEVER NULL -def information_schema ROUTINES SQL_PATH 22 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SCHEMATA CATALOG_NAME 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema SCHEMATA DEFAULT_CHARACTER_SET_NAME 3 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema SCHEMATA DEFAULT_COLLATION_NAME 4 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema SCHEMATA SCHEMA_NAME 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SCHEMATA SQL_PATH 5 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema SCHEMA_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL -def information_schema SCHEMA_PRIVILEGES IS_GRANTABLE 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SESSION_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SESSION_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema SESSION_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema SPATIAL_REF_SYS AUTH_NAME 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema SPATIAL_REF_SYS AUTH_SRID 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(5) NEVER NULL -def information_schema SPATIAL_REF_SYS SRID 1 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) NEVER NULL -def information_schema SPATIAL_REF_SYS SRTEXT 4 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema SQL_FUNCTIONS FUNCTION 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema STATISTICS CARDINALITY 10 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema STATISTICS COLLATION 9 NULL YES varchar 1 3 NULL NULL NULL utf8 utf8_general_ci varchar(1) NEVER NULL -def information_schema STATISTICS COLUMN_NAME 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema STATISTICS COMMENT 15 NULL YES varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL -def information_schema STATISTICS INDEX_COMMENT 16 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) NEVER NULL -def information_schema STATISTICS INDEX_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema STATISTICS INDEX_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema STATISTICS INDEX_TYPE 14 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL -def information_schema STATISTICS NON_UNIQUE 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(1) NEVER NULL -def information_schema STATISTICS NULLABLE 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema STATISTICS PACKED 12 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL -def information_schema STATISTICS SEQ_IN_INDEX 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(2) NEVER NULL -def information_schema STATISTICS SUB_PART 11 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(3) NEVER NULL -def information_schema STATISTICS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema STATISTICS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema STATISTICS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SYSTEM_VARIABLES COMMAND_LINE_ARGUMENT 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SYSTEM_VARIABLES DEFAULT_VALUE 5 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema SYSTEM_VARIABLES ENUM_VALUE_LIST 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema SYSTEM_VARIABLES GLOBAL_VALUE 3 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema SYSTEM_VARIABLES GLOBAL_VALUE_ORIGIN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SYSTEM_VARIABLES NUMERIC_BLOCK_SIZE 11 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) NEVER NULL -def information_schema SYSTEM_VARIABLES NUMERIC_MAX_VALUE 10 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) NEVER NULL -def information_schema SYSTEM_VARIABLES NUMERIC_MIN_VALUE 9 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) NEVER NULL -def information_schema SYSTEM_VARIABLES READ_ONLY 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema SYSTEM_VARIABLES SESSION_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_COMMENT 8 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_SCOPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLES AUTO_INCREMENT 14 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES AVG_ROW_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES CHECKSUM 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES CHECK_TIME 17 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema TABLES CREATE_TIME 15 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema TABLES DATA_FREE 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES DATA_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES ENGINE 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLES INDEX_LENGTH 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES MAX_DATA_LENGTH 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES ROW_FORMAT 7 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL -def information_schema TABLES TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema TABLES TABLE_COLLATION 18 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema TABLES TABLE_COMMENT 21 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema TABLES TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLES TABLE_ROWS 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLES TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLES TABLE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLES UPDATE_TIME 16 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL -def information_schema TABLES VERSION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLESPACES AUTOEXTEND_SIZE 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLESPACES ENGINE 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLESPACES EXTENT_SIZE 5 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLESPACES LOGFILE_GROUP_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLESPACES MAXIMUM_SIZE 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLESPACES NODEGROUP_ID 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema TABLESPACES TABLESPACE_COMMENT 9 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL -def information_schema TABLESPACES TABLESPACE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLESPACES TABLESPACE_TYPE 3 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_CONSTRAINTS TABLE_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_CONSTRAINTS TABLE_SCHEMA 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL -def information_schema TABLE_PRIVILEGES IS_GRANTABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema TABLE_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TABLE_STATISTICS ROWS_CHANGED 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES 5 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema TABLE_STATISTICS ROWS_READ 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema TABLE_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL -def information_schema TABLE_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL -def information_schema TRIGGERS ACTION_CONDITION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema TRIGGERS ACTION_ORDER 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL -def information_schema TRIGGERS ACTION_ORIENTATION 11 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_NEW_ROW 16 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_NEW_TABLE 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_OLD_ROW 15 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_OLD_TABLE 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TRIGGERS ACTION_STATEMENT 10 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL -def information_schema TRIGGERS ACTION_TIMING 12 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) NEVER NULL -def information_schema TRIGGERS CHARACTER_SET_CLIENT 20 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema TRIGGERS COLLATION_CONNECTION 21 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema TRIGGERS CREATED 17 NULL YES datetime NULL NULL NULL NULL 2 NULL NULL datetime(2) NEVER NULL -def information_schema TRIGGERS DATABASE_COLLATION 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema TRIGGERS DEFINER 19 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL -def information_schema TRIGGERS EVENT_MANIPULATION 4 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) NEVER NULL -def information_schema TRIGGERS EVENT_OBJECT_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema TRIGGERS EVENT_OBJECT_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TRIGGERS EVENT_OBJECT_TABLE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TRIGGERS SQL_MODE 18 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) NEVER NULL -def information_schema TRIGGERS TRIGGER_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema TRIGGERS TRIGGER_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema TRIGGERS TRIGGER_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema USER_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL -def information_schema USER_PRIVILEGES IS_GRANTABLE 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema USER_PRIVILEGES PRIVILEGE_TYPE 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema USER_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema USER_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL -def information_schema USER_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL -def information_schema USER_STATISTICS CONNECTED_TIME 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL -def information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL -def information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS TOTAL_CONNECTIONS 2 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL -def information_schema USER_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL -def information_schema USER_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL -def information_schema USER_STATISTICS USER 1 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL -def information_schema VIEWS ALGORITHM 11 '' NO varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL -def information_schema VIEWS CHARACTER_SET_CLIENT 9 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema VIEWS CHECK_OPTION 5 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL -def information_schema VIEWS COLLATION_CONNECTION 10 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL -def information_schema VIEWS DEFINER 7 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL -def information_schema VIEWS IS_UPDATABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL -def information_schema VIEWS SECURITY_TYPE 8 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) NEVER NULL -def information_schema VIEWS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL -def information_schema VIEWS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema VIEWS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema VIEWS VIEW_DEFINITION 4 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema ALL_PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema APPLICABLE_ROLES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL +def information_schema APPLICABLE_ROLES IS_DEFAULT 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema APPLICABLE_ROLES IS_GRANTABLE 3 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema APPLICABLE_ROLES ROLE_NAME 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL +def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema CHARACTER_SETS DESCRIPTION 3 '' NO varchar 60 180 NULL NULL NULL utf8 utf8_general_ci varchar(60) select NEVER NULL +def information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) select NEVER NULL +def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 5 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema CHECK_CONSTRAINTS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL +def information_schema CLIENT_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS CLIENT 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS CONNECTED_TIME 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL +def information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS 2 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema CLIENT_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema CLIENT_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema COLLATIONS CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema COLLATIONS COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(11) select NEVER NULL +def information_schema COLLATIONS IS_COMPILED 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema COLLATIONS IS_DEFAULT 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema COLLATIONS SORTLEN 6 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) select NEVER NULL +def information_schema COLLATION_CHARACTER_SET_APPLICABILITY CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema COLUMNS CHARACTER_MAXIMUM_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema COLUMNS CHARACTER_OCTET_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema COLUMNS CHARACTER_SET_NAME 14 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema COLUMNS COLLATION_NAME 15 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema COLUMNS COLUMN_COMMENT 20 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select NEVER NULL +def information_schema COLUMNS COLUMN_DEFAULT 6 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema COLUMNS COLUMN_KEY 17 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema COLUMNS COLUMN_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema COLUMNS COLUMN_TYPE 16 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema COLUMNS DATA_TYPE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema COLUMNS DATETIME_PRECISION 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema COLUMNS EXTRA 18 '' NO varchar 30 90 NULL NULL NULL utf8 utf8_general_ci varchar(30) select NEVER NULL +def information_schema COLUMNS GENERATION_EXPRESSION 22 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema COLUMNS IS_GENERATED 21 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) select NEVER NULL +def information_schema COLUMNS IS_NULLABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema COLUMNS NUMERIC_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema COLUMNS NUMERIC_SCALE 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema COLUMNS ORDINAL_POSITION 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema COLUMNS PRIVILEGES 19 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema COLUMNS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema COLUMNS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema COLUMNS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema COLUMN_PRIVILEGES COLUMN_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema COLUMN_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL +def information_schema COLUMN_PRIVILEGES IS_GRANTABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema COLUMN_PRIVILEGES PRIVILEGE_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema COLUMN_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema COLUMN_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema COLUMN_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ENABLED_ROLES ROLE_NAME 1 NULL YES varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL +def information_schema ENGINES COMMENT 3 '' NO varchar 160 480 NULL NULL NULL utf8 utf8_general_ci varchar(160) select NEVER NULL +def information_schema ENGINES ENGINE 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ENGINES SAVEPOINTS 6 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema ENGINES SUPPORT 2 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL +def information_schema ENGINES TRANSACTIONS 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema ENGINES XA 5 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema EVENTS CHARACTER_SET_CLIENT 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema EVENTS COLLATION_CONNECTION 23 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema EVENTS CREATED 17 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema EVENTS DATABASE_COLLATION 24 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema EVENTS DEFINER 4 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL +def information_schema EVENTS ENDS 14 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema EVENTS EVENT_BODY 6 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL +def information_schema EVENTS EVENT_CATALOG 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema EVENTS EVENT_COMMENT 20 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema EVENTS EVENT_DEFINITION 7 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema EVENTS EVENT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema EVENTS EVENT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema EVENTS EVENT_TYPE 8 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL +def information_schema EVENTS EXECUTE_AT 9 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema EVENTS INTERVAL_FIELD 11 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) select NEVER NULL +def information_schema EVENTS INTERVAL_VALUE 10 NULL YES varchar 256 768 NULL NULL NULL utf8 utf8_general_ci varchar(256) select NEVER NULL +def information_schema EVENTS LAST_ALTERED 18 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema EVENTS LAST_EXECUTED 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema EVENTS ON_COMPLETION 16 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL +def information_schema EVENTS ORIGINATOR 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) select NEVER NULL +def information_schema EVENTS SQL_MODE 12 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) select NEVER NULL +def information_schema EVENTS STARTS 13 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema EVENTS STATUS 15 '' NO varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) select NEVER NULL +def information_schema EVENTS TIME_ZONE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES AUTOEXTEND_SIZE 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES AVG_ROW_LENGTH 28 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES CHECKSUM 36 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES CHECK_TIME 35 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema FILES CREATE_TIME 33 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema FILES CREATION_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema FILES DATA_FREE 32 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES DATA_LENGTH 29 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES DELETED_ROWS 12 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES ENGINE 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES EXTENT_SIZE 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES EXTRA 38 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_general_ci varchar(255) select NEVER NULL +def information_schema FILES FILE_ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES FILE_NAME 2 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema FILES FILE_TYPE 3 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema FILES FREE_EXTENTS 14 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES FULLTEXT_KEYS 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES INDEX_LENGTH 31 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES INITIAL_SIZE 17 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES LAST_ACCESS_TIME 22 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema FILES LAST_UPDATE_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema FILES LOGFILE_GROUP_NAME 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES LOGFILE_GROUP_NUMBER 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES MAXIMUM_SIZE 18 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES MAX_DATA_LENGTH 30 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES RECOVER_TIME 23 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES ROW_FORMAT 26 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL +def information_schema FILES STATUS 37 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema FILES TABLESPACE_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES TABLE_CATALOG 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES TABLE_NAME 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES TABLE_ROWS 27 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema FILES TABLE_SCHEMA 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema FILES TOTAL_EXTENTS 15 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES TRANSACTION_COUNTER 24 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES UPDATE_COUNT 13 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema FILES UPDATE_TIME 34 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema FILES VERSION 25 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema GEOMETRY_COLUMNS COORD_DIMENSION 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL +def information_schema GEOMETRY_COLUMNS F_GEOMETRY_COLUMN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GEOMETRY_COLUMNS F_TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema GEOMETRY_COLUMNS F_TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GEOMETRY_COLUMNS F_TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GEOMETRY_COLUMNS GEOMETRY_TYPE 10 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) select NEVER NULL +def information_schema GEOMETRY_COLUMNS G_GEOMETRY_COLUMN 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GEOMETRY_COLUMNS G_TABLE_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema GEOMETRY_COLUMNS G_TABLE_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GEOMETRY_COLUMNS G_TABLE_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GEOMETRY_COLUMNS MAX_PPR 12 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL +def information_schema GEOMETRY_COLUMNS SRID 13 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) select NEVER NULL +def information_schema GEOMETRY_COLUMNS STORAGE_TYPE 9 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL +def information_schema GLOBAL_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema INDEX_STATISTICS INDEX_NAME 3 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL +def information_schema INDEX_STATISTICS ROWS_READ 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema INDEX_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL +def information_schema INDEX_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL +def information_schema KEYWORDS WORD 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES KEY_CACHE_NAME 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL +def information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES SEGMENTS 2 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned select NEVER NULL +def information_schema KEY_CACHES SEGMENT_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned select NEVER NULL +def information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_COLUMN_USAGE ORDINAL_POSITION 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) select NEVER NULL +def information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(10) select NEVER NULL +def information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARAMETERS COLLATION_NAME 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARAMETERS DATA_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARAMETERS DATETIME_PRECISION 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARAMETERS DTD_IDENTIFIER 15 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema PARAMETERS NUMERIC_PRECISION 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema PARAMETERS NUMERIC_SCALE 11 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema PARAMETERS ORDINAL_POSITION 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema PARAMETERS PARAMETER_MODE 5 NULL YES varchar 5 15 NULL NULL NULL utf8 utf8_general_ci varchar(5) select NEVER NULL +def information_schema PARAMETERS PARAMETER_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARAMETERS ROUTINE_TYPE 16 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL +def information_schema PARAMETERS SPECIFIC_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema PARAMETERS SPECIFIC_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARAMETERS SPECIFIC_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARTITIONS AVG_ROW_LENGTH 14 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS CHECKSUM 22 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS CHECK_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema PARTITIONS CREATE_TIME 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema PARTITIONS DATA_FREE 18 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS DATA_LENGTH 15 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS INDEX_LENGTH 17 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS MAX_DATA_LENGTH 16 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS NODEGROUP 24 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL +def information_schema PARTITIONS PARTITION_COMMENT 23 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema PARTITIONS PARTITION_DESCRIPTION 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema PARTITIONS PARTITION_EXPRESSION 10 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema PARTITIONS PARTITION_METHOD 8 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) select NEVER NULL +def information_schema PARTITIONS PARTITION_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARTITIONS PARTITION_ORDINAL_POSITION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS SUBPARTITION_EXPRESSION 11 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema PARTITIONS SUBPARTITION_METHOD 9 NULL YES varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL +def information_schema PARTITIONS SUBPARTITION_NAME 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARTITIONS SUBPARTITION_ORDINAL_POSITION 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS TABLESPACE_NAME 25 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARTITIONS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema PARTITIONS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARTITIONS TABLE_ROWS 13 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema PARTITIONS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PARTITIONS UPDATE_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL +def information_schema PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL +def information_schema PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL +def information_schema PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL +def information_schema PROCESSLIST COMMAND 5 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL +def information_schema PROCESSLIST DB 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PROCESSLIST EXAMINED_ROWS 14 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) select NEVER NULL +def information_schema PROCESSLIST HOST 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PROCESSLIST ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema PROCESSLIST INFO 8 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema PROCESSLIST INFO_BINARY 16 NULL YES blob 65535 65535 NULL NULL NULL NULL NULL blob select NEVER NULL +def information_schema PROCESSLIST MAX_STAGE 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL +def information_schema PROCESSLIST MEMORY_USED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(7) select NEVER NULL +def information_schema PROCESSLIST PROGRESS 12 0.000 NO decimal NULL NULL 7 3 NULL NULL NULL decimal(7,3) select NEVER NULL +def information_schema PROCESSLIST QUERY_ID 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema PROCESSLIST STAGE 10 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL +def information_schema PROCESSLIST STATE 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema PROCESSLIST TID 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema PROCESSLIST TIME 6 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) select NEVER NULL +def information_schema PROCESSLIST TIME_MS 9 0.000 NO decimal NULL NULL 22 3 NULL NULL NULL decimal(22,3) select NEVER NULL +def information_schema PROCESSLIST USER 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UPDATE_RULE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES CHARACTER_MAXIMUM_LENGTH 7 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema ROUTINES CHARACTER_OCTET_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema ROUTINES CHARACTER_SET_CLIENT 29 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema ROUTINES CHARACTER_SET_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES COLLATION_CONNECTION 30 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema ROUTINES COLLATION_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES CREATED 24 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema ROUTINES DATABASE_COLLATION 31 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema ROUTINES DATA_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES DATETIME_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema ROUTINES DEFINER 28 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL +def information_schema ROUTINES DTD_IDENTIFIER 14 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema ROUTINES EXTERNAL_LANGUAGE 18 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES EXTERNAL_NAME 17 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES IS_DETERMINISTIC 20 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema ROUTINES LAST_ALTERED 25 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema ROUTINES NUMERIC_PRECISION 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema ROUTINES NUMERIC_SCALE 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL +def information_schema ROUTINES PARAMETER_STYLE 19 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL +def information_schema ROUTINES ROUTINE_BODY 15 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL +def information_schema ROUTINES ROUTINE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema ROUTINES ROUTINE_COMMENT 27 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema ROUTINES ROUTINE_DEFINITION 16 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema ROUTINES ROUTINE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES ROUTINE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES ROUTINE_TYPE 5 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL +def information_schema ROUTINES SECURITY_TYPE 23 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) select NEVER NULL +def information_schema ROUTINES SPECIFIC_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES SQL_DATA_ACCESS 21 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema ROUTINES SQL_MODE 26 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) select NEVER NULL +def information_schema ROUTINES SQL_PATH 22 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SCHEMATA CATALOG_NAME 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema SCHEMATA DEFAULT_CHARACTER_SET_NAME 3 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema SCHEMATA DEFAULT_COLLATION_NAME 4 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema SCHEMATA SCHEMA_NAME 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SCHEMATA SQL_PATH 5 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema SCHEMA_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL +def information_schema SCHEMA_PRIVILEGES IS_GRANTABLE 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SESSION_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SESSION_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SESSION_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SPATIAL_REF_SYS AUTH_NAME 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema SPATIAL_REF_SYS AUTH_SRID 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(5) select NEVER NULL +def information_schema SPATIAL_REF_SYS SRID 1 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) select NEVER NULL +def information_schema SPATIAL_REF_SYS SRTEXT 4 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SQL_FUNCTIONS FUNCTION 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema STATISTICS CARDINALITY 10 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema STATISTICS COLLATION 9 NULL YES varchar 1 3 NULL NULL NULL utf8 utf8_general_ci varchar(1) select NEVER NULL +def information_schema STATISTICS COLUMN_NAME 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema STATISTICS COMMENT 15 NULL YES varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL +def information_schema STATISTICS INDEX_COMMENT 16 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select NEVER NULL +def information_schema STATISTICS INDEX_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema STATISTICS INDEX_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema STATISTICS INDEX_TYPE 14 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL +def information_schema STATISTICS NON_UNIQUE 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(1) select NEVER NULL +def information_schema STATISTICS NULLABLE 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema STATISTICS PACKED 12 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL +def information_schema STATISTICS SEQ_IN_INDEX 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(2) select NEVER NULL +def information_schema STATISTICS SUB_PART 11 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(3) select NEVER NULL +def information_schema STATISTICS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema STATISTICS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema STATISTICS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SYSTEM_VARIABLES COMMAND_LINE_ARGUMENT 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SYSTEM_VARIABLES DEFAULT_VALUE 5 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SYSTEM_VARIABLES ENUM_VALUE_LIST 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema SYSTEM_VARIABLES GLOBAL_VALUE 3 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SYSTEM_VARIABLES GLOBAL_VALUE_ORIGIN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SYSTEM_VARIABLES NUMERIC_BLOCK_SIZE 11 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) select NEVER NULL +def information_schema SYSTEM_VARIABLES NUMERIC_MAX_VALUE 10 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) select NEVER NULL +def information_schema SYSTEM_VARIABLES NUMERIC_MIN_VALUE 9 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) select NEVER NULL +def information_schema SYSTEM_VARIABLES READ_ONLY 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema SYSTEM_VARIABLES SESSION_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_COMMENT 8 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_SCOPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLES AUTO_INCREMENT 14 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES AVG_ROW_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES CHECKSUM 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES CHECK_TIME 17 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema TABLES CREATE_TIME 15 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema TABLES DATA_FREE 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES DATA_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES ENGINE 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLES INDEX_LENGTH 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES MAX_DATA_LENGTH 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES ROW_FORMAT 7 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL +def information_schema TABLES TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema TABLES TABLE_COLLATION 18 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema TABLES TABLE_COMMENT 21 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema TABLES TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLES TABLE_ROWS 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLES TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLES TABLE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLES UPDATE_TIME 16 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL +def information_schema TABLES VERSION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLESPACES AUTOEXTEND_SIZE 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLESPACES ENGINE 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLESPACES EXTENT_SIZE 5 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLESPACES LOGFILE_GROUP_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLESPACES MAXIMUM_SIZE 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLESPACES NODEGROUP_ID 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema TABLESPACES TABLESPACE_COMMENT 9 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema TABLESPACES TABLESPACE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLESPACES TABLESPACE_TYPE 3 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_CONSTRAINTS TABLE_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_CONSTRAINTS TABLE_SCHEMA 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL +def information_schema TABLE_PRIVILEGES IS_GRANTABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema TABLE_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TABLE_STATISTICS ROWS_CHANGED 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES 5 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema TABLE_STATISTICS ROWS_READ 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema TABLE_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL +def information_schema TABLE_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL +def information_schema TRIGGERS ACTION_CONDITION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema TRIGGERS ACTION_ORDER 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL +def information_schema TRIGGERS ACTION_ORIENTATION 11 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_NEW_ROW 16 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_NEW_TABLE 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_OLD_ROW 15 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_OLD_TABLE 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TRIGGERS ACTION_STATEMENT 10 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema TRIGGERS ACTION_TIMING 12 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) select NEVER NULL +def information_schema TRIGGERS CHARACTER_SET_CLIENT 20 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema TRIGGERS COLLATION_CONNECTION 21 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema TRIGGERS CREATED 17 NULL YES datetime NULL NULL NULL NULL 2 NULL NULL datetime(2) select NEVER NULL +def information_schema TRIGGERS DATABASE_COLLATION 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema TRIGGERS DEFINER 19 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL +def information_schema TRIGGERS EVENT_MANIPULATION 4 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) select NEVER NULL +def information_schema TRIGGERS EVENT_OBJECT_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema TRIGGERS EVENT_OBJECT_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TRIGGERS EVENT_OBJECT_TABLE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TRIGGERS SQL_MODE 18 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) select NEVER NULL +def information_schema TRIGGERS TRIGGER_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema TRIGGERS TRIGGER_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema TRIGGERS TRIGGER_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema USER_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL +def information_schema USER_PRIVILEGES IS_GRANTABLE 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema USER_PRIVILEGES PRIVILEGE_TYPE 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema USER_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema USER_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL +def information_schema USER_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select NEVER NULL +def information_schema USER_STATISTICS CONNECTED_TIME 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select NEVER NULL +def information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL +def information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS TOTAL_CONNECTIONS 2 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select NEVER NULL +def information_schema USER_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL +def information_schema USER_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL +def information_schema USER_STATISTICS USER 1 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL +def information_schema VIEWS ALGORITHM 11 '' NO varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL +def information_schema VIEWS CHARACTER_SET_CLIENT 9 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema VIEWS CHECK_OPTION 5 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL +def information_schema VIEWS COLLATION_CONNECTION 10 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL +def information_schema VIEWS DEFINER 7 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL +def information_schema VIEWS IS_UPDATABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL +def information_schema VIEWS SECURITY_TYPE 8 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) select NEVER NULL +def information_schema VIEWS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema VIEWS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema VIEWS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema VIEWS VIEW_DEFINITION 4 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL ########################################################################## # Show the quotient of CHARACTER_OCTET_LENGTH and CHARACTER_MAXIMUM_LENGTH ########################################################################## diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index df7edb3d8b3..01c3ea5cd75 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1,5 +1,5 @@ ---- sysvars_server_embedded.result 2019-09-01 15:14:00.790739643 +0300 -+++ sysvars_server_embedded,32bit.reject 2019-09-01 19:15:06.044626854 +0300 +--- sysvars_server_embedded.result ++++ sysvars_server_embedded,32bit.reject @@ -14,7 +14,7 @@ order by variable_name; VARIABLE_NAME ARIA_BLOCK_SIZE @@ -227,7 +227,7 @@ VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -664,7 +664,7 @@ +@@ -674,7 +674,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DEFAULT_WEEK_FORMAT VARIABLE_SCOPE SESSION @@ -236,7 +236,7 @@ VARIABLE_COMMENT The default week format used by WEEK() functions NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 7 -@@ -674,7 +674,7 @@ +@@ -684,7 +684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_LIMIT VARIABLE_SCOPE GLOBAL @@ -245,7 +245,7 @@ VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -684,7 +684,7 @@ +@@ -694,7 +694,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -254,7 +254,7 @@ VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -694,7 +694,7 @@ +@@ -704,7 +704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_QUEUE_SIZE VARIABLE_SCOPE GLOBAL @@ -263,7 +263,7 @@ VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -714,7 +714,7 @@ +@@ -724,7 +724,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME DIV_PRECISION_INCREMENT VARIABLE_SCOPE SESSION @@ -272,7 +272,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -794,7 +794,7 @@ +@@ -814,7 +814,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME EXPIRE_LOGS_DAYS VARIABLE_SCOPE GLOBAL @@ -281,7 +281,7 @@ VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 99 -@@ -824,7 +824,7 @@ +@@ -844,7 +844,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME EXTRA_MAX_CONNECTIONS VARIABLE_SCOPE GLOBAL @@ -290,7 +290,7 @@ VARIABLE_COMMENT The number of connections on extra-port NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -854,7 +854,7 @@ +@@ -874,7 +874,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME FLUSH_TIME VARIABLE_SCOPE GLOBAL @@ -299,7 +299,7 @@ VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -884,7 +884,7 @@ +@@ -904,7 +904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MAX_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -308,7 +308,7 @@ VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -894,7 +894,7 @@ +@@ -914,7 +914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MIN_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -317,7 +317,7 @@ VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 84 -@@ -904,7 +904,7 @@ +@@ -924,7 +924,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_QUERY_EXPANSION_LIMIT VARIABLE_SCOPE GLOBAL @@ -326,16 +326,7 @@ VARIABLE_COMMENT Number of best matches to use for query expansion NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -947,7 +947,7 @@ - VARIABLE_TYPE BIGINT UNSIGNED - VARIABLE_COMMENT The maximum length of the result of function GROUP_CONCAT() - NUMERIC_MIN_VALUE 4 --NUMERIC_MAX_VALUE 18446744073709551615 -+NUMERIC_MAX_VALUE 4294967295 - NUMERIC_BLOCK_SIZE 1 - ENUM_VALUE_LIST NULL - READ_ONLY NO -@@ -1074,7 +1074,7 @@ +@@ -1154,7 +1154,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HISTOGRAM_SIZE VARIABLE_SCOPE SESSION @@ -344,7 +335,7 @@ VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1104,7 +1104,7 @@ +@@ -1184,7 +1184,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HOST_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -353,7 +344,7 @@ VARIABLE_COMMENT How many host names should be cached to avoid resolving. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65536 -@@ -1184,7 +1184,7 @@ +@@ -1264,7 +1264,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME INTERACTIVE_TIMEOUT VARIABLE_SCOPE SESSION @@ -362,7 +353,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1207,7 +1207,7 @@ +@@ -1287,7 +1287,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer that is used for joins NUMERIC_MIN_VALUE 128 @@ -371,7 +362,7 @@ NUMERIC_BLOCK_SIZE 128 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1224,7 +1224,7 @@ +@@ -1304,7 +1304,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME JOIN_CACHE_LEVEL VARIABLE_SCOPE SESSION @@ -380,7 +371,7 @@ VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8 -@@ -1247,7 +1247,7 @@ +@@ -1327,7 +1327,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford NUMERIC_MIN_VALUE 0 @@ -389,7 +380,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1404,7 +1404,7 @@ +@@ -1494,7 +1494,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOCK_WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -398,7 +389,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1504,7 +1504,7 @@ +@@ -1624,7 +1624,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_RATE_LIMIT VARIABLE_SCOPE SESSION @@ -407,7 +398,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1534,7 +1534,7 @@ +@@ -1654,7 +1654,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION @@ -416,7 +407,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1584,7 +1584,7 @@ +@@ -1714,7 +1714,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION @@ -425,7 +416,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1597,14 +1597,14 @@ +@@ -1727,14 +1727,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the transactional cache NUMERIC_MIN_VALUE 4096 @@ -442,7 +433,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -1617,14 +1617,14 @@ +@@ -1747,14 +1747,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the statement cache NUMERIC_MIN_VALUE 4096 @@ -459,7 +450,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -1634,7 +1634,7 @@ +@@ -1764,7 +1764,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_CONNECT_ERRORS VARIABLE_SCOPE GLOBAL @@ -468,7 +459,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1644,7 +1644,7 @@ +@@ -1774,7 +1774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_DELAYED_THREADS VARIABLE_SCOPE SESSION @@ -477,7 +468,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1664,7 +1664,7 @@ +@@ -1794,7 +1794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_ERROR_COUNT VARIABLE_SCOPE SESSION @@ -486,7 +477,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -1677,14 +1677,14 @@ +@@ -1807,14 +1807,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -503,7 +494,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1704,7 +1704,7 @@ +@@ -1834,7 +1834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LENGTH_FOR_SORT_DATA VARIABLE_SCOPE SESSION @@ -512,7 +503,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -1714,7 +1714,7 @@ +@@ -1844,7 +1844,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LONG_DATA_SIZE VARIABLE_SCOPE GLOBAL @@ -521,7 +512,7 @@ VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -1734,7 +1734,7 @@ +@@ -1864,7 +1864,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_RECURSIVE_ITERATIONS VARIABLE_SCOPE SESSION @@ -530,8 +521,8 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1744,7 +1744,7 @@ - COMMAND_LINE_ARGUMENT OPTIONAL +@@ -1884,7 +1884,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SEEKS_FOR_KEY VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED @@ -539,16 +530,16 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1764,7 +1764,7 @@ +@@ -1904,7 +1904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) - NUMERIC_MIN_VALUE 4 + NUMERIC_MIN_VALUE 64 NUMERIC_MAX_VALUE 8388608 -@@ -1774,7 +1774,7 @@ +@@ -1914,7 +1914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SP_RECURSION_DEPTH VARIABLE_SCOPE SESSION @@ -557,7 +548,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1794,7 +1794,7 @@ +@@ -1934,7 +1934,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_TMP_TABLES VARIABLE_SCOPE SESSION @@ -566,7 +557,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1814,7 +1814,7 @@ +@@ -1954,7 +1954,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_WRITE_LOCK_COUNT VARIABLE_SCOPE GLOBAL @@ -575,7 +566,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1824,7 +1824,7 @@ +@@ -1964,7 +1964,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -584,7 +575,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -1834,7 +1834,7 @@ +@@ -1974,7 +1974,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_HASH_INSTANCES VARIABLE_SCOPE GLOBAL @@ -593,7 +584,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -1844,7 +1844,7 @@ +@@ -1984,7 +1984,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -602,7 +593,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1854,7 +1854,7 @@ +@@ -1994,7 +1994,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MRR_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -611,7 +602,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -1864,17 +1864,17 @@ +@@ -2004,17 +2004,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MULTI_RANGE_COUNT VARIABLE_SCOPE SESSION @@ -632,7 +623,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -1884,7 +1884,7 @@ +@@ -2024,7 +2024,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_DATA_POINTER_SIZE VARIABLE_SCOPE GLOBAL @@ -641,7 +632,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -1907,7 +1907,7 @@ +@@ -2047,7 +2047,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Restricts the total memory used for memory mapping of MySQL tables NUMERIC_MIN_VALUE 7 @@ -650,7 +641,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -1924,10 +1924,10 @@ +@@ -2064,10 +2064,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MYISAM_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -663,7 +654,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1937,7 +1937,7 @@ +@@ -2077,7 +2077,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -672,7 +663,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1974,7 +1974,7 @@ +@@ -2114,7 +2114,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME NET_BUFFER_LENGTH VARIABLE_SCOPE SESSION @@ -681,7 +672,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -1984,7 +1984,7 @@ +@@ -2124,7 +2124,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_READ_TIMEOUT VARIABLE_SCOPE SESSION @@ -690,7 +681,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1994,7 +1994,7 @@ +@@ -2134,7 +2134,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_RETRY_COUNT VARIABLE_SCOPE SESSION @@ -699,7 +690,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2004,7 +2004,7 @@ +@@ -2144,7 +2144,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_WRITE_TIMEOUT VARIABLE_SCOPE SESSION @@ -708,7 +699,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2054,7 +2054,7 @@ +@@ -2194,7 +2194,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -717,7 +708,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2064,7 +2064,7 @@ +@@ -2204,7 +2204,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -726,7 +717,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2074,7 +2074,7 @@ +@@ -2214,7 +2214,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -735,7 +726,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2084,7 +2084,7 @@ +@@ -2224,7 +2224,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -744,7 +735,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2104,7 +2104,7 @@ +@@ -2244,7 +2244,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY VARIABLE_SCOPE SESSION @@ -753,7 +744,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2124,7 +2124,7 @@ +@@ -2264,7 +2264,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -762,7 +753,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2134,7 +2134,7 @@ +@@ -2274,7 +2274,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -770,8 +761,8 @@ +VARIABLE_TYPE INT VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 - NUMERIC_MAX_VALUE 200 -@@ -2144,7 +2144,7 @@ + NUMERIC_MAX_VALUE 1048576 +@@ -2284,7 +2284,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -780,7 +771,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2154,7 +2154,7 @@ +@@ -2294,7 +2294,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -789,7 +780,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2164,7 +2164,7 @@ +@@ -2304,7 +2304,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -798,7 +789,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2174,7 +2174,7 @@ +@@ -2314,7 +2314,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -807,7 +798,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2184,7 +2184,7 @@ +@@ -2324,7 +2324,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -816,7 +807,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2194,7 +2194,7 @@ +@@ -2334,7 +2334,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -825,7 +816,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2204,7 +2204,7 @@ +@@ -2344,7 +2344,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -834,7 +825,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2214,7 +2214,7 @@ +@@ -2354,7 +2354,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -843,7 +834,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2224,7 +2224,7 @@ +@@ -2364,7 +2364,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -852,7 +843,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2234,7 +2234,7 @@ +@@ -2374,7 +2374,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -861,7 +852,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2244,7 +2244,7 @@ +@@ -2384,7 +2384,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -870,7 +861,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2254,7 +2254,7 @@ +@@ -2394,7 +2394,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -879,7 +870,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2264,7 +2264,7 @@ +@@ -2404,7 +2404,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -888,7 +879,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2274,7 +2274,7 @@ +@@ -2414,7 +2414,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -897,7 +888,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2284,7 +2284,7 @@ +@@ -2424,7 +2424,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -906,7 +897,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2294,7 +2294,7 @@ +@@ -2434,7 +2434,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -915,7 +906,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2304,7 +2304,7 @@ +@@ -2444,7 +2444,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -924,7 +915,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2314,7 +2314,7 @@ +@@ -2454,7 +2454,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -933,7 +924,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2324,7 +2324,7 @@ +@@ -2464,7 +2464,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -942,7 +933,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2334,7 +2334,7 @@ +@@ -2474,7 +2474,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -951,7 +942,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2344,7 +2344,7 @@ +@@ -2484,7 +2484,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -960,7 +951,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2354,7 +2354,7 @@ +@@ -2494,7 +2494,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -969,7 +960,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2364,7 +2364,7 @@ +@@ -2504,7 +2504,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -978,7 +969,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2374,7 +2374,7 @@ +@@ -2514,7 +2514,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -987,7 +978,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2384,7 +2384,7 @@ +@@ -2524,7 +2524,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -996,7 +987,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2394,7 +2394,7 @@ +@@ -2534,7 +2534,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -1005,7 +996,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2404,7 +2404,7 @@ +@@ -2544,7 +2544,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1014,7 +1005,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2414,7 +2414,7 @@ +@@ -2554,7 +2554,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1023,7 +1014,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2424,7 +2424,7 @@ +@@ -2564,7 +2564,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1032,7 +1023,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2474,7 +2474,7 @@ +@@ -2614,7 +2614,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1041,7 +1032,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2494,7 +2494,7 @@ +@@ -2634,7 +2634,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1050,7 +1041,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -2504,7 +2504,7 @@ +@@ -2644,7 +2644,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1059,7 +1050,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2554,7 +2554,7 @@ +@@ -2694,7 +2694,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1068,7 +1059,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2564,7 +2564,7 @@ +@@ -2704,7 +2704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1077,7 +1068,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2574,7 +2574,7 @@ +@@ -2714,7 +2714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1086,7 +1077,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2587,7 +2587,7 @@ +@@ -2727,7 +2727,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1095,7 +1086,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2624,7 +2624,7 @@ +@@ -2764,7 +2764,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1104,7 +1095,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2637,7 +2637,7 @@ +@@ -2777,7 +2777,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1113,7 +1104,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2647,14 +2647,14 @@ +@@ -2787,14 +2787,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1130,7 +1121,15 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -2664,7 +2664,7 @@ +@@ -2807,14 +2807,14 @@ + VARIABLE_TYPE BIGINT UNSIGNED + VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME READ_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1139,7 +1138,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2684,7 +2684,7 @@ +@@ -2834,7 +2834,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1148,7 +1147,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -2694,10 +2694,10 @@ +@@ -3034,10 +3034,10 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1161,7 +1160,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2724,7 +2724,7 @@ +@@ -3064,7 +3064,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1170,8 +1169,17 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2794,7 +2794,7 @@ - COMMAND_LINE_ARGUMENT OPTIONAL +@@ -3194,7 +3194,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16383 +@@ -3224,7 +3224,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -1179,7 +1187,43 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2804,7 +2804,7 @@ +@@ -3244,7 +3244,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 2147483647 +@@ -3264,7 +3264,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME SLAVE_PARALLEL_THREADS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16383 +@@ -3274,7 +3274,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_PARALLEL_WORKERS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Alias for slave_parallel_threads + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16383 +@@ -3314,7 +3314,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME SLAVE_TRANSACTION_RETRIES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout, before giving up and stopping + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -3334,7 +3334,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1188,7 +1232,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -2847,7 +2847,7 @@ +@@ -3377,7 +3377,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1197,7 +1241,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3054,7 +3054,7 @@ +@@ -3594,7 +3594,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1206,7 +1250,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -3114,7 +3114,7 @@ +@@ -3674,7 +3674,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1215,7 +1259,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -3124,7 +3124,7 @@ +@@ -3684,7 +3684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1224,7 +1268,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -3144,7 +3144,7 @@ +@@ -3704,7 +3704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1233,7 +1277,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -3154,7 +3154,7 @@ +@@ -3714,7 +3714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CONCURRENCY VARIABLE_SCOPE GLOBAL @@ -1242,7 +1286,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -3237,7 +3237,7 @@ +@@ -3867,7 +3867,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1251,7 +1295,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3247,7 +3247,7 @@ +@@ -3877,7 +3877,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 1024 @@ -1260,7 +1304,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3257,14 +3257,14 @@ +@@ -3887,14 +3887,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1277,7 +1321,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3274,7 +3274,7 @@ +@@ -3904,7 +3904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1286,7 +1330,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3404,7 +3404,7 @@ +@@ -4034,7 +4034,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1295,7 +1339,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -3431,7 +3431,7 @@ +@@ -4061,7 +4061,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 5ccabeecf2d..42c236bf54a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -632,6 +632,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME DEFAULT_MASTER_CONNECTION +VARIABLE_SCOPE SESSION ONLY +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Master connection to use for all slave variables and slave commands +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DEFAULT_REGEX_FLAGS VARIABLE_SCOPE SESSION VARIABLE_TYPE SET @@ -782,6 +792,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME EVENT_SCHEDULER +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Enable the event scheduler. Possible values are ON, OFF, and DISABLED (keep the event scheduler completely deactivated, it cannot be activated run-time) +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON,DISABLED,ORIGINAL +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME EXPENSIVE_SUBQUERY_LIMIT VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -952,6 +972,36 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME GTID_BINLOG_POS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Last GTID logged to the binary log, per replicationdomain +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME GTID_BINLOG_STATE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The internal GTID state of the binlog, used to keep track of all GTIDs ever logged to the binlog. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME GTID_CURRENT_POS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Current GTID position of the server. Per replication domain, this is either the last GTID replicated by a slave thread, or the GTID logged to the binary log, whichever is most recent. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME GTID_DOMAIN_ID VARIABLE_SCOPE SESSION VARIABLE_TYPE INT UNSIGNED @@ -962,6 +1012,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME GTID_IGNORE_DUPLICATES +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT When set, different master connections in multi-source replication are allowed to receive and process event groups with the same GTID (when using GTID mode). Only one will be applied, any others will be ignored. Within a given replication domain, just the sequence number will be used to decide whether a given GTID has been already applied; this means it is the responsibility of the user to ensure that GTID sequence numbers are strictly increasing. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME GTID_SEQ_NO VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED @@ -972,6 +1032,26 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME GTID_SLAVE_POS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The list of global transaction IDs that were last replicated on the server, one for each replication domain. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME GTID_STRICT_MODE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Enforce strict seq_no ordering of events in the binary log. Slave stops with an error if it encounters an event that would cause it to generate an out-of-order binlog if executed. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME HAVE_COMPRESS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -1332,6 +1412,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME LAST_GTID +VARIABLE_SCOPE SESSION ONLY +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The GTID of the last commit (if binlogging was enabled), or the empty string if none. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LAST_INSERT_ID VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED @@ -1422,6 +1512,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME LOG_BIN_BASENAME +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The full path of the binary log file names, excluding the extension. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOG_BIN_COMPRESS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -1442,6 +1542,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME LOG_BIN_INDEX +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT File that holds the names for last binary log files. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOG_BIN_TRUST_FUNCTION_CREATORS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -1482,6 +1592,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME LOG_SLAVE_UPDATES +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY YES +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LOG_SLOW_ADMIN_STATEMENTS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -1582,6 +1702,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME MASTER_VERIFY_CHECKSUM +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Force checksum verification of logged events in the binary log before sending them to slaves or printing them in the output of SHOW BINLOG EVENTS +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -1742,6 +1872,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME MAX_RELAY_LOG_SIZE +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT relay log will be rotated automatically when the size exceeds this value. If 0 at startup, it's set to max_binlog_size +NUMERIC_MIN_VALUE 4096 +NUMERIC_MAX_VALUE 1073741824 +NUMERIC_BLOCK_SIZE 4096 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SEEKS_FOR_KEY VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -2662,6 +2802,16 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME READ_BINLOG_SPEED_LIMIT +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME READ_BUFFER_SIZE VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -2692,6 +2842,196 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME RELAY_LOG +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The location and name to use for relay logs. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME RELAY_LOG_BASENAME +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The full path of the relay log file names, excluding the extension. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME RELAY_LOG_INDEX +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The location and name to use for the file that keeps a list of the last relay logs. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME RELAY_LOG_INFO_FILE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The location and name of the file that remembers where the SQL replication thread is in the relay logs. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME RELAY_LOG_PURGE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT if disabled - do not purge relay logs. if enabled - purge them as soon as they are no more needed. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME RELAY_LOG_RECOVERY +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Enables automatic relay log recovery right after the database startup, which means that the IO Thread starts re-fetching from the master right after the last transaction processed. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME RELAY_LOG_SPACE_LIMIT +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Maximum space to use for all relay logs +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME REPLICATE_ANNOTATE_ROW_EVENTS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Tells the slave to write annotate rows events received from the master to its own binary log. Ignored if log_slave_updates is not set +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY YES +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME REPLICATE_DO_DB +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Tell the slave to restrict replication to updates of tables whose names appear in the comma-separated list. For statement-based replication, only the default database (that is, the one selected by USE) is considered, not any explicitly mentioned tables in the query. For row-based replication, the actual names of table(s) being updated are checked. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME REPLICATE_DO_TABLE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Tells the slave to restrict replication to tables in the comma-separated list. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME REPLICATE_EVENTS_MARKED_FOR_SKIP +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Whether the slave should replicate events that were created with @@skip_replication=1 on the master. Default REPLICATE (no events are skipped). Other values are FILTER_ON_SLAVE (events will be sent by the master but ignored by the slave) and FILTER_ON_MASTER (events marked with @@skip_replication=1 will be filtered on the master and never be sent to the slave). +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST REPLICATE,FILTER_ON_SLAVE,FILTER_ON_MASTER +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME REPLICATE_IGNORE_DB +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Tell the slave to restrict replication to updates of tables whose names do not appear in the comma-separated list. For statement-based replication, only the default database (that is, the one selected by USE) is considered, not any explicitly mentioned tables in the query. For row-based replication, the actual names of table(s) being updated are checked. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME REPLICATE_IGNORE_TABLE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Tells the slave thread not to replicate any statement that updates the specified table, even if any other tables might be updated by the same statement. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME REPLICATE_WILD_DO_TABLE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Tells the slave thread to restrict replication to statements where any of the updated tables match the specified database and table name patterns. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME REPLICATE_WILD_IGNORE_TABLE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Tells the slave thread to not replicate to the tables that match the given wildcard pattern. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME REPORT_HOST +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Hostname or IP of the slave to be reported to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME REPORT_PASSWORD +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The account password of the slave to be reported to the master during slave registration +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME REPORT_PORT +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Port for connecting to slave reported to the master during slave registration. Set it only if the slave is listening on a non-default port or if you have a special tunnel from the master or other clients to the slave. If not sure, leave this option unset +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME REPORT_USER +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The account user name of the slave to be reported to the master during slave registration +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -2732,6 +3072,46 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SESSION_TRACK_SCHEMA +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Track changes to the default schema. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME SESSION_TRACK_STATE_CHANGE +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Track changes to the session state. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME SESSION_TRACK_SYSTEM_VARIABLES +VARIABLE_SCOPE SESSION +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Track changes in registered system variables. For compatibility with MySQL defaults this variable should be set to "autocommit, character_set_client, character_set_connection, character_set_results, time_zone" +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SESSION_TRACK_TRANSACTION_INFO +VARIABLE_SCOPE SESSION +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Track changes to the transaction attributes. OFF to disable; STATE to track just transaction state (Is there an active transaction? Does it have any data? etc.); CHARACTERISTICS to track transaction state and report all statements needed to start a transaction withthe same characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction). +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SKIP_EXTERNAL_LOCKING VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -2762,6 +3142,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME SKIP_PARALLEL_REPLICATION +VARIABLE_SCOPE SESSION ONLY +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT If set when a transaction is written to the binlog, parallel apply of that transaction will be avoided on a slave where slave_parallel_mode is not "aggressive". Can be used to avoid unnecessary rollback and retry for transactions that are likely to cause a conflict if replicated in parallel. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SKIP_REPLICATION VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BOOLEAN @@ -2792,6 +3182,46 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME SLAVE_DDL_EXEC_MODE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT How replication events should be executed. Legal values are STRICT and IDEMPOTENT (default). In IDEMPOTENT mode, replication will not stop for DDL operations that are idempotent. This means that CREATE TABLE is treated as CREATE TABLE OR REPLACE and DROP TABLE is treated as DROP TABLE IF EXISTS. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST STRICT,IDEMPOTENT +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 16383 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_EXEC_MODE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT How replication events should be executed. Legal values are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will not stop for operations that are idempotent. For example, in row based replication attempts to delete rows that doesn't exist will be ignored. In STRICT mode, replication will stop on any unexpected difference between the master and the slave. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST STRICT,IDEMPOTENT +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_LOAD_TMPDIR +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT The location where the slave should put its temporary files when replicating a LOAD DATA INFILE command +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED @@ -2802,6 +3232,106 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_NET_TIMEOUT +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Number of seconds to wait for more data from any master/slave connection before aborting the read +NUMERIC_MIN_VALUE 1 +NUMERIC_MAX_VALUE 31536000 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 2147483647 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_PARALLEL_MODE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Controls what transactions are applied in parallel when using --slave-parallel-threads. Possible values: "optimistic" tries to apply most transactional DML in parallel, and handles any conflicts with rollback and retry. "conservative" limits parallelism in an effort to avoid any conflicts. "aggressive" tries to maximise the parallelism, possibly at the cost of increased conflict rate. "minimal" only parallelizes the commit steps of transactions. "none" disables parallel apply completely. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST none,minimal,conservative,optimistic,aggressive +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME SLAVE_PARALLEL_THREADS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 16383 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_PARALLEL_WORKERS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Alias for slave_parallel_threads +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 16383 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_RUN_TRIGGERS_FOR_RBR +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Modes for how triggers in row-base replication on slave side will be executed. Legal values are NO (default), YES and LOGGING. NO means that trigger for RBR will not be running on slave. YES and LOGGING means that triggers will be running on slave, if there was not triggers running on the master for the statement. LOGGING also means results of that the executed triggers work will be written to the binlog. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NO,YES,LOGGING +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_SKIP_ERRORS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Tells the slave thread to continue replication when a query event returns an error from the provided list +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_SQL_VERIFY_CHECKSUM +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Force checksum verification of replication events after reading them from relay log. Note: Events are always checksum-verified by slave on receiving them from the network before writing them to the relay log +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME SLAVE_TRANSACTION_RETRIES +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout, before giving up and stopping +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_TYPE_CONVERSIONS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE SET +VARIABLE_COMMENT Set of slave type conversions that are enabled. If the variable is empty, no conversions are allowed and it is expected that the types match exactly +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST ALL_LOSSY,ALL_NON_LOSSY +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED @@ -2952,6 +3482,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME SQL_SLAVE_SKIP_COUNTER +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Skip the next N events from the master log +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SQL_WARNINGS VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN @@ -2971,7 +3511,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SSL_CAPATH VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -2981,7 +3521,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SSL_CERT VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -2991,7 +3531,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SSL_CIPHER VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3001,7 +3541,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SSL_CRL VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3011,7 +3551,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SSL_CRLPATH VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3021,7 +3561,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SSL_KEY VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3031,7 +3571,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME STANDARD_COMPLIANT_CTE VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN @@ -3102,6 +3642,26 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SYNC_RELAY_LOG +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Synchronously flush relay log to disk after every #th event. Use 0 to disable synchronous flushing +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SYNC_RELAY_LOG_INFO +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Synchronously flush relay log info to disk after every #th transaction. Use 0 to disable synchronous flushing +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SYSTEM_TIME_ZONE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3169,9 +3729,79 @@ VARIABLE_COMMENT Define threads usage for handling queries NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST one-thread-per-connection,no-threads +ENUM_VALUE_LIST one-thread-per-connection,no-threads,pool-of-threads READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME THREAD_POOL_IDLE_TIMEOUT +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Timeout in seconds for an idle thread in the thread pool.Worker thread will be shut down after timeout +NUMERIC_MIN_VALUE 1 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME THREAD_POOL_MAX_THREADS +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Maximum allowed number of worker threads in the thread pool +NUMERIC_MIN_VALUE 1 +NUMERIC_MAX_VALUE 65536 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME THREAD_POOL_OVERSUBSCRIBE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT How many additional active worker threads in a group are allowed. +NUMERIC_MIN_VALUE 1 +NUMERIC_MAX_VALUE 1000 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME THREAD_POOL_PRIORITY +VARIABLE_SCOPE SESSION +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Threadpool priority. High priority connections usually start executing earlier than low priority.If priority set to 'auto', the the actual priority(low or high) is determined based on whether or not connection is inside transaction. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST high,low,auto +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME THREAD_POOL_PRIO_KICKUP_TIMER +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT The number of milliseconds before a dequeued low-priority statement is moved to the high-priority queue +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME THREAD_POOL_SIZE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Number of thread groups in the pool. This parameter is roughly equivalent to maximum number of concurrently executing threads (threads in a waiting state do not count as executing). +NUMERIC_MIN_VALUE 1 +NUMERIC_MAX_VALUE 100000 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME THREAD_POOL_STALL_LIMIT +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Maximum query execution time in milliseconds,before an executing non-yielding thread is considered stalled.If a worker thread is stalled, additional worker thread may be created to handle remaining clients. +NUMERIC_MIN_VALUE 10 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_STACK VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED diff --git a/mysql-test/t/events_embedded.test b/mysql-test/t/events_embedded.test index 9922ea6dfee..e0bde053e8a 100644 --- a/mysql-test/t/events_embedded.test +++ b/mysql-test/t/events_embedded.test @@ -1,5 +1,5 @@ --source include/is_embedded.inc ---error 1193 set global event_scheduler=ON; +set global event_scheduler=ORIGINAL; -- cgit v1.2.1 From 8b3b73808d90f25a3ec5698864d9b406ae7bba80 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 May 2020 16:19:49 +1000 Subject: MDEV-27635: selinux: allow read of /proc/sys/kernel/core_pattern Prevent the error: setroubleshoot[23678]: SELinux is preventing /usr/libexec/mysqld from read access on the file core_pattern. Reading of the core pattern occurs on crash as added in MDEV-15051 RHEL-7.7 $ ls -laZ /proc/sys/kernel/core_pattern -rw-r--r--. root root system_u:object_r:usermodehelper_t:s0 /proc/sys/kernel/core_pattern --- support-files/policy/selinux/mariadb-server.te | 1 + 1 file changed, 1 insertion(+) diff --git a/support-files/policy/selinux/mariadb-server.te b/support-files/policy/selinux/mariadb-server.te index 45ef40f4153..c8b2c21ff07 100644 --- a/support-files/policy/selinux/mariadb-server.te +++ b/support-files/policy/selinux/mariadb-server.te @@ -77,6 +77,7 @@ allow mysqld_t user_tmp_t:dir { write add_name }; allow mysqld_t user_tmp_t:file create; allow mysqld_t bin_t:lnk_file read; allow mysqld_t tmp_t:file { append create read write open getattr unlink setattr }; +allow mysqld_t usermodehelper_t:file { read open }; # Allows too much leeway - the xtrabackup/wsrep rules in fc should fix it, but # keep for the moment. -- cgit v1.2.1 From 2ef12cab420786da6c16d0b6d05386b6bbb90f3c Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 18 Jan 2022 19:56:43 +0200 Subject: MDEV-27536 invalid BINLOG_BASE64_EVENT and assertion Diagnostics_area:: !is_set() The assert was caused by an error of XA transaction that had BINLOG 'base64_string' statement. The statement failed because of lack of checking whether the encoded replication event was handled by the slave applier thread. If it's not the slave applier no error should be generated, but it was in this case, see a test added. Fixed along with the idea borrowed the upstream to introduce a check of which applier executes the replication event and do not report any error if the applier is a regular server client. --- .../suite/binlog/r/binlog_xa_handling.result | 11 +++++++++ mysql-test/suite/binlog/t/binlog_xa_handling.test | 28 ++++++++++++++++++++++ sql/log_event.cc | 3 ++- 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/binlog/r/binlog_xa_handling.result create mode 100644 mysql-test/suite/binlog/t/binlog_xa_handling.test diff --git a/mysql-test/suite/binlog/r/binlog_xa_handling.result b/mysql-test/suite/binlog/r/binlog_xa_handling.result new file mode 100644 index 00000000000..980045a08d0 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_xa_handling.result @@ -0,0 +1,11 @@ +connection default; +CREATE TABLE t1(f1 int) ENGINE=Innodb; +XA START '',''; +INSERT INTO t1 VALUES(10); +BINLOG ' +SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8='; +XA END ''; +XA PREPARE ''; +XA ROLLBACK ''; +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_xa_handling.test b/mysql-test/suite/binlog/t/binlog_xa_handling.test new file mode 100644 index 00000000000..00e8cfea296 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_handling.test @@ -0,0 +1,28 @@ +############################################################################### +# Bug#19928622: ASSERTION `! IS_SET()' FAILED. | ABORT IN +# DIAGNOSTICS_AREA::SET_OK_STATUS +# +# MDEV-27536 Invalid BINLOG_BASE64_EVENT and assertion Diagnostics_area:: !is_set() +# +# Test: +# ===== +# Begin an XA transaction and execte a DML statement so that XA state becomes +# XA_ACTIVE. Execute the BINLOG command it should not cause any assert. +# Execution should be successful. +############################################################################### +--source include/have_log_bin.inc +--source include/have_innodb.inc + +--connection default +CREATE TABLE t1(f1 int) ENGINE=Innodb; + +XA START '',''; +INSERT INTO t1 VALUES(10); +BINLOG ' +SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8='; +XA END ''; +XA PREPARE ''; +XA ROLLBACK ''; + +DROP TABLE t1; diff --git a/sql/log_event.cc b/sql/log_event.cc index 9108b57fec1..f8373202750 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6167,7 +6167,8 @@ int Format_description_log_event::do_apply_event(rpl_group_info *rgi) original place when it comes to us; we'll know this by checking log_pos ("artificial" events have log_pos == 0). */ - if (!is_artificial_event() && created && thd->transaction.all.ha_list) + if (!thd->rli_fake && + !is_artificial_event() && created && thd->transaction.all.ha_list) { /* This is not an error (XA is safe), just an information */ rli->report(INFORMATION_LEVEL, 0, NULL, -- cgit v1.2.1 From 8d9b1aa0d6e424fe3b73badf56bc561c81063b9c Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 27 Jan 2022 13:44:39 +0200 Subject: MDEV-27536 incremental commit to correct regression test. --- mysql-test/suite/binlog/r/binlog_xa_handling.result | 8 ++++---- mysql-test/suite/binlog/t/binlog_xa_handling.test | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_xa_handling.result b/mysql-test/suite/binlog/r/binlog_xa_handling.result index 980045a08d0..7a60fb59b9a 100644 --- a/mysql-test/suite/binlog/r/binlog_xa_handling.result +++ b/mysql-test/suite/binlog/r/binlog_xa_handling.result @@ -1,11 +1,11 @@ connection default; CREATE TABLE t1(f1 int) ENGINE=Innodb; -XA START '',''; +XA START 'xa'; INSERT INTO t1 VALUES(10); BINLOG ' SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8='; -XA END ''; -XA PREPARE ''; -XA ROLLBACK ''; +XA END 'xa'; +XA PREPARE 'xa'; +XA ROLLBACK 'xa'; DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_xa_handling.test b/mysql-test/suite/binlog/t/binlog_xa_handling.test index 00e8cfea296..c454e83169e 100644 --- a/mysql-test/suite/binlog/t/binlog_xa_handling.test +++ b/mysql-test/suite/binlog/t/binlog_xa_handling.test @@ -16,13 +16,13 @@ --connection default CREATE TABLE t1(f1 int) ENGINE=Innodb; -XA START '',''; +XA START 'xa'; INSERT INTO t1 VALUES(10); BINLOG ' SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8='; -XA END ''; -XA PREPARE ''; -XA ROLLBACK ''; +XA END 'xa'; +XA PREPARE 'xa'; +XA ROLLBACK 'xa'; DROP TABLE t1; -- cgit v1.2.1 From 93a5fb00252c54cad2844b385808a1c6ff0037eb Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 27 Jan 2022 14:43:21 +0200 Subject: MDEV-27477 Remaining SUSE patches for 10.2+ This patch let's you specify not only user to use but also group that MariaDB should use. Original patch: https://github.com/openSUSE/mysql-packaging/blob/master/patches/mysql-patches/mariadb-10.2.3-group.patch Author: Kristyna Streitova Reviewer: monty@mariadb.org --- scripts/CMakeLists.txt | 1 + scripts/mysql_install_db.sh | 22 +++++++++++++++++++--- scripts/mysqld_safe.sh | 10 +++++++++- support-files/CMakeLists.txt | 1 + 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 190d9f774fb..ec8a53c1b90 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -163,6 +163,7 @@ ENDIF() SET(HOSTNAME "hostname") SET(MYSQLD_USER "mysql") +SET(MYSQLD_GROUP "mysql") ENDIF(UNIX) # Really ugly, one script, "mysql_install_db", needs prefix set to ".", diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index fdd3a42d77f..2a23eb987b4 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -30,6 +30,7 @@ defaults="" defaults_group_suffix="" mysqld_opt="" user="" +group="" silent_startup="--silent-startup" force=0 @@ -98,6 +99,11 @@ Usage: $0 [OPTIONS] user. You must be root to use this option. By default mysqld runs using your current login name and files and directories that it creates will be owned by you. + --group=group_name The login group to use for running mysqld. Files and + directories created by mysqld will be owned by this + group. You must be root to use this option. By default + mysqld runs using your current group and files and + directories that it creates will be owned by you. --upgrade-info Store mysql_upgrade_info in the installed data directory. All other options are passed to the mysqld program @@ -146,11 +152,11 @@ parse_arguments() --builddir=*) builddir=`parse_arg "$arg"` ;; --srcdir=*) srcdir=`parse_arg "$arg"` ;; --ldata=*|--datadir=*|--data=*) ldata=`parse_arg "$arg"` ;; - --user=*) # Note that the user will be passed to mysqld so that it runs # as 'user' (crucial e.g. if log-bin=/some_other_path/ # where a chown of datadir won't help) - user=`parse_arg "$arg"` ;; + --user=*) user=`parse_arg "$arg"` ;; + --group=*) group=`parse_arg "$arg"` ;; --skip-name-resolve) ip_only=1 ;; --verbose) verbose=1 ; silent_startup="" ;; --rpm) in_rpm=1 ;; @@ -461,7 +467,12 @@ do fi if test -n "$user" then - chown $user "$dir" + if test -z "$group" + then + chown $user $dir + else + chown $user:$group $dir + fi if test $? -ne 0 then echo "Cannot change ownership of the database directories to the '$user'" @@ -476,6 +487,11 @@ then args="$args --user=$user" fi +if test -n "$group" +then + args="$args --group=$group" +fi + # When doing a "cross bootstrap" install, no reference to the current # host should be added to the system tables. So we filter out any # lines which contain the current host name. diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 9f539bf875d..29b6d839685 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -29,6 +29,7 @@ logging=init want_syslog=0 syslog_tag= user='@MYSQLD_USER@' +group='@MYSQLD_GROUP@' pid_file= err_log= err_log_base= @@ -318,6 +319,7 @@ parse_arguments() { --pid[-_]file=*) pid_file="$val" ;; --plugin[-_]dir=*) PLUGIN_DIR="$val" ;; --user=*) user="$val"; SET_USER=1 ;; + --group=*) group="$val"; SET_USER=1 ;; --log[-_]basename=*|--hostname=*|--loose[-_]log[-_]basename=*) pid_file="$val.pid"; err_log_base="$val"; @@ -720,6 +722,7 @@ then if test "$user" != "root" -o $SET_USER = 1 then USER_OPTION="--user=$user" + GROUP_OPTION="--group=$group" fi if test -n "$open_files" then @@ -742,7 +745,12 @@ then log_error "Fatal error Can't create database directory '$mysql_unix_port'" exit 1 fi - chown $user $mysql_unix_port_dir + if [ "$user" -a "$group" ]; then + chown $user:$group $mysql_unix_port_dir + else + [ "$user" ] && chown $user $mysql_unix_port_dir + [ "$group" ] && chgrp $group $mysql_unix_port_dir + fi chmod 755 $mysql_unix_port_dir fi diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index 028201cb1b1..3b93f87cae7 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -29,6 +29,7 @@ ELSE() SET(CFLAGS ${CMAKE_C_FLAGS}) SET(CXXFLAGS ${CMAKE_CXX_FLAGS}) SET(MYSQLD_USER "mysql") + SET(MYSQLD_GROUP "mysql") SET(ini_file_extension "cnf") SET(HOSTNAME "hostname") ENDIF() -- cgit v1.2.1 From 5acc79d03099568be42ddbc2faa506d2a5b69cf2 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 27 Jan 2022 14:51:16 +0200 Subject: Remove --upgrade-info option from mysql_upgrade Removed the option as it safe to always create the file when we have created the MariaDB data directories. This fixes this issue not only for debian but for all MariaDB users. --- debian/mariadb-server-10.2.postinst | 2 +- man/mysql_install_db.1 | 15 --------------- scripts/mysql_install_db.sh | 6 ------ 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/debian/mariadb-server-10.2.postinst b/debian/mariadb-server-10.2.postinst index 3fe5a04fbc3..14b2053b3a0 100644 --- a/debian/mariadb-server-10.2.postinst +++ b/debian/mariadb-server-10.2.postinst @@ -144,7 +144,7 @@ EOF # Debian: beware of the bashisms... # Debian: can safely run on upgrades with existing databases set +e - bash /usr/bin/mysql_install_db --rpm --cross-bootstrap --user=mysql --disable-log-bin --upgrade-info 2>&1 | $ERR_LOGGER + bash /usr/bin/mysql_install_db --rpm --cross-bootstrap --user=mysql --disable-log-bin 2>&1 | $ERR_LOGGER set -e ## On every reconfiguration the maintenance user is recreated. diff --git a/man/mysql_install_db.1 b/man/mysql_install_db.1 index 229a6f8df99..3406c9605b7 100644 --- a/man/mysql_install_db.1 +++ b/man/mysql_install_db.1 @@ -276,21 +276,6 @@ This must be given as the first argument\&. .sp -1 .IP \(bu 2.3 .\} -.\" mysql_install_db: upgrade-info option -.\" upgrade-info option: mysql_install_db -\fB\-\-upgrade\-info\fR -.sp -This places a mysql_upgrade_info file containing the server version in the data directory\&. -.RE -.sp -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.sp -1 -.IP \(bu 2.3 -.\} .\" mysql_install_db: rpm option .\" rpm option: mysql_install_db \fB\-\-rpm\fR diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 2a23eb987b4..d1c0fc67baf 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -42,7 +42,6 @@ create database if not exists test; use mysql;" auth_root_authentication_method=normal auth_root_socket_user='root' -upgrade_info=0 dirname0=`dirname $0 2>/dev/null` dirname0=`dirname $dirname0 2>/dev/null` @@ -104,7 +103,6 @@ Usage: $0 [OPTIONS] group. You must be root to use this option. By default mysqld runs using your current group and files and directories that it creates will be owned by you. - --upgrade-info Store mysql_upgrade_info in the installed data directory. All other options are passed to the mysqld program @@ -160,7 +158,6 @@ parse_arguments() --skip-name-resolve) ip_only=1 ;; --verbose) verbose=1 ; silent_startup="" ;; --rpm) in_rpm=1 ;; - --upgrade-info) upgrade_info=1 ;; --help) usage ;; --no-defaults|--defaults-file=*|--defaults-extra-file=*) defaults="$arg" ;; @@ -528,10 +525,7 @@ SET @auth_root_socket='$auth_root_socket_user';" ;; esac if { echo "$install_params"; cat "$create_system_tables" "$create_system_tables2" "$fill_system_tables" "$fill_help_tables" "$maria_add_gis_sp"; } | eval "$filter_cmd_line" | mysqld_install_cmd_line > /dev/null then - if test "$upgrade_info" -eq 1 - then printf "@VERSION@-MariaDB" > "$ldata/mysql_upgrade_info" - fi s_echo "OK" else echo -- cgit v1.2.1 From e99d3da6381023395c86f679bb76b00b4385dc2d Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 27 Jan 2022 16:04:58 +0200 Subject: Silence the file-key-management plugin during mysql_install_db This avoids printing the error "mysqld: file-key-management-filename is not set" which can happen if the file-key-management pluging is statically compiled --- scripts/mysql_install_db.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index d1c0fc67baf..63c014ea098 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -505,7 +505,7 @@ mysqld_install_cmd_line() { "$mysqld_bootstrap" $defaults $defaults_group_suffix "$mysqld_opt" --bootstrap $silent_startup\ "--basedir=$basedir" "--datadir=$ldata" --log-warnings=0 --enforce-storage-engine="" \ - "--plugin-dir=${plugindir}" \ + "--plugin-dir=${plugindir}" --loose-disable-plugin-file-key-management \ $args --max_allowed_packet=8M \ --net_buffer_length=16K } -- cgit v1.2.1 From 24c51be6fe66d65e711af210ca4ba26c9cbabe53 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 27 Jan 2022 21:44:45 +0200 Subject: Fixed compilation error if HAVE_CRYPT is not defined --- sql/item_strfunc.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index e5935178f10..7fa3fb0b4b6 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2203,9 +2203,10 @@ char *Item_func_password::alloc(THD *thd, const char *password, String *Item_func_encrypt::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); #ifdef HAVE_CRYPT + String *res =args[0]->val_str(str); + char salt[3],*salt_ptr; if ((null_value=args[0]->null_value)) return 0; -- cgit v1.2.1 From 7045ec27a6d560752717a0db0e4fb6eba5dc0be9 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 28 Jan 2022 13:53:39 +0200 Subject: Fixed wrong function call in embedded server This happens when compiled with HAVE_EMBEDDED_PRIVILEGE_CONTROL. There is a lot of other problems with the above option that should be fixed at some point --- libmysqld/lib_sql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index ddb3f2c71aa..a0c57239dec 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -831,7 +831,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db) /* acl_authenticate() takes the data from thd->net->read_pos */ thd->net.read_pos= (uchar*)buf; - if (acl_authenticate(thd, 0, end - buf)) + if (acl_authenticate(thd, (uint) (end - buf))) { my_free(thd->security_ctx->user); goto err; -- cgit v1.2.1 From a1f630ccfe33a14ee3c535a78b645d384c82876d Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 27 Jan 2022 21:48:02 +0200 Subject: Fixed result for embedded server - Revert wrongly record embedded result files. These were either recorded with normal server (not embedded) or an embedded server with not default compile option. This can be seen that the committed result file had replication variables which should never happen. - Reverted back change of include/is_embedded.inc. One cannot check for $MYSQL_EMBEDDED as this only tells if there exists an embedded server, not if the current server we are testing is the embedded server. This could easily be verified by doing 'mtr sys_vars.sysvars_server_embedded'. This would fail with a wrong result instead of being marked as skipped as --embedded was not used. --- mysql-test/include/is_embedded.inc | 6 +- mysql-test/include/is_embedded_no_privileges.inc | 16 + mysql-test/suite/funcs_1/datadict/columns.inc | 4 + .../suite/funcs_1/r/is_columns_is_embedded.result | 948 ++++++++++----------- .../suite/funcs_1/t/is_columns_is_embedded.test | 2 +- .../funcs_1/t/is_columns_myisam_embedded.test | 6 +- .../suite/funcs_1/t/is_columns_mysql_embedded.test | 5 +- .../sys_vars/r/sysvars_server_embedded,32bit.rdiff | 285 +++---- .../sys_vars/r/sysvars_server_embedded.result | 646 +------------- 9 files changed, 626 insertions(+), 1292 deletions(-) create mode 100644 mysql-test/include/is_embedded_no_privileges.inc diff --git a/mysql-test/include/is_embedded.inc b/mysql-test/include/is_embedded.inc index ee2fefa51da..a440406edd4 100644 --- a/mysql-test/include/is_embedded.inc +++ b/mysql-test/include/is_embedded.inc @@ -1,5 +1,7 @@ -if(!$MYSQL_EMBEDDED) +# +# Check if the current used server is an embedded server# +# +if (`SELECT VERSION() NOT LIKE '%embedded%'`) { --skip Test requires: embedded server } - diff --git a/mysql-test/include/is_embedded_no_privileges.inc b/mysql-test/include/is_embedded_no_privileges.inc new file mode 100644 index 00000000000..364c697c5a8 --- /dev/null +++ b/mysql-test/include/is_embedded_no_privileges.inc @@ -0,0 +1,16 @@ +# +# Test that we do not have an embedded server compiled with privileges. +# This is not a regular setup, but we are running this in buildbot for +# testing of embedded + privileges. +# Some funcs_1 test cannot handle this combination, which is why we have this +# file to disable them +# + +--source include/is_embedded.inc + +let priv=`SELECT privileges FROM information_schema.columns limit 1`; + +if (`SELECT "$priv" <> ""`) +{ + --skip Embedded server is compiled with privileges; Test disabled. +} diff --git a/mysql-test/suite/funcs_1/datadict/columns.inc b/mysql-test/suite/funcs_1/datadict/columns.inc index 64318492b00..a03fef9c0dd 100644 --- a/mysql-test/suite/funcs_1/datadict/columns.inc +++ b/mysql-test/suite/funcs_1/datadict/columns.inc @@ -25,6 +25,10 @@ # --source suite/funcs_1/datadict/datadict_bug_12777.inc + +# The following is needed as embedded server can be compiled with and without +# privlege tables + eval SELECT * FROM information_schema.columns $my_where diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result index 3282d30669e..9116830e88c 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result @@ -3,480 +3,480 @@ WHERE table_schema = 'information_schema' AND table_name <> 'profiling' AND table_name not like 'innodb_%' ORDER BY table_schema, table_name, column_name; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE DATETIME_PRECISION CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT IS_GENERATED GENERATION_EXPRESSION -def information_schema ALL_PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema ALL_PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema APPLICABLE_ROLES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL -def information_schema APPLICABLE_ROLES IS_DEFAULT 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema APPLICABLE_ROLES IS_GRANTABLE 3 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema APPLICABLE_ROLES ROLE_NAME 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL -def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema CHARACTER_SETS DESCRIPTION 3 '' NO varchar 60 180 NULL NULL NULL utf8 utf8_general_ci varchar(60) select NEVER NULL -def information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) select NEVER NULL -def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 5 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema CHECK_CONSTRAINTS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL -def information_schema CLIENT_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS CLIENT 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS CONNECTED_TIME 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL -def information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS 2 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema CLIENT_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema CLIENT_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema COLLATIONS CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema COLLATIONS COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(11) select NEVER NULL -def information_schema COLLATIONS IS_COMPILED 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema COLLATIONS IS_DEFAULT 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema COLLATIONS SORTLEN 6 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) select NEVER NULL -def information_schema COLLATION_CHARACTER_SET_APPLICABILITY CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema COLUMNS CHARACTER_MAXIMUM_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema COLUMNS CHARACTER_OCTET_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema COLUMNS CHARACTER_SET_NAME 14 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema COLUMNS COLLATION_NAME 15 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema COLUMNS COLUMN_COMMENT 20 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select NEVER NULL -def information_schema COLUMNS COLUMN_DEFAULT 6 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema COLUMNS COLUMN_KEY 17 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema COLUMNS COLUMN_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema COLUMNS COLUMN_TYPE 16 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema COLUMNS DATA_TYPE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema COLUMNS DATETIME_PRECISION 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema COLUMNS EXTRA 18 '' NO varchar 30 90 NULL NULL NULL utf8 utf8_general_ci varchar(30) select NEVER NULL -def information_schema COLUMNS GENERATION_EXPRESSION 22 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema COLUMNS IS_GENERATED 21 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) select NEVER NULL -def information_schema COLUMNS IS_NULLABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema COLUMNS NUMERIC_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema COLUMNS NUMERIC_SCALE 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema COLUMNS ORDINAL_POSITION 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema COLUMNS PRIVILEGES 19 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema COLUMNS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema COLUMNS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema COLUMNS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema COLUMN_PRIVILEGES COLUMN_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema COLUMN_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL -def information_schema COLUMN_PRIVILEGES IS_GRANTABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema COLUMN_PRIVILEGES PRIVILEGE_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema COLUMN_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema COLUMN_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema COLUMN_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ENABLED_ROLES ROLE_NAME 1 NULL YES varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL -def information_schema ENGINES COMMENT 3 '' NO varchar 160 480 NULL NULL NULL utf8 utf8_general_ci varchar(160) select NEVER NULL -def information_schema ENGINES ENGINE 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ENGINES SAVEPOINTS 6 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema ENGINES SUPPORT 2 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL -def information_schema ENGINES TRANSACTIONS 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema ENGINES XA 5 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema EVENTS CHARACTER_SET_CLIENT 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema EVENTS COLLATION_CONNECTION 23 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema EVENTS CREATED 17 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema EVENTS DATABASE_COLLATION 24 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema EVENTS DEFINER 4 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL -def information_schema EVENTS ENDS 14 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema EVENTS EVENT_BODY 6 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL -def information_schema EVENTS EVENT_CATALOG 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema EVENTS EVENT_COMMENT 20 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema EVENTS EVENT_DEFINITION 7 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema EVENTS EVENT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema EVENTS EVENT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema EVENTS EVENT_TYPE 8 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL -def information_schema EVENTS EXECUTE_AT 9 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema EVENTS INTERVAL_FIELD 11 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) select NEVER NULL -def information_schema EVENTS INTERVAL_VALUE 10 NULL YES varchar 256 768 NULL NULL NULL utf8 utf8_general_ci varchar(256) select NEVER NULL -def information_schema EVENTS LAST_ALTERED 18 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema EVENTS LAST_EXECUTED 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema EVENTS ON_COMPLETION 16 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL -def information_schema EVENTS ORIGINATOR 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) select NEVER NULL -def information_schema EVENTS SQL_MODE 12 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) select NEVER NULL -def information_schema EVENTS STARTS 13 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema EVENTS STATUS 15 '' NO varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) select NEVER NULL -def information_schema EVENTS TIME_ZONE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES AUTOEXTEND_SIZE 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES AVG_ROW_LENGTH 28 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES CHECKSUM 36 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES CHECK_TIME 35 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema FILES CREATE_TIME 33 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema FILES CREATION_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema FILES DATA_FREE 32 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES DATA_LENGTH 29 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES DELETED_ROWS 12 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES ENGINE 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES EXTENT_SIZE 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES EXTRA 38 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_general_ci varchar(255) select NEVER NULL -def information_schema FILES FILE_ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES FILE_NAME 2 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema FILES FILE_TYPE 3 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema FILES FREE_EXTENTS 14 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES FULLTEXT_KEYS 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES INDEX_LENGTH 31 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES INITIAL_SIZE 17 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES LAST_ACCESS_TIME 22 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema FILES LAST_UPDATE_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema FILES LOGFILE_GROUP_NAME 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES LOGFILE_GROUP_NUMBER 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES MAXIMUM_SIZE 18 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES MAX_DATA_LENGTH 30 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES RECOVER_TIME 23 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES ROW_FORMAT 26 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL -def information_schema FILES STATUS 37 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema FILES TABLESPACE_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES TABLE_CATALOG 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES TABLE_NAME 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES TABLE_ROWS 27 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema FILES TABLE_SCHEMA 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema FILES TOTAL_EXTENTS 15 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES TRANSACTION_COUNTER 24 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES UPDATE_COUNT 13 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema FILES UPDATE_TIME 34 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema FILES VERSION 25 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema GEOMETRY_COLUMNS COORD_DIMENSION 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL -def information_schema GEOMETRY_COLUMNS F_GEOMETRY_COLUMN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GEOMETRY_COLUMNS F_TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema GEOMETRY_COLUMNS F_TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GEOMETRY_COLUMNS F_TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GEOMETRY_COLUMNS GEOMETRY_TYPE 10 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) select NEVER NULL -def information_schema GEOMETRY_COLUMNS G_GEOMETRY_COLUMN 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GEOMETRY_COLUMNS G_TABLE_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema GEOMETRY_COLUMNS G_TABLE_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GEOMETRY_COLUMNS G_TABLE_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GEOMETRY_COLUMNS MAX_PPR 12 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL -def information_schema GEOMETRY_COLUMNS SRID 13 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) select NEVER NULL -def information_schema GEOMETRY_COLUMNS STORAGE_TYPE 9 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL -def information_schema GLOBAL_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema INDEX_STATISTICS INDEX_NAME 3 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL -def information_schema INDEX_STATISTICS ROWS_READ 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema INDEX_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL -def information_schema INDEX_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL -def information_schema KEYWORDS WORD 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES KEY_CACHE_NAME 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL -def information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES SEGMENTS 2 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned select NEVER NULL -def information_schema KEY_CACHES SEGMENT_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned select NEVER NULL -def information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_COLUMN_USAGE ORDINAL_POSITION 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) select NEVER NULL -def information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(10) select NEVER NULL -def information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARAMETERS COLLATION_NAME 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARAMETERS DATA_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARAMETERS DATETIME_PRECISION 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARAMETERS DTD_IDENTIFIER 15 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema PARAMETERS NUMERIC_PRECISION 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema PARAMETERS NUMERIC_SCALE 11 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema PARAMETERS ORDINAL_POSITION 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema PARAMETERS PARAMETER_MODE 5 NULL YES varchar 5 15 NULL NULL NULL utf8 utf8_general_ci varchar(5) select NEVER NULL -def information_schema PARAMETERS PARAMETER_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARAMETERS ROUTINE_TYPE 16 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL -def information_schema PARAMETERS SPECIFIC_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema PARAMETERS SPECIFIC_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARAMETERS SPECIFIC_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARTITIONS AVG_ROW_LENGTH 14 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS CHECKSUM 22 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS CHECK_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema PARTITIONS CREATE_TIME 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema PARTITIONS DATA_FREE 18 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS DATA_LENGTH 15 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS INDEX_LENGTH 17 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS MAX_DATA_LENGTH 16 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS NODEGROUP 24 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL -def information_schema PARTITIONS PARTITION_COMMENT 23 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema PARTITIONS PARTITION_DESCRIPTION 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema PARTITIONS PARTITION_EXPRESSION 10 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema PARTITIONS PARTITION_METHOD 8 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) select NEVER NULL -def information_schema PARTITIONS PARTITION_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARTITIONS PARTITION_ORDINAL_POSITION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS SUBPARTITION_EXPRESSION 11 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema PARTITIONS SUBPARTITION_METHOD 9 NULL YES varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL -def information_schema PARTITIONS SUBPARTITION_NAME 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARTITIONS SUBPARTITION_ORDINAL_POSITION 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS TABLESPACE_NAME 25 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARTITIONS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema PARTITIONS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARTITIONS TABLE_ROWS 13 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema PARTITIONS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PARTITIONS UPDATE_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) select NEVER NULL -def information_schema PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL -def information_schema PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select NEVER NULL -def information_schema PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) select NEVER NULL -def information_schema PROCESSLIST COMMAND 5 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL -def information_schema PROCESSLIST DB 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PROCESSLIST EXAMINED_ROWS 14 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) select NEVER NULL -def information_schema PROCESSLIST HOST 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PROCESSLIST ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema PROCESSLIST INFO 8 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema PROCESSLIST INFO_BINARY 16 NULL YES blob 65535 65535 NULL NULL NULL NULL NULL blob select NEVER NULL -def information_schema PROCESSLIST MAX_STAGE 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL -def information_schema PROCESSLIST MEMORY_USED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(7) select NEVER NULL -def information_schema PROCESSLIST PROGRESS 12 0.000 NO decimal NULL NULL 7 3 NULL NULL NULL decimal(7,3) select NEVER NULL -def information_schema PROCESSLIST QUERY_ID 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema PROCESSLIST STAGE 10 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL -def information_schema PROCESSLIST STATE 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema PROCESSLIST TID 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema PROCESSLIST TIME 6 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) select NEVER NULL -def information_schema PROCESSLIST TIME_MS 9 0.000 NO decimal NULL NULL 22 3 NULL NULL NULL decimal(22,3) select NEVER NULL -def information_schema PROCESSLIST USER 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS UPDATE_RULE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES CHARACTER_MAXIMUM_LENGTH 7 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema ROUTINES CHARACTER_OCTET_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema ROUTINES CHARACTER_SET_CLIENT 29 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema ROUTINES CHARACTER_SET_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES COLLATION_CONNECTION 30 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema ROUTINES COLLATION_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES CREATED 24 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema ROUTINES DATABASE_COLLATION 31 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema ROUTINES DATA_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES DATETIME_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema ROUTINES DEFINER 28 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL -def information_schema ROUTINES DTD_IDENTIFIER 14 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema ROUTINES EXTERNAL_LANGUAGE 18 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES EXTERNAL_NAME 17 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES IS_DETERMINISTIC 20 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema ROUTINES LAST_ALTERED 25 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema ROUTINES NUMERIC_PRECISION 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema ROUTINES NUMERIC_SCALE 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL -def information_schema ROUTINES PARAMETER_STYLE 19 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL -def information_schema ROUTINES ROUTINE_BODY 15 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL -def information_schema ROUTINES ROUTINE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema ROUTINES ROUTINE_COMMENT 27 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema ROUTINES ROUTINE_DEFINITION 16 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema ROUTINES ROUTINE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES ROUTINE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES ROUTINE_TYPE 5 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL -def information_schema ROUTINES SECURITY_TYPE 23 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) select NEVER NULL -def information_schema ROUTINES SPECIFIC_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES SQL_DATA_ACCESS 21 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema ROUTINES SQL_MODE 26 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) select NEVER NULL -def information_schema ROUTINES SQL_PATH 22 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SCHEMATA CATALOG_NAME 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema SCHEMATA DEFAULT_CHARACTER_SET_NAME 3 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema SCHEMATA DEFAULT_COLLATION_NAME 4 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema SCHEMATA SCHEMA_NAME 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SCHEMATA SQL_PATH 5 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema SCHEMA_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL -def information_schema SCHEMA_PRIVILEGES IS_GRANTABLE 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SESSION_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SESSION_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema SESSION_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema SPATIAL_REF_SYS AUTH_NAME 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema SPATIAL_REF_SYS AUTH_SRID 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(5) select NEVER NULL -def information_schema SPATIAL_REF_SYS SRID 1 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) select NEVER NULL -def information_schema SPATIAL_REF_SYS SRTEXT 4 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema SQL_FUNCTIONS FUNCTION 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema STATISTICS CARDINALITY 10 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema STATISTICS COLLATION 9 NULL YES varchar 1 3 NULL NULL NULL utf8 utf8_general_ci varchar(1) select NEVER NULL -def information_schema STATISTICS COLUMN_NAME 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema STATISTICS COMMENT 15 NULL YES varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL -def information_schema STATISTICS INDEX_COMMENT 16 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select NEVER NULL -def information_schema STATISTICS INDEX_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema STATISTICS INDEX_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema STATISTICS INDEX_TYPE 14 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) select NEVER NULL -def information_schema STATISTICS NON_UNIQUE 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(1) select NEVER NULL -def information_schema STATISTICS NULLABLE 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema STATISTICS PACKED 12 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL -def information_schema STATISTICS SEQ_IN_INDEX 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(2) select NEVER NULL -def information_schema STATISTICS SUB_PART 11 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(3) select NEVER NULL -def information_schema STATISTICS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema STATISTICS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema STATISTICS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SYSTEM_VARIABLES COMMAND_LINE_ARGUMENT 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SYSTEM_VARIABLES DEFAULT_VALUE 5 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema SYSTEM_VARIABLES ENUM_VALUE_LIST 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema SYSTEM_VARIABLES GLOBAL_VALUE 3 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema SYSTEM_VARIABLES GLOBAL_VALUE_ORIGIN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SYSTEM_VARIABLES NUMERIC_BLOCK_SIZE 11 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) select NEVER NULL -def information_schema SYSTEM_VARIABLES NUMERIC_MAX_VALUE 10 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) select NEVER NULL -def information_schema SYSTEM_VARIABLES NUMERIC_MIN_VALUE 9 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) select NEVER NULL -def information_schema SYSTEM_VARIABLES READ_ONLY 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema SYSTEM_VARIABLES SESSION_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_COMMENT 8 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_SCOPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SYSTEM_VARIABLES VARIABLE_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLES AUTO_INCREMENT 14 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES AVG_ROW_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES CHECKSUM 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES CHECK_TIME 17 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema TABLES CREATE_TIME 15 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema TABLES DATA_FREE 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES DATA_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES ENGINE 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLES INDEX_LENGTH 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES MAX_DATA_LENGTH 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES ROW_FORMAT 7 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL -def information_schema TABLES TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema TABLES TABLE_COLLATION 18 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema TABLES TABLE_COMMENT 21 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema TABLES TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLES TABLE_ROWS 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLES TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLES TABLE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLES UPDATE_TIME 16 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select NEVER NULL -def information_schema TABLES VERSION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLESPACES AUTOEXTEND_SIZE 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLESPACES ENGINE 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLESPACES EXTENT_SIZE 5 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLESPACES LOGFILE_GROUP_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLESPACES MAXIMUM_SIZE 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLESPACES NODEGROUP_ID 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema TABLESPACES TABLESPACE_COMMENT 9 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL -def information_schema TABLESPACES TABLESPACE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLESPACES TABLESPACE_TYPE 3 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_CONSTRAINTS TABLE_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_CONSTRAINTS TABLE_SCHEMA 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL -def information_schema TABLE_PRIVILEGES IS_GRANTABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema TABLE_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TABLE_STATISTICS ROWS_CHANGED 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES 5 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema TABLE_STATISTICS ROWS_READ 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema TABLE_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL -def information_schema TABLE_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL -def information_schema TRIGGERS ACTION_CONDITION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema TRIGGERS ACTION_ORDER 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) select NEVER NULL -def information_schema TRIGGERS ACTION_ORIENTATION 11 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) select NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_NEW_ROW 16 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_NEW_TABLE 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_OLD_ROW 15 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema TRIGGERS ACTION_REFERENCE_OLD_TABLE 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TRIGGERS ACTION_STATEMENT 10 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL -def information_schema TRIGGERS ACTION_TIMING 12 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) select NEVER NULL -def information_schema TRIGGERS CHARACTER_SET_CLIENT 20 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema TRIGGERS COLLATION_CONNECTION 21 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema TRIGGERS CREATED 17 NULL YES datetime NULL NULL NULL NULL 2 NULL NULL datetime(2) select NEVER NULL -def information_schema TRIGGERS DATABASE_COLLATION 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema TRIGGERS DEFINER 19 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL -def information_schema TRIGGERS EVENT_MANIPULATION 4 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) select NEVER NULL -def information_schema TRIGGERS EVENT_OBJECT_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema TRIGGERS EVENT_OBJECT_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TRIGGERS EVENT_OBJECT_TABLE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TRIGGERS SQL_MODE 18 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) select NEVER NULL -def information_schema TRIGGERS TRIGGER_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema TRIGGERS TRIGGER_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema TRIGGERS TRIGGER_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema USER_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) select NEVER NULL -def information_schema USER_PRIVILEGES IS_GRANTABLE 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema USER_PRIVILEGES PRIVILEGE_TYPE 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema USER_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema USER_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL -def information_schema USER_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select NEVER NULL -def information_schema USER_STATISTICS CONNECTED_TIME 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select NEVER NULL -def information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL -def information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS TOTAL_CONNECTIONS 2 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select NEVER NULL -def information_schema USER_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select NEVER NULL -def information_schema USER_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL -def information_schema USER_STATISTICS USER 1 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select NEVER NULL -def information_schema VIEWS ALGORITHM 11 '' NO varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) select NEVER NULL -def information_schema VIEWS CHARACTER_SET_CLIENT 9 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema VIEWS CHECK_OPTION 5 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) select NEVER NULL -def information_schema VIEWS COLLATION_CONNECTION 10 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL -def information_schema VIEWS DEFINER 7 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) select NEVER NULL -def information_schema VIEWS IS_UPDATABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NEVER NULL -def information_schema VIEWS SECURITY_TYPE 8 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) select NEVER NULL -def information_schema VIEWS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL -def information_schema VIEWS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema VIEWS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema VIEWS VIEW_DEFINITION 4 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema ALL_PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema ALL_PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema APPLICABLE_ROLES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL +def information_schema APPLICABLE_ROLES IS_DEFAULT 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema APPLICABLE_ROLES IS_GRANTABLE 3 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema APPLICABLE_ROLES ROLE_NAME 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL +def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema CHARACTER_SETS DESCRIPTION 3 '' NO varchar 60 180 NULL NULL NULL utf8 utf8_general_ci varchar(60) NEVER NULL +def information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) NEVER NULL +def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 5 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema CHECK_CONSTRAINTS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL +def information_schema CLIENT_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS CLIENT 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS CONNECTED_TIME 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL +def information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS 2 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema CLIENT_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema CLIENT_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema COLLATIONS CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema COLLATIONS COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(11) NEVER NULL +def information_schema COLLATIONS IS_COMPILED 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema COLLATIONS IS_DEFAULT 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema COLLATIONS SORTLEN 6 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) NEVER NULL +def information_schema COLLATION_CHARACTER_SET_APPLICABILITY CHARACTER_SET_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME 1 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema COLUMNS CHARACTER_MAXIMUM_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema COLUMNS CHARACTER_OCTET_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema COLUMNS CHARACTER_SET_NAME 14 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema COLUMNS COLLATION_NAME 15 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema COLUMNS COLUMN_COMMENT 20 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) NEVER NULL +def information_schema COLUMNS COLUMN_DEFAULT 6 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema COLUMNS COLUMN_KEY 17 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema COLUMNS COLUMN_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema COLUMNS COLUMN_TYPE 16 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema COLUMNS DATA_TYPE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema COLUMNS DATETIME_PRECISION 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema COLUMNS EXTRA 18 '' NO varchar 30 90 NULL NULL NULL utf8 utf8_general_ci varchar(30) NEVER NULL +def information_schema COLUMNS GENERATION_EXPRESSION 22 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema COLUMNS IS_GENERATED 21 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) NEVER NULL +def information_schema COLUMNS IS_NULLABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema COLUMNS NUMERIC_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema COLUMNS NUMERIC_SCALE 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema COLUMNS ORDINAL_POSITION 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema COLUMNS PRIVILEGES 19 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema COLUMNS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema COLUMNS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema COLUMNS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema COLUMN_PRIVILEGES COLUMN_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema COLUMN_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL +def information_schema COLUMN_PRIVILEGES IS_GRANTABLE 7 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema COLUMN_PRIVILEGES PRIVILEGE_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema COLUMN_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema COLUMN_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema COLUMN_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ENABLED_ROLES ROLE_NAME 1 NULL YES varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL +def information_schema ENGINES COMMENT 3 '' NO varchar 160 480 NULL NULL NULL utf8 utf8_general_ci varchar(160) NEVER NULL +def information_schema ENGINES ENGINE 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ENGINES SAVEPOINTS 6 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema ENGINES SUPPORT 2 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL +def information_schema ENGINES TRANSACTIONS 4 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema ENGINES XA 5 NULL YES varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema EVENTS CHARACTER_SET_CLIENT 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema EVENTS COLLATION_CONNECTION 23 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema EVENTS CREATED 17 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema EVENTS DATABASE_COLLATION 24 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema EVENTS DEFINER 4 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL +def information_schema EVENTS ENDS 14 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema EVENTS EVENT_BODY 6 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL +def information_schema EVENTS EVENT_CATALOG 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema EVENTS EVENT_COMMENT 20 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema EVENTS EVENT_DEFINITION 7 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema EVENTS EVENT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema EVENTS EVENT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema EVENTS EVENT_TYPE 8 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL +def information_schema EVENTS EXECUTE_AT 9 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema EVENTS INTERVAL_FIELD 11 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) NEVER NULL +def information_schema EVENTS INTERVAL_VALUE 10 NULL YES varchar 256 768 NULL NULL NULL utf8 utf8_general_ci varchar(256) NEVER NULL +def information_schema EVENTS LAST_ALTERED 18 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema EVENTS LAST_EXECUTED 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema EVENTS ON_COMPLETION 16 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL +def information_schema EVENTS ORIGINATOR 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) NEVER NULL +def information_schema EVENTS SQL_MODE 12 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) NEVER NULL +def information_schema EVENTS STARTS 13 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema EVENTS STATUS 15 '' NO varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) NEVER NULL +def information_schema EVENTS TIME_ZONE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES AUTOEXTEND_SIZE 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES AVG_ROW_LENGTH 28 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES CHECKSUM 36 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES CHECK_TIME 35 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema FILES CREATE_TIME 33 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema FILES CREATION_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema FILES DATA_FREE 32 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES DATA_LENGTH 29 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES DELETED_ROWS 12 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES ENGINE 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES EXTENT_SIZE 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES EXTRA 38 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_general_ci varchar(255) NEVER NULL +def information_schema FILES FILE_ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES FILE_NAME 2 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema FILES FILE_TYPE 3 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema FILES FREE_EXTENTS 14 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES FULLTEXT_KEYS 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES INDEX_LENGTH 31 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES INITIAL_SIZE 17 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES LAST_ACCESS_TIME 22 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema FILES LAST_UPDATE_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema FILES LOGFILE_GROUP_NAME 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES LOGFILE_GROUP_NUMBER 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES MAXIMUM_SIZE 18 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES MAX_DATA_LENGTH 30 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES RECOVER_TIME 23 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES ROW_FORMAT 26 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL +def information_schema FILES STATUS 37 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema FILES TABLESPACE_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES TABLE_CATALOG 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES TABLE_NAME 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES TABLE_ROWS 27 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema FILES TABLE_SCHEMA 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema FILES TOTAL_EXTENTS 15 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES TRANSACTION_COUNTER 24 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES UPDATE_COUNT 13 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema FILES UPDATE_TIME 34 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema FILES VERSION 25 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema GEOMETRY_COLUMNS COORD_DIMENSION 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL +def information_schema GEOMETRY_COLUMNS F_GEOMETRY_COLUMN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GEOMETRY_COLUMNS F_TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema GEOMETRY_COLUMNS F_TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GEOMETRY_COLUMNS F_TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GEOMETRY_COLUMNS GEOMETRY_TYPE 10 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) NEVER NULL +def information_schema GEOMETRY_COLUMNS G_GEOMETRY_COLUMN 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GEOMETRY_COLUMNS G_TABLE_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema GEOMETRY_COLUMNS G_TABLE_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GEOMETRY_COLUMNS G_TABLE_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GEOMETRY_COLUMNS MAX_PPR 12 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL +def information_schema GEOMETRY_COLUMNS SRID 13 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) NEVER NULL +def information_schema GEOMETRY_COLUMNS STORAGE_TYPE 9 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL +def information_schema GLOBAL_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema INDEX_STATISTICS INDEX_NAME 3 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL +def information_schema INDEX_STATISTICS ROWS_READ 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema INDEX_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL +def information_schema INDEX_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL +def information_schema KEYWORDS WORD 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES KEY_CACHE_NAME 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL +def information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES SEGMENTS 2 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned NEVER NULL +def information_schema KEY_CACHES SEGMENT_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL NULL int(3) unsigned NEVER NULL +def information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_COLUMN_USAGE ORDINAL_POSITION 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(10) NEVER NULL +def information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT 9 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(10) NEVER NULL +def information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARAMETERS COLLATION_NAME 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARAMETERS DATA_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARAMETERS DATETIME_PRECISION 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARAMETERS DTD_IDENTIFIER 15 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema PARAMETERS NUMERIC_PRECISION 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema PARAMETERS NUMERIC_SCALE 11 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema PARAMETERS ORDINAL_POSITION 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema PARAMETERS PARAMETER_MODE 5 NULL YES varchar 5 15 NULL NULL NULL utf8 utf8_general_ci varchar(5) NEVER NULL +def information_schema PARAMETERS PARAMETER_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARAMETERS ROUTINE_TYPE 16 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL +def information_schema PARAMETERS SPECIFIC_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema PARAMETERS SPECIFIC_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARAMETERS SPECIFIC_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARTITIONS AVG_ROW_LENGTH 14 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS CHECKSUM 22 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS CHECK_TIME 21 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema PARTITIONS CREATE_TIME 19 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema PARTITIONS DATA_FREE 18 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS DATA_LENGTH 15 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS INDEX_LENGTH 17 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS MAX_DATA_LENGTH 16 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS NODEGROUP 24 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL +def information_schema PARTITIONS PARTITION_COMMENT 23 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema PARTITIONS PARTITION_DESCRIPTION 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema PARTITIONS PARTITION_EXPRESSION 10 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema PARTITIONS PARTITION_METHOD 8 NULL YES varchar 18 54 NULL NULL NULL utf8 utf8_general_ci varchar(18) NEVER NULL +def information_schema PARTITIONS PARTITION_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARTITIONS PARTITION_ORDINAL_POSITION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS SUBPARTITION_EXPRESSION 11 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema PARTITIONS SUBPARTITION_METHOD 9 NULL YES varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL +def information_schema PARTITIONS SUBPARTITION_NAME 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARTITIONS SUBPARTITION_ORDINAL_POSITION 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS TABLESPACE_NAME 25 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARTITIONS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema PARTITIONS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARTITIONS TABLE_ROWS 13 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema PARTITIONS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PARTITIONS UPDATE_TIME 20 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema PLUGINS LOAD_OPTION 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PLUGINS PLUGIN_AUTH_VERSION 13 NULL YES varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema PLUGINS PLUGIN_LICENSE 10 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema PLUGINS PLUGIN_MATURITY 12 '' NO varchar 12 36 NULL NULL NULL utf8 utf8_general_ci varchar(12) NEVER NULL +def information_schema PLUGINS PLUGIN_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PLUGINS PLUGIN_STATUS 3 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL +def information_schema PLUGINS PLUGIN_TYPE 4 '' NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) NEVER NULL +def information_schema PLUGINS PLUGIN_TYPE_VERSION 5 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema PLUGINS PLUGIN_VERSION 2 '' NO varchar 20 60 NULL NULL NULL utf8 utf8_general_ci varchar(20) NEVER NULL +def information_schema PROCESSLIST COMMAND 5 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL +def information_schema PROCESSLIST DB 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PROCESSLIST EXAMINED_ROWS 14 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) NEVER NULL +def information_schema PROCESSLIST HOST 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PROCESSLIST ID 1 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema PROCESSLIST INFO 8 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema PROCESSLIST INFO_BINARY 16 NULL YES blob 65535 65535 NULL NULL NULL NULL NULL blob NEVER NULL +def information_schema PROCESSLIST MAX_STAGE 11 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL +def information_schema PROCESSLIST MEMORY_USED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(7) NEVER NULL +def information_schema PROCESSLIST PROGRESS 12 0.000 NO decimal NULL NULL 7 3 NULL NULL NULL decimal(7,3) NEVER NULL +def information_schema PROCESSLIST QUERY_ID 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema PROCESSLIST STAGE 10 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL +def information_schema PROCESSLIST STATE 7 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema PROCESSLIST TID 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema PROCESSLIST TIME 6 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) NEVER NULL +def information_schema PROCESSLIST TIME_MS 9 0.000 NO decimal NULL NULL 22 3 NULL NULL NULL decimal(22,3) NEVER NULL +def information_schema PROCESSLIST USER 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS UPDATE_RULE 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES CHARACTER_MAXIMUM_LENGTH 7 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema ROUTINES CHARACTER_OCTET_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema ROUTINES CHARACTER_SET_CLIENT 29 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema ROUTINES CHARACTER_SET_NAME 12 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES COLLATION_CONNECTION 30 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema ROUTINES COLLATION_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES CREATED 24 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema ROUTINES DATABASE_COLLATION 31 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema ROUTINES DATA_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES DATETIME_PRECISION 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema ROUTINES DEFINER 28 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL +def information_schema ROUTINES DTD_IDENTIFIER 14 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema ROUTINES EXTERNAL_LANGUAGE 18 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES EXTERNAL_NAME 17 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES IS_DETERMINISTIC 20 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema ROUTINES LAST_ALTERED 25 '0000-00-00 00:00:00' NO datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema ROUTINES NUMERIC_PRECISION 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema ROUTINES NUMERIC_SCALE 10 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL +def information_schema ROUTINES PARAMETER_STYLE 19 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL +def information_schema ROUTINES ROUTINE_BODY 15 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL +def information_schema ROUTINES ROUTINE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema ROUTINES ROUTINE_COMMENT 27 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema ROUTINES ROUTINE_DEFINITION 16 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema ROUTINES ROUTINE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES ROUTINE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES ROUTINE_TYPE 5 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL +def information_schema ROUTINES SECURITY_TYPE 23 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) NEVER NULL +def information_schema ROUTINES SPECIFIC_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES SQL_DATA_ACCESS 21 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema ROUTINES SQL_MODE 26 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) NEVER NULL +def information_schema ROUTINES SQL_PATH 22 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SCHEMATA CATALOG_NAME 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema SCHEMATA DEFAULT_CHARACTER_SET_NAME 3 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema SCHEMATA DEFAULT_COLLATION_NAME 4 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema SCHEMATA SCHEMA_NAME 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SCHEMATA SQL_PATH 5 NULL YES varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema SCHEMA_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL +def information_schema SCHEMA_PRIVILEGES IS_GRANTABLE 5 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SESSION_STATUS VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SESSION_STATUS VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SESSION_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SPATIAL_REF_SYS AUTH_NAME 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema SPATIAL_REF_SYS AUTH_SRID 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(5) NEVER NULL +def information_schema SPATIAL_REF_SYS SRID 1 0 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) NEVER NULL +def information_schema SPATIAL_REF_SYS SRTEXT 4 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SQL_FUNCTIONS FUNCTION 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema STATISTICS CARDINALITY 10 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema STATISTICS COLLATION 9 NULL YES varchar 1 3 NULL NULL NULL utf8 utf8_general_ci varchar(1) NEVER NULL +def information_schema STATISTICS COLUMN_NAME 8 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema STATISTICS COMMENT 15 NULL YES varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL +def information_schema STATISTICS INDEX_COMMENT 16 '' NO varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) NEVER NULL +def information_schema STATISTICS INDEX_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema STATISTICS INDEX_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema STATISTICS INDEX_TYPE 14 '' NO varchar 16 48 NULL NULL NULL utf8 utf8_general_ci varchar(16) NEVER NULL +def information_schema STATISTICS NON_UNIQUE 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(1) NEVER NULL +def information_schema STATISTICS NULLABLE 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema STATISTICS PACKED 12 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL +def information_schema STATISTICS SEQ_IN_INDEX 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(2) NEVER NULL +def information_schema STATISTICS SUB_PART 11 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(3) NEVER NULL +def information_schema STATISTICS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema STATISTICS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema STATISTICS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SYSTEM_VARIABLES COMMAND_LINE_ARGUMENT 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SYSTEM_VARIABLES DEFAULT_VALUE 5 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SYSTEM_VARIABLES ENUM_VALUE_LIST 12 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema SYSTEM_VARIABLES GLOBAL_VALUE 3 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SYSTEM_VARIABLES GLOBAL_VALUE_ORIGIN 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SYSTEM_VARIABLES NUMERIC_BLOCK_SIZE 11 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) NEVER NULL +def information_schema SYSTEM_VARIABLES NUMERIC_MAX_VALUE 10 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) NEVER NULL +def information_schema SYSTEM_VARIABLES NUMERIC_MIN_VALUE 9 NULL YES varchar 21 63 NULL NULL NULL utf8 utf8_general_ci varchar(21) NEVER NULL +def information_schema SYSTEM_VARIABLES READ_ONLY 13 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema SYSTEM_VARIABLES SESSION_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_COMMENT 8 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_SCOPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema SYSTEM_VARIABLES VARIABLE_TYPE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLES AUTO_INCREMENT 14 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES AVG_ROW_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES CHECKSUM 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES CHECK_TIME 17 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema TABLES CREATE_TIME 15 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema TABLES DATA_FREE 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES DATA_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES ENGINE 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLES INDEX_LENGTH 12 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES MAX_DATA_LENGTH 11 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES ROW_FORMAT 7 NULL YES varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL +def information_schema TABLES TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema TABLES TABLE_COLLATION 18 NULL YES varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema TABLES TABLE_COMMENT 21 '' NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema TABLES TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLES TABLE_ROWS 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLES TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLES TABLE_TYPE 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLES UPDATE_TIME 16 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL +def information_schema TABLES VERSION 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLESPACES AUTOEXTEND_SIZE 6 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLESPACES ENGINE 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLESPACES EXTENT_SIZE 5 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLESPACES LOGFILE_GROUP_NAME 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLESPACES MAXIMUM_SIZE 7 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLESPACES NODEGROUP_ID 8 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema TABLESPACES TABLESPACE_COMMENT 9 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema TABLESPACES TABLESPACE_NAME 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLESPACES TABLESPACE_TYPE 3 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_CONSTRAINTS TABLE_NAME 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_CONSTRAINTS TABLE_SCHEMA 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL +def information_schema TABLE_PRIVILEGES IS_GRANTABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema TABLE_PRIVILEGES TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TABLE_STATISTICS ROWS_CHANGED 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES 5 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema TABLE_STATISTICS ROWS_READ 3 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema TABLE_STATISTICS TABLE_NAME 2 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL +def information_schema TABLE_STATISTICS TABLE_SCHEMA 1 '' NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL +def information_schema TRIGGERS ACTION_CONDITION 9 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema TRIGGERS ACTION_ORDER 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(4) NEVER NULL +def information_schema TRIGGERS ACTION_ORIENTATION 11 '' NO varchar 9 27 NULL NULL NULL utf8 utf8_general_ci varchar(9) NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_NEW_ROW 16 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_NEW_TABLE 14 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_OLD_ROW 15 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema TRIGGERS ACTION_REFERENCE_OLD_TABLE 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TRIGGERS ACTION_STATEMENT 10 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema TRIGGERS ACTION_TIMING 12 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) NEVER NULL +def information_schema TRIGGERS CHARACTER_SET_CLIENT 20 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema TRIGGERS COLLATION_CONNECTION 21 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema TRIGGERS CREATED 17 NULL YES datetime NULL NULL NULL NULL 2 NULL NULL datetime(2) NEVER NULL +def information_schema TRIGGERS DATABASE_COLLATION 22 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema TRIGGERS DEFINER 19 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL +def information_schema TRIGGERS EVENT_MANIPULATION 4 '' NO varchar 6 18 NULL NULL NULL utf8 utf8_general_ci varchar(6) NEVER NULL +def information_schema TRIGGERS EVENT_OBJECT_CATALOG 5 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema TRIGGERS EVENT_OBJECT_SCHEMA 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TRIGGERS EVENT_OBJECT_TABLE 7 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TRIGGERS SQL_MODE 18 '' NO varchar 8192 24576 NULL NULL NULL utf8 utf8_general_ci varchar(8192) NEVER NULL +def information_schema TRIGGERS TRIGGER_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema TRIGGERS TRIGGER_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema TRIGGERS TRIGGER_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema USER_PRIVILEGES GRANTEE 1 '' NO varchar 190 570 NULL NULL NULL utf8 utf8_general_ci varchar(190) NEVER NULL +def information_schema USER_PRIVILEGES IS_GRANTABLE 4 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema USER_PRIVILEGES PRIVILEGE_TYPE 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema USER_PRIVILEGES TABLE_CATALOG 2 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema USER_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL +def information_schema USER_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL +def information_schema USER_STATISTICS CONNECTED_TIME 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL +def information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL +def information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 25 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS TOTAL_CONNECTIONS 2 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL +def information_schema USER_STATISTICS TOTAL_SSL_CONNECTIONS 24 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL +def information_schema USER_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def information_schema USER_STATISTICS USER 1 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) NEVER NULL +def information_schema VIEWS ALGORITHM 11 '' NO varchar 10 30 NULL NULL NULL utf8 utf8_general_ci varchar(10) NEVER NULL +def information_schema VIEWS CHARACTER_SET_CLIENT 9 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema VIEWS CHECK_OPTION 5 '' NO varchar 8 24 NULL NULL NULL utf8 utf8_general_ci varchar(8) NEVER NULL +def information_schema VIEWS COLLATION_CONNECTION 10 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL +def information_schema VIEWS DEFINER 7 '' NO varchar 189 567 NULL NULL NULL utf8 utf8_general_ci varchar(189) NEVER NULL +def information_schema VIEWS IS_UPDATABLE 6 '' NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) NEVER NULL +def information_schema VIEWS SECURITY_TYPE 8 '' NO varchar 7 21 NULL NULL NULL utf8 utf8_general_ci varchar(7) NEVER NULL +def information_schema VIEWS TABLE_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema VIEWS TABLE_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema VIEWS TABLE_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema VIEWS VIEW_DEFINITION 4 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL ########################################################################## # Show the quotient of CHARACTER_OCTET_LENGTH and CHARACTER_MAXIMUM_LENGTH ########################################################################## diff --git a/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test b/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test index 9db247fd6fd..bb9cc2a6ffb 100644 --- a/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test +++ b/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test @@ -14,7 +14,7 @@ # --source include/have_innodb.inc ---source include/is_embedded.inc +--source include/is_embedded_no_privileges.inc let $my_where = WHERE table_schema = 'information_schema' AND table_name <> 'profiling' AND table_name not like 'innodb_%'; diff --git a/mysql-test/suite/funcs_1/t/is_columns_myisam_embedded.test b/mysql-test/suite/funcs_1/t/is_columns_myisam_embedded.test index 3d0cca24474..bb2200604f3 100644 --- a/mysql-test/suite/funcs_1/t/is_columns_myisam_embedded.test +++ b/mysql-test/suite/funcs_1/t/is_columns_myisam_embedded.test @@ -10,10 +10,8 @@ # 2008-06-06 mleich Create this this variant for the embedded server. # -if (`SELECT VERSION() NOT LIKE '%embedded%'`) -{ - --skip Test requires: embedded server -} +--source include/is_embedded_no_privileges.inc + let $engine_type= MyISAM; SET @@session.sql_mode = 'NO_ENGINE_SUBSTITUTION'; --source suite/funcs_1/datadict/datadict_load.inc diff --git a/mysql-test/suite/funcs_1/t/is_columns_mysql_embedded.test b/mysql-test/suite/funcs_1/t/is_columns_mysql_embedded.test index d1ed45425ec..9ef1b6d869a 100644 --- a/mysql-test/suite/funcs_1/t/is_columns_mysql_embedded.test +++ b/mysql-test/suite/funcs_1/t/is_columns_mysql_embedded.test @@ -10,10 +10,7 @@ # 2008-06-06 mleich Create this variant for the embedded server # -if (`SELECT VERSION() NOT LIKE '%embedded%'`) -{ - --skip Test requires: embedded server -} +--source include/is_embedded_no_privileges.inc let $my_where = WHERE table_schema = 'mysql'; --source suite/funcs_1/datadict/columns.inc diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index 01c3ea5cd75..5f378a69ca4 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1,5 +1,5 @@ ---- sysvars_server_embedded.result -+++ sysvars_server_embedded,32bit.reject +--- ../../mysql-test/suite/sys_vars/r/sysvars_server_embedded.result 2022-01-27 20:42:19.039084441 +0200 ++++ ../../mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.result~ 2022-01-28 16:12:40.038627481 +0200 @@ -14,7 +14,7 @@ order by variable_name; VARIABLE_NAME ARIA_BLOCK_SIZE @@ -227,7 +227,7 @@ VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -674,7 +674,7 @@ +@@ -664,7 +664,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DEFAULT_WEEK_FORMAT VARIABLE_SCOPE SESSION @@ -236,7 +236,7 @@ VARIABLE_COMMENT The default week format used by WEEK() functions NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 7 -@@ -684,7 +684,7 @@ +@@ -674,7 +674,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_LIMIT VARIABLE_SCOPE GLOBAL @@ -245,7 +245,7 @@ VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -694,7 +694,7 @@ +@@ -684,7 +684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -254,7 +254,7 @@ VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -704,7 +704,7 @@ +@@ -694,7 +694,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_QUEUE_SIZE VARIABLE_SCOPE GLOBAL @@ -263,7 +263,7 @@ VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -724,7 +724,7 @@ +@@ -714,7 +714,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME DIV_PRECISION_INCREMENT VARIABLE_SCOPE SESSION @@ -272,7 +272,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -814,7 +814,7 @@ +@@ -794,7 +794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME EXPIRE_LOGS_DAYS VARIABLE_SCOPE GLOBAL @@ -281,7 +281,7 @@ VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 99 -@@ -844,7 +844,7 @@ +@@ -824,7 +824,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME EXTRA_MAX_CONNECTIONS VARIABLE_SCOPE GLOBAL @@ -290,7 +290,7 @@ VARIABLE_COMMENT The number of connections on extra-port NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -874,7 +874,7 @@ +@@ -854,7 +854,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME FLUSH_TIME VARIABLE_SCOPE GLOBAL @@ -299,7 +299,7 @@ VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -904,7 +904,7 @@ +@@ -884,7 +884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MAX_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -308,7 +308,7 @@ VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -914,7 +914,7 @@ +@@ -894,7 +894,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MIN_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -317,7 +317,7 @@ VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 84 -@@ -924,7 +924,7 @@ +@@ -904,7 +904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_QUERY_EXPANSION_LIMIT VARIABLE_SCOPE GLOBAL @@ -326,7 +326,7 @@ VARIABLE_COMMENT Number of best matches to use for query expansion NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -1154,7 +1154,7 @@ +@@ -1074,7 +1074,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HISTOGRAM_SIZE VARIABLE_SCOPE SESSION @@ -335,7 +335,7 @@ VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1184,7 +1184,7 @@ +@@ -1104,7 +1104,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HOST_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -344,7 +344,7 @@ VARIABLE_COMMENT How many host names should be cached to avoid resolving. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65536 -@@ -1264,7 +1264,7 @@ +@@ -1184,7 +1184,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME INTERACTIVE_TIMEOUT VARIABLE_SCOPE SESSION @@ -353,7 +353,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1287,7 +1287,7 @@ +@@ -1207,7 +1207,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer that is used for joins NUMERIC_MIN_VALUE 128 @@ -362,7 +362,7 @@ NUMERIC_BLOCK_SIZE 128 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1304,7 +1304,7 @@ +@@ -1224,7 +1224,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME JOIN_CACHE_LEVEL VARIABLE_SCOPE SESSION @@ -371,7 +371,7 @@ VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8 -@@ -1327,7 +1327,7 @@ +@@ -1247,7 +1247,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford NUMERIC_MIN_VALUE 0 @@ -380,7 +380,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1494,7 +1494,7 @@ +@@ -1404,7 +1404,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOCK_WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -389,7 +389,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1624,7 +1624,7 @@ +@@ -1504,7 +1504,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_RATE_LIMIT VARIABLE_SCOPE SESSION @@ -398,7 +398,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1654,7 +1654,7 @@ +@@ -1534,7 +1534,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION @@ -407,7 +407,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1714,7 +1714,7 @@ +@@ -1584,7 +1584,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION @@ -416,7 +416,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1727,14 +1727,14 @@ +@@ -1597,14 +1597,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the transactional cache NUMERIC_MIN_VALUE 4096 @@ -433,7 +433,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -1747,14 +1747,14 @@ +@@ -1617,14 +1617,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the statement cache NUMERIC_MIN_VALUE 4096 @@ -450,7 +450,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -1764,7 +1764,7 @@ +@@ -1634,7 +1634,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_CONNECT_ERRORS VARIABLE_SCOPE GLOBAL @@ -459,7 +459,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1774,7 +1774,7 @@ +@@ -1644,7 +1644,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_DELAYED_THREADS VARIABLE_SCOPE SESSION @@ -468,7 +468,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1794,7 +1794,7 @@ +@@ -1664,7 +1664,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_ERROR_COUNT VARIABLE_SCOPE SESSION @@ -477,7 +477,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -1807,14 +1807,14 @@ +@@ -1677,14 +1677,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -494,7 +494,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1834,7 +1834,7 @@ +@@ -1704,7 +1704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LENGTH_FOR_SORT_DATA VARIABLE_SCOPE SESSION @@ -503,7 +503,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -1844,7 +1844,7 @@ +@@ -1714,7 +1714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LONG_DATA_SIZE VARIABLE_SCOPE GLOBAL @@ -512,7 +512,7 @@ VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -1864,7 +1864,7 @@ +@@ -1734,7 +1734,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_RECURSIVE_ITERATIONS VARIABLE_SCOPE SESSION @@ -521,8 +521,8 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1884,7 +1884,7 @@ - COMMAND_LINE_ARGUMENT REQUIRED +@@ -1744,7 +1744,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_SEEKS_FOR_KEY VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED @@ -530,7 +530,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1904,7 +1904,7 @@ +@@ -1764,7 +1764,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION @@ -539,7 +539,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 64 NUMERIC_MAX_VALUE 8388608 -@@ -1914,7 +1914,7 @@ +@@ -1774,7 +1774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SP_RECURSION_DEPTH VARIABLE_SCOPE SESSION @@ -548,7 +548,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1934,7 +1934,7 @@ +@@ -1794,7 +1794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_TMP_TABLES VARIABLE_SCOPE SESSION @@ -557,7 +557,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1954,7 +1954,7 @@ +@@ -1814,7 +1814,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_WRITE_LOCK_COUNT VARIABLE_SCOPE GLOBAL @@ -566,7 +566,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1964,7 +1964,7 @@ +@@ -1824,7 +1824,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -575,7 +575,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -1974,7 +1974,7 @@ +@@ -1834,7 +1834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_HASH_INSTANCES VARIABLE_SCOPE GLOBAL @@ -584,7 +584,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -1984,7 +1984,7 @@ +@@ -1844,7 +1844,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -593,7 +593,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1994,7 +1994,7 @@ +@@ -1854,7 +1854,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MRR_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -602,7 +602,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2004,17 +2004,17 @@ +@@ -1864,17 +1864,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MULTI_RANGE_COUNT VARIABLE_SCOPE SESSION @@ -623,7 +623,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2024,7 +2024,7 @@ +@@ -1884,7 +1884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_DATA_POINTER_SIZE VARIABLE_SCOPE GLOBAL @@ -632,7 +632,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2047,7 +2047,7 @@ +@@ -1907,7 +1907,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Restricts the total memory used for memory mapping of MySQL tables NUMERIC_MIN_VALUE 7 @@ -641,7 +641,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2064,10 +2064,10 @@ +@@ -1924,10 +1924,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MYISAM_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -654,7 +654,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2077,7 +2077,7 @@ +@@ -1937,7 +1937,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -663,7 +663,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2114,7 +2114,7 @@ +@@ -1974,7 +1974,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME NET_BUFFER_LENGTH VARIABLE_SCOPE SESSION @@ -672,7 +672,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2124,7 +2124,7 @@ +@@ -1984,7 +1984,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_READ_TIMEOUT VARIABLE_SCOPE SESSION @@ -681,7 +681,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2134,7 +2134,7 @@ +@@ -1994,7 +1994,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_RETRY_COUNT VARIABLE_SCOPE SESSION @@ -690,7 +690,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2144,7 +2144,7 @@ +@@ -2004,7 +2004,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_WRITE_TIMEOUT VARIABLE_SCOPE SESSION @@ -699,7 +699,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2194,7 +2194,7 @@ +@@ -2054,7 +2054,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -708,7 +708,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2204,7 +2204,7 @@ +@@ -2064,7 +2064,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -717,7 +717,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2214,7 +2214,7 @@ +@@ -2074,7 +2074,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -726,7 +726,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2224,7 +2224,7 @@ +@@ -2084,7 +2084,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -735,7 +735,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2244,7 +2244,7 @@ +@@ -2104,7 +2104,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY VARIABLE_SCOPE SESSION @@ -744,7 +744,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2264,7 +2264,7 @@ +@@ -2124,7 +2124,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -753,7 +753,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2274,7 +2274,7 @@ +@@ -2134,7 +2134,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -762,7 +762,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2284,7 +2284,7 @@ +@@ -2144,7 +2144,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -771,7 +771,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2294,7 +2294,7 @@ +@@ -2154,7 +2154,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -780,7 +780,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2304,7 +2304,7 @@ +@@ -2164,7 +2164,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -789,7 +789,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2314,7 +2314,7 @@ +@@ -2174,7 +2174,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -798,7 +798,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2324,7 +2324,7 @@ +@@ -2184,7 +2184,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -807,7 +807,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2334,7 +2334,7 @@ +@@ -2194,7 +2194,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -816,7 +816,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2344,7 +2344,7 @@ +@@ -2204,7 +2204,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -825,7 +825,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2354,7 +2354,7 @@ +@@ -2214,7 +2214,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -834,7 +834,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2364,7 +2364,7 @@ +@@ -2224,7 +2224,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -843,7 +843,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2374,7 +2374,7 @@ +@@ -2234,7 +2234,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -852,7 +852,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2384,7 +2384,7 @@ +@@ -2244,7 +2244,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -861,7 +861,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2394,7 +2394,7 @@ +@@ -2254,7 +2254,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -870,7 +870,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2404,7 +2404,7 @@ +@@ -2264,7 +2264,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -879,7 +879,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2414,7 +2414,7 @@ +@@ -2274,7 +2274,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -888,7 +888,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2424,7 +2424,7 @@ +@@ -2284,7 +2284,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -897,7 +897,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2434,7 +2434,7 @@ +@@ -2294,7 +2294,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -906,7 +906,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2444,7 +2444,7 @@ +@@ -2304,7 +2304,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -915,7 +915,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2454,7 +2454,7 @@ +@@ -2314,7 +2314,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -924,7 +924,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2464,7 +2464,7 @@ +@@ -2324,7 +2324,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -933,7 +933,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2474,7 +2474,7 @@ +@@ -2334,7 +2334,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -942,7 +942,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2484,7 +2484,7 @@ +@@ -2344,7 +2344,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -951,7 +951,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2494,7 +2494,7 @@ +@@ -2354,7 +2354,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -960,7 +960,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2504,7 +2504,7 @@ +@@ -2364,7 +2364,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -969,7 +969,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2514,7 +2514,7 @@ +@@ -2374,7 +2374,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -978,7 +978,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2524,7 +2524,7 @@ +@@ -2384,7 +2384,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -987,7 +987,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2534,7 +2534,7 @@ +@@ -2394,7 +2394,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -996,7 +996,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2544,7 +2544,7 @@ +@@ -2404,7 +2404,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1005,7 +1005,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2554,7 +2554,7 @@ +@@ -2414,7 +2414,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1014,7 +1014,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2564,7 +2564,7 @@ +@@ -2424,7 +2424,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1023,7 +1023,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2614,7 +2614,7 @@ +@@ -2474,7 +2474,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1032,7 +1032,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2634,7 +2634,7 @@ +@@ -2494,7 +2494,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1041,7 +1041,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -2644,7 +2644,7 @@ +@@ -2504,7 +2504,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1050,7 +1050,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2694,7 +2694,7 @@ +@@ -2554,7 +2554,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1059,7 +1059,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2704,7 +2704,7 @@ +@@ -2564,7 +2564,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1068,7 +1068,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2714,7 +2714,7 @@ +@@ -2574,7 +2574,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1077,7 +1077,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2727,7 +2727,7 @@ +@@ -2587,7 +2587,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1086,7 +1086,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2764,7 +2764,7 @@ +@@ -2624,7 +2624,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1095,7 +1095,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2777,7 +2777,7 @@ +@@ -2637,7 +2637,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1104,7 +1104,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2787,14 +2787,14 @@ +@@ -2647,14 +2647,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1121,15 +1121,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -2807,14 +2807,14 @@ - VARIABLE_TYPE BIGINT UNSIGNED - VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) - NUMERIC_MIN_VALUE 0 --NUMERIC_MAX_VALUE 18446744073709551615 -+NUMERIC_MAX_VALUE 4294967295 - NUMERIC_BLOCK_SIZE 1 - ENUM_VALUE_LIST NULL - READ_ONLY NO +@@ -2664,7 +2664,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME READ_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1138,7 +1130,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2834,7 +2834,7 @@ +@@ -2684,7 +2684,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1147,7 +1139,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3034,10 +3034,10 @@ +@@ -2694,10 +2694,10 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1160,7 +1152,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3064,7 +3064,7 @@ +@@ -2724,7 +2724,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1169,17 +1161,8 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3194,7 +3194,7 @@ - COMMAND_LINE_ARGUMENT REQUIRED - VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 16383 -@@ -3224,7 +3224,7 @@ - COMMAND_LINE_ARGUMENT REQUIRED +@@ -2794,7 +2794,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -1187,43 +1170,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3244,7 +3244,7 @@ - COMMAND_LINE_ARGUMENT REQUIRED - VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 2147483647 -@@ -3264,7 +3264,7 @@ - COMMAND_LINE_ARGUMENT NULL - VARIABLE_NAME SLAVE_PARALLEL_THREADS - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 16383 -@@ -3274,7 +3274,7 @@ - COMMAND_LINE_ARGUMENT REQUIRED - VARIABLE_NAME SLAVE_PARALLEL_WORKERS - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Alias for slave_parallel_threads - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 16383 -@@ -3314,7 +3314,7 @@ - COMMAND_LINE_ARGUMENT OPTIONAL - VARIABLE_NAME SLAVE_TRANSACTION_RETRIES - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout, before giving up and stopping - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 4294967295 -@@ -3334,7 +3334,7 @@ +@@ -2804,7 +2804,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1232,7 +1179,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3377,7 +3377,7 @@ +@@ -2847,7 +2847,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1241,7 +1188,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3594,7 +3594,7 @@ +@@ -3054,7 +3054,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1250,7 +1197,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -3674,7 +3674,7 @@ +@@ -3114,7 +3114,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1259,7 +1206,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -3684,7 +3684,7 @@ +@@ -3124,7 +3124,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1268,7 +1215,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -3704,7 +3704,7 @@ +@@ -3144,7 +3144,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1277,7 +1224,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -3714,7 +3714,7 @@ +@@ -3154,7 +3154,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CONCURRENCY VARIABLE_SCOPE GLOBAL @@ -1286,7 +1233,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -3867,7 +3867,7 @@ +@@ -3237,7 +3237,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1295,7 +1242,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3877,7 +3877,7 @@ +@@ -3247,7 +3247,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 1024 @@ -1304,7 +1251,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3887,14 +3887,14 @@ +@@ -3257,14 +3257,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1321,7 +1268,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3904,7 +3904,7 @@ +@@ -3274,7 +3274,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1330,7 +1277,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4034,7 +4034,7 @@ +@@ -3404,7 +3404,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1339,7 +1286,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4061,7 +4061,7 @@ +@@ -3431,7 +3431,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 42c236bf54a..5ccabeecf2d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -632,16 +632,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME DEFAULT_MASTER_CONNECTION -VARIABLE_SCOPE SESSION ONLY -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Master connection to use for all slave variables and slave commands -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DEFAULT_REGEX_FLAGS VARIABLE_SCOPE SESSION VARIABLE_TYPE SET @@ -792,16 +782,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME EVENT_SCHEDULER -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE ENUM -VARIABLE_COMMENT Enable the event scheduler. Possible values are ON, OFF, and DISABLED (keep the event scheduler completely deactivated, it cannot be activated run-time) -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON,DISABLED,ORIGINAL -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME EXPENSIVE_SUBQUERY_LIMIT VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -972,36 +952,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME GTID_BINLOG_POS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Last GTID logged to the binary log, per replicationdomain -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME GTID_BINLOG_STATE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The internal GTID state of the binlog, used to keep track of all GTIDs ever logged to the binlog. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME GTID_CURRENT_POS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Current GTID position of the server. Per replication domain, this is either the last GTID replicated by a slave thread, or the GTID logged to the binary log, whichever is most recent. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME GTID_DOMAIN_ID VARIABLE_SCOPE SESSION VARIABLE_TYPE INT UNSIGNED @@ -1012,16 +962,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME GTID_IGNORE_DUPLICATES -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT When set, different master connections in multi-source replication are allowed to receive and process event groups with the same GTID (when using GTID mode). Only one will be applied, any others will be ignored. Within a given replication domain, just the sequence number will be used to decide whether a given GTID has been already applied; this means it is the responsibility of the user to ensure that GTID sequence numbers are strictly increasing. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME GTID_SEQ_NO VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED @@ -1032,26 +972,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME GTID_SLAVE_POS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The list of global transaction IDs that were last replicated on the server, one for each replication domain. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME GTID_STRICT_MODE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Enforce strict seq_no ordering of events in the binary log. Slave stops with an error if it encounters an event that would cause it to generate an out-of-order binlog if executed. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME HAVE_COMPRESS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -1412,16 +1332,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME LAST_GTID -VARIABLE_SCOPE SESSION ONLY -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The GTID of the last commit (if binlogging was enabled), or the empty string if none. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LAST_INSERT_ID VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED @@ -1512,16 +1422,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME LOG_BIN_BASENAME -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The full path of the binary log file names, excluding the extension. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOG_BIN_COMPRESS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -1542,16 +1442,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME LOG_BIN_INDEX -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT File that holds the names for last binary log files. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOG_BIN_TRUST_FUNCTION_CREATORS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -1592,16 +1482,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME LOG_SLAVE_UPDATES -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY YES -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LOG_SLOW_ADMIN_STATEMENTS VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -1702,16 +1582,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME MASTER_VERIFY_CHECKSUM -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Force checksum verification of logged events in the binary log before sending them to slaves or printing them in the output of SHOW BINLOG EVENTS -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -1872,16 +1742,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME MAX_RELAY_LOG_SIZE -VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT relay log will be rotated automatically when the size exceeds this value. If 0 at startup, it's set to max_binlog_size -NUMERIC_MIN_VALUE 4096 -NUMERIC_MAX_VALUE 1073741824 -NUMERIC_BLOCK_SIZE 4096 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SEEKS_FOR_KEY VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -2802,16 +2662,6 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME READ_BINLOG_SPEED_LIMIT -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 18446744073709551615 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME READ_BUFFER_SIZE VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -2842,196 +2692,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME RELAY_LOG -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The location and name to use for relay logs. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME RELAY_LOG_BASENAME -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The full path of the relay log file names, excluding the extension. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME RELAY_LOG_INDEX -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The location and name to use for the file that keeps a list of the last relay logs. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME RELAY_LOG_INFO_FILE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The location and name of the file that remembers where the SQL replication thread is in the relay logs. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME RELAY_LOG_PURGE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT if disabled - do not purge relay logs. if enabled - purge them as soon as they are no more needed. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME RELAY_LOG_RECOVERY -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Enables automatic relay log recovery right after the database startup, which means that the IO Thread starts re-fetching from the master right after the last transaction processed. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME RELAY_LOG_SPACE_LIMIT -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Maximum space to use for all relay logs -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 18446744073709551615 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME REPLICATE_ANNOTATE_ROW_EVENTS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Tells the slave to write annotate rows events received from the master to its own binary log. Ignored if log_slave_updates is not set -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY YES -COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME REPLICATE_DO_DB -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Tell the slave to restrict replication to updates of tables whose names appear in the comma-separated list. For statement-based replication, only the default database (that is, the one selected by USE) is considered, not any explicitly mentioned tables in the query. For row-based replication, the actual names of table(s) being updated are checked. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME REPLICATE_DO_TABLE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Tells the slave to restrict replication to tables in the comma-separated list. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME REPLICATE_EVENTS_MARKED_FOR_SKIP -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE ENUM -VARIABLE_COMMENT Whether the slave should replicate events that were created with @@skip_replication=1 on the master. Default REPLICATE (no events are skipped). Other values are FILTER_ON_SLAVE (events will be sent by the master but ignored by the slave) and FILTER_ON_MASTER (events marked with @@skip_replication=1 will be filtered on the master and never be sent to the slave). -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST REPLICATE,FILTER_ON_SLAVE,FILTER_ON_MASTER -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME REPLICATE_IGNORE_DB -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Tell the slave to restrict replication to updates of tables whose names do not appear in the comma-separated list. For statement-based replication, only the default database (that is, the one selected by USE) is considered, not any explicitly mentioned tables in the query. For row-based replication, the actual names of table(s) being updated are checked. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME REPLICATE_IGNORE_TABLE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Tells the slave thread not to replicate any statement that updates the specified table, even if any other tables might be updated by the same statement. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME REPLICATE_WILD_DO_TABLE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Tells the slave thread to restrict replication to statements where any of the updated tables match the specified database and table name patterns. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME REPLICATE_WILD_IGNORE_TABLE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Tells the slave thread to not replicate to the tables that match the given wildcard pattern. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME REPORT_HOST -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Hostname or IP of the slave to be reported to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME REPORT_PASSWORD -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The account password of the slave to be reported to the master during slave registration -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME REPORT_PORT -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Port for connecting to slave reported to the master during slave registration. Set it only if the slave is listening on a non-default port or if you have a special tunnel from the master or other clients to the slave. If not sure, leave this option unset -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME REPORT_USER -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The account user name of the slave to be reported to the master during slave registration -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -3072,46 +2732,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SESSION_TRACK_SCHEMA -VARIABLE_SCOPE SESSION -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Track changes to the default schema. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME SESSION_TRACK_STATE_CHANGE -VARIABLE_SCOPE SESSION -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Track changes to the session state. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME SESSION_TRACK_SYSTEM_VARIABLES -VARIABLE_SCOPE SESSION -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Track changes in registered system variables. For compatibility with MySQL defaults this variable should be set to "autocommit, character_set_client, character_set_connection, character_set_results, time_zone" -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SESSION_TRACK_TRANSACTION_INFO -VARIABLE_SCOPE SESSION -VARIABLE_TYPE ENUM -VARIABLE_COMMENT Track changes to the transaction attributes. OFF to disable; STATE to track just transaction state (Is there an active transaction? Does it have any data? etc.); CHARACTERISTICS to track transaction state and report all statements needed to start a transaction withthe same characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction). -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SKIP_EXTERNAL_LOCKING VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -3142,16 +2762,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME SKIP_PARALLEL_REPLICATION -VARIABLE_SCOPE SESSION ONLY -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT If set when a transaction is written to the binlog, parallel apply of that transaction will be avoided on a slave where slave_parallel_mode is not "aggressive". Can be used to avoid unnecessary rollback and retry for transactions that are likely to cause a conflict if replicated in parallel. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SKIP_REPLICATION VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BOOLEAN @@ -3182,46 +2792,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME SLAVE_DDL_EXEC_MODE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE ENUM -VARIABLE_COMMENT How replication events should be executed. Legal values are STRICT and IDEMPOTENT (default). In IDEMPOTENT mode, replication will not stop for DDL operations that are idempotent. This means that CREATE TABLE is treated as CREATE TABLE OR REPLACE and DROP TABLE is treated as DROP TABLE IF EXISTS. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST STRICT,IDEMPOTENT -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 16383 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_EXEC_MODE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE ENUM -VARIABLE_COMMENT How replication events should be executed. Legal values are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will not stop for operations that are idempotent. For example, in row based replication attempts to delete rows that doesn't exist will be ignored. In STRICT mode, replication will stop on any unexpected difference between the master and the slave. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST STRICT,IDEMPOTENT -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_LOAD_TMPDIR -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT The location where the slave should put its temporary files when replicating a LOAD DATA INFILE command -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED @@ -3232,106 +2802,6 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_NET_TIMEOUT -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Number of seconds to wait for more data from any master/slave connection before aborting the read -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 31536000 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 2147483647 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_PARALLEL_MODE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE ENUM -VARIABLE_COMMENT Controls what transactions are applied in parallel when using --slave-parallel-threads. Possible values: "optimistic" tries to apply most transactional DML in parallel, and handles any conflicts with rollback and retry. "conservative" limits parallelism in an effort to avoid any conflicts. "aggressive" tries to maximise the parallelism, possibly at the cost of increased conflict rate. "minimal" only parallelizes the commit steps of transactions. "none" disables parallel apply completely. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST none,minimal,conservative,optimistic,aggressive -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME SLAVE_PARALLEL_THREADS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 16383 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_PARALLEL_WORKERS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Alias for slave_parallel_threads -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 16383 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_RUN_TRIGGERS_FOR_RBR -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE ENUM -VARIABLE_COMMENT Modes for how triggers in row-base replication on slave side will be executed. Legal values are NO (default), YES and LOGGING. NO means that trigger for RBR will not be running on slave. YES and LOGGING means that triggers will be running on slave, if there was not triggers running on the master for the statement. LOGGING also means results of that the executed triggers work will be written to the binlog. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NO,YES,LOGGING -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_SKIP_ERRORS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Tells the slave thread to continue replication when a query event returns an error from the provided list -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_SQL_VERIFY_CHECKSUM -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Force checksum verification of replication events after reading them from relay log. Note: Events are always checksum-verified by slave on receiving them from the network before writing them to the relay log -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME SLAVE_TRANSACTION_RETRIES -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout, before giving up and stopping -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SLAVE_TYPE_CONVERSIONS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE SET -VARIABLE_COMMENT Set of slave type conversions that are enabled. If the variable is empty, no conversions are allowed and it is expected that the types match exactly -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST ALL_LOSSY,ALL_NON_LOSSY -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED @@ -3482,16 +2952,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL -VARIABLE_NAME SQL_SLAVE_SKIP_COUNTER -VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Skip the next N events from the master log -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SQL_WARNINGS VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN @@ -3511,7 +2971,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SSL_CAPATH VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3521,7 +2981,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SSL_CERT VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3531,7 +2991,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SSL_CIPHER VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3541,7 +3001,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SSL_CRL VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3551,7 +3011,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SSL_CRLPATH VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3561,7 +3021,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SSL_KEY VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3571,7 +3031,7 @@ NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STANDARD_COMPLIANT_CTE VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN @@ -3642,26 +3102,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SYNC_RELAY_LOG -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Synchronously flush relay log to disk after every #th event. Use 0 to disable synchronous flushing -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SYNC_RELAY_LOG_INFO -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Synchronously flush relay log info to disk after every #th transaction. Use 0 to disable synchronous flushing -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SYSTEM_TIME_ZONE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -3729,79 +3169,9 @@ VARIABLE_COMMENT Define threads usage for handling queries NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST one-thread-per-connection,no-threads,pool-of-threads +ENUM_VALUE_LIST one-thread-per-connection,no-threads READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME THREAD_POOL_IDLE_TIMEOUT -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Timeout in seconds for an idle thread in the thread pool.Worker thread will be shut down after timeout -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME THREAD_POOL_MAX_THREADS -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Maximum allowed number of worker threads in the thread pool -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 65536 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME THREAD_POOL_OVERSUBSCRIBE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT How many additional active worker threads in a group are allowed. -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 1000 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME THREAD_POOL_PRIORITY -VARIABLE_SCOPE SESSION -VARIABLE_TYPE ENUM -VARIABLE_COMMENT Threadpool priority. High priority connections usually start executing earlier than low priority.If priority set to 'auto', the the actual priority(low or high) is determined based on whether or not connection is inside transaction. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST high,low,auto -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME THREAD_POOL_PRIO_KICKUP_TIMER -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT The number of milliseconds before a dequeued low-priority statement is moved to the high-priority queue -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME THREAD_POOL_SIZE -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Number of thread groups in the pool. This parameter is roughly equivalent to maximum number of concurrently executing threads (threads in a waiting state do not count as executing). -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 100000 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME THREAD_POOL_STALL_LIMIT -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Maximum query execution time in milliseconds,before an executing non-yielding thread is considered stalled.If a worker thread is stalled, additional worker thread may be created to handle remaining clients. -NUMERIC_MIN_VALUE 10 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 1 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_STACK VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -- cgit v1.2.1 From 5e5feb84b6211f6fe9bbed767512b7b944f59ec9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 28 Jan 2022 16:53:26 +0100 Subject: MDEV-11241 Certain combining marks cause MariaDB to crash when doing Full-Text searches fix it for Aria too --- mysql-test/suite/maria/fulltext2.result | 7 +++++++ mysql-test/suite/maria/fulltext2.test | 9 +++++++++ storage/maria/ma_ft_boolean_search.c | 6 +----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/maria/fulltext2.result b/mysql-test/suite/maria/fulltext2.result index 1e4e6636ef6..6cffc5cf404 100644 --- a/mysql-test/suite/maria/fulltext2.result +++ b/mysql-test/suite/maria/fulltext2.result @@ -84,3 +84,10 @@ select count(*) from t1 where match a against ('aaayyy' in boolean mode); count(*) 0 drop table t1; +set names utf8mb4; +create table t1 (a int, b text, fulltext (b)) charset=utf8mb4 collate=utf8mb4_unicode_ci engine=aria; +insert t1 values (1000, 'C͓̙̯͔̩ͅͅi̩̘̜̲a̯̲̬̳̜̖̤o͕͓̜͓̺̖̗,̠̬͚ ̺T͇̲h͈̱e ̬̜D̖o̦̖͔̗͖̩̘c̣̼t̝͉̫̮̗o͉̫̭r̙͎̗.͓̪̥'); +select a from t1 where match(b) against ('ciao' in boolean mode); +a +1000 +drop table t1; diff --git a/mysql-test/suite/maria/fulltext2.test b/mysql-test/suite/maria/fulltext2.test index 060b748eb4f..7bfbe600ff7 100644 --- a/mysql-test/suite/maria/fulltext2.test +++ b/mysql-test/suite/maria/fulltext2.test @@ -75,3 +75,12 @@ select count(*) from t1 where match a against ('aaaxxx' in boolean mode); select count(*) from t1 where match a against ('aaayyy' in boolean mode); drop table t1; + +# +# MDEV-11241 Certain combining marks cause MariaDB to crash when doing Full-Text searches +# +set names utf8mb4; +create table t1 (a int, b text, fulltext (b)) charset=utf8mb4 collate=utf8mb4_unicode_ci engine=aria; +insert t1 values (1000, 'C͓̙̯͔̩ͅͅi̩̘̜̲a̯̲̬̳̜̖̤o͕͓̜͓̺̖̗,̠̬͚ ̺T͇̲h͈̱e ̬̜D̖o̦̖͔̗͖̩̘c̣̼t̝͉̫̮̗o͉̫̭r̙͎̗.͓̪̥'); +select a from t1 where match(b) against ('ciao' in boolean mode); +drop table t1; diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c index 2f0fba9a0ad..fec9266a760 100644 --- a/storage/maria/ma_ft_boolean_search.c +++ b/storage/maria/ma_ft_boolean_search.c @@ -195,11 +195,7 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, switch (info->type) { case FT_TOKEN_WORD: ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root, - sizeof(FTB_WORD) + - (info->trunc ? MARIA_MAX_KEY_BUFF : - word_len * ftb_param->ftb->charset->mbmaxlen + - HA_FT_WLEN + - ftb_param->ftb->info->s->rec_reflength)); + sizeof(FTB_WORD) + HA_MAX_KEY_BUFF); ftbw->len= word_len + 1; ftbw->flags= 0; ftbw->off= 0; -- cgit v1.2.1 From 8afcda9309832f44a9ba27aaf16d08a0357c0880 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 29 Jan 2022 13:42:38 +0100 Subject: ASAN/valgrind errors in connect.misc test accessing freed memory. Before XMLCOL::WriteColumn() Tdbp->Clist gets assigned a nodelist in Clist = RowNode->SelectNodes(g, Colname, Clist); which is RowNode->Doc->Xop->nodesetval. In XMLCOL::WriteColumn() ValNode = ColNode->SelectSingleNode(g, Xname, Vxnp); calls LIBXMLDOC::GetNodeList() again, which frees the previous XPath object Xop and replaces it with a new one. In this case RowNode->Doc == ColNode->Doc, so Clist->Listp points to a freed memory now. --- storage/connect/tabxml.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index 7357d2373c8..f17f5278c96 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -1803,6 +1803,9 @@ void XMLCOL::WriteColumn(PGLOBAL g) else if (Tdbp->Clist) ColNode = NULL; + // refresh CList in case its Listp was freed in SelectSingleNode above + if (Tdbp->Clist) + Tdbp->RowNode->SelectNodes(g, Tdbp->Colname, Tdbp->Clist); } // endfor i /*********************************************************************/ -- cgit v1.2.1 From e2b50213cf12623da31c8b49be4d40772876223c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 29 Jan 2022 13:56:18 +0100 Subject: main.events_embedded test failures in buildbot revert 68b3fa8865a --- mysql-test/r/events_embedded.result | 2 +- mysql-test/t/events_embedded.test | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/events_embedded.result b/mysql-test/r/events_embedded.result index 5dc48402a88..1a02188f2df 100644 --- a/mysql-test/r/events_embedded.result +++ b/mysql-test/r/events_embedded.result @@ -1,2 +1,2 @@ set global event_scheduler=ON; -set global event_scheduler=ORIGINAL; +ERROR HY000: Unknown system variable 'event_scheduler' diff --git a/mysql-test/t/events_embedded.test b/mysql-test/t/events_embedded.test index e0bde053e8a..f6921f302bf 100644 --- a/mysql-test/t/events_embedded.test +++ b/mysql-test/t/events_embedded.test @@ -1,5 +1,4 @@ --source include/is_embedded.inc +--error 1193 set global event_scheduler=ON; -set global event_scheduler=ORIGINAL; - -- cgit v1.2.1