diff options
354 files changed, 20614 insertions, 1637 deletions
diff --git a/.gitignore b/.gitignore index 255759e76dd..519b0c09404 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,17 @@ *-t *.ctest *.reject +*.orig *.spec *.bak *.dgcov *.rpm .*.swp +.#* +.vimrc +.editorconfig +.kateconfig +*.kdev4 *.ninja .ninja_* .gdb_history @@ -494,3 +500,7 @@ UpgradeLog*.htm # Microsoft Fakes FakesAssemblies/ + +compile_commands.json +.clang-format +.kscope/ diff --git a/BUILD/capture_warnings.sh b/BUILD/capture_warnings.sh new file mode 100755 index 00000000000..3413c4226ee --- /dev/null +++ b/BUILD/capture_warnings.sh @@ -0,0 +1,86 @@ +#!/bin/bash +warn_path=$1 +warn_mode=$2 # 'late', 'early' or 'both' +shift 2 + +warn_file="$warn_path/compile.warnings" +suppress_file="$warn_path/suppress.warnings" + +# suppress_warnings: +# +# 1. treat STDIN as sequence of warnings (w) delimited by ^~~~... lines +# +# 2. sanitize each w to matchable m: +# a. ignore 'In file included from' lines; +# b. protect BRE chars; +# c. ignore text coords (NNN:NNN); +# d. convert multiline to X-delimited single line. +# +# 3. match sanitized m against X-delimited suppress.warnings: +# if match not found print w to STDOUT. + +suppress_warnings() +{ + [ -f "$suppress_file" ] || { + cat + return + } + [ -z "$suppress_file" ] && { + cat > /dev/null + return + } + local m w from + IFS="" + while read -r l + do + w="$w$l"$'\n' + + [[ $l =~ ^"In file included from " ]] && { + from=1 + continue + } + + [[ $from && $l =~ ^[[:space:]]+"from " ]] && + continue + + unset from + + if [[ $l =~ ^[[:space:]]*~*\^~*$ ]] + then + cat "$suppress_file" | tr '\n' 'X' | /bin/grep -Gq "$m" || + echo "$w" + unset m w + else + # Protect BRE metacharacters \.[*^$ + l=${l//\\/\\\\} + l=${l//./\\.} + l=${l//[/\\[} + l=${l//-/\\-} + l=${l//\*/\\*} + l=${l//^/\\^} + l=${l//\$/\\\$} + # replace text coords line:char with BRE wildcard + [[ $l =~ ^(.*:)[[:digit:]]+:[[:digit:]]+(.*)$ ]] && + l=${BASH_REMATCH[1]}[[:digit:]]\\+:[[:digit:]]\\+${BASH_REMATCH[2]} + m="$m$l"$'X' + fi + done +} + +exec 3>&1 +"$@" 2>&1 1>&3 | suppress_warnings | ( + cmderr=`cat` + + if [[ -n "$cmderr" ]]; then + if [[ "$cmderr" =~ error: ]]; then + echo "$cmderr" >&2 + exit + fi + [[ "$warn_mode" != "late" ]] && + echo "$cmderr" >&2 + [[ "$warn_mode" != "early" && "$cmderr" =~ (warning|note): ]] && + echo "$cmderr" >> "$warn_file" + fi +) + +exit ${PIPESTATUS} diff --git a/CMakeLists.txt b/CMakeLists.txt index b16105a710b..93ff9c81fcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -503,3 +503,5 @@ IF(NON_DISTRIBUTABLE_WARNING) MESSAGE(WARNING " You have linked MariaDB with GPLv3 libraries! You may not distribute the resulting binary. If you do, you will put yourself into a legal problem with Free Software Foundation.") ENDIF() + +INCLUDE(${CMAKE_SOURCE_DIR}/cmake/print_warnings.cmake) diff --git a/README.md b/README.md index f46888e4b2f..801c30b33e2 100644 --- a/README.md +++ b/README.md @@ -67,4 +67,4 @@ https://github.com/MariaDB/server Code status: ------------ -* [![tests status](https://secure.travis-ci.org/MariaDB/server.png?branch=10.2)](https://travis-ci.org/MariaDB/server) travis-ci.org (10.2 branch) +* [![tests status](https://travis-ci.org/tempesta-tech/mariadb.svg?branch=natsys%2Ftrunk)](https://travis-ci.org/tempesta-tech/mariadb) travis-ci.org (natsys/trunk) diff --git a/cmake/print_warnings.cmake b/cmake/print_warnings.cmake new file mode 100644 index 00000000000..0991ceef7fb --- /dev/null +++ b/cmake/print_warnings.cmake @@ -0,0 +1,37 @@ +IF(NOT DEFINED WARN_MODE) + IF(CMAKE_BUILD_TYPE MATCHES "Debug") + SET(WARN_MODE "late") + ELSE() + SET(WARN_MODE "early") + ENDIF() +ENDIF() + +IF(NOT WARN_MODE STREQUAL "early" AND + NOT WARN_MODE STREQUAL "late" AND + NOT WARN_MODE STREQUAL "both") + MESSAGE(FATAL_ERROR "Unknown WARN_MODE: expected 'early', 'late' or 'both'") +ENDIF() + +SET_DIRECTORY_PROPERTIES(PROPERTIES RULE_LAUNCH_COMPILE + "bash ${CMAKE_SOURCE_DIR}/BUILD/capture_warnings.sh ${CMAKE_BINARY_DIR} ${WARN_MODE}") +SET_DIRECTORY_PROPERTIES(PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + "${CMAKE_BINARY_DIR}/compile.warnings") +ADD_CUSTOM_TARGET(rm_compile.warnings ALL + COMMAND rm -f compile.warnings + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +ADD_CUSTOM_TARGET(print_warnings ALL + COMMAND bash -c '[ -f compile.warnings ] && { echo "Warnings found:" \; cat compile.warnings \; echo "" \; } \; true' + DEPENDS mysqld rm_compile.warnings + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") + +IF(TARGET explain_filename-t) + ADD_DEPENDENCIES(print_warnings explain_filename-t) +ENDIF() + +IF(TARGET mysql_client_test) + ADD_DEPENDENCIES(print_warnings mysql_client_test) +ENDIF() + +IF(TARGET udf_example) + ADD_DEPENDENCIES(print_warnings udf_example) +ENDIF() diff --git a/include/m_string.h b/include/m_string.h index f06acbea358..1889d177911 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -211,6 +211,7 @@ extern ulonglong strtoull(const char *str, char **ptr, int base); #define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1)) #define USTRING_WITH_LEN(X) ((uchar*) X), ((size_t) (sizeof(X) - 1)) #define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1)) +#define LEX_STRING_WITH_LEN(X) (X).str, (X).length typedef struct st_mysql_const_lex_string LEX_CSTRING; diff --git a/include/my_base.h b/include/my_base.h index b93300d7562..d69216311f6 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -408,6 +408,10 @@ enum ha_base_keytype { when only HA_STATUS_VARIABLE but it won't be used. */ #define HA_STATUS_VARIABLE_EXTRA 128U +/* + Treat empty table as empty (ignore HA_STATUS_TIME hack). +*/ +#define HA_STATUS_OPEN 256U /* Errorcodes given by handler functions diff --git a/include/my_sys.h b/include/my_sys.h index e8658d34af9..211e0baa0de 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -715,6 +715,7 @@ extern int my_sync(File fd, myf my_flags); extern int my_sync_dir(const char *dir_name, myf my_flags); extern int my_sync_dir_by_file(const char *file_name, myf my_flags); extern const char *my_get_err_msg(uint nr); +extern void my_error_as(uint nr1, uint nr2, myf MyFlags, ...); extern int my_error_register(const char** (*get_errmsgs) (int nr), uint first, uint last); extern my_bool my_error_unregister(uint first, uint last); diff --git a/include/mysql_com.h b/include/mysql_com.h index 71858c93046..7240b69968f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -192,6 +192,17 @@ enum enum_indicator_type #define FIELD_FLAGS_COLUMN_FORMAT_MASK (3U << FIELD_FLAGS_COLUMN_FORMAT) #define FIELD_IS_DROPPED (1U << 26) /* Intern: Field is being dropped */ +#define VERS_SYS_START_FLAG (1 << 27) /* autogenerated column declared with + `generated always as row start` + (see II.a SQL Standard) */ +#define VERS_SYS_END_FLAG (1 << 28) /* autogenerated column declared with + `generated always as row end` + (see II.a SQL Standard).*/ +#define VERS_OPTIMIZED_UPDATE_FLAG (1 << 29) /* column that doesn't support + system versioning when table + itself supports it*/ +#define HIDDEN_FLAG (1 << 31) /* hide from SELECT * */ + #define REFRESH_GRANT (1ULL << 0) /* Refresh grant tables */ #define REFRESH_LOG (1ULL << 1) /* Start on new log file */ #define REFRESH_TABLES (1ULL << 2) /* close all tables */ diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index cdf1abcd89c..ed10262de50 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -118,6 +118,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/temporary_tables.cc ../sql/session_tracker.cc ../sql/proxy_protocol.cc + ../sql/item_vers.cc + ../sql/vtmd.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) diff --git a/mysql-test/disabled.def b/mysql-test/disabled.def index b489139a59f..49d82275b2d 100644 --- a/mysql-test/disabled.def +++ b/mysql-test/disabled.def @@ -21,3 +21,5 @@ innodb-wl5522-debug-zip : broken upstream innodb_bug12902967 : broken upstream file_contents : MDEV-6526 these files are not installed anymore max_statement_time : cannot possibly work, depends on timing +ssl_ca : natsys: fails in mariadb-10.2.2 +innodb_load_xa : natsys: requires external innodb plugin diff --git a/mysql-test/extra/binlog_tests/blackhole.test b/mysql-test/extra/binlog_tests/blackhole.test index 90146d41471..0ffd24adc03 100644 --- a/mysql-test/extra/binlog_tests/blackhole.test +++ b/mysql-test/extra/binlog_tests/blackhole.test @@ -17,13 +17,13 @@ drop table if exists t1,t2; --enable_warnings CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, + Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE=blackhole; INSERT INTO t1 VALUES (9410,9412); -select period from t1; +select period_ from t1; select * from t1; select t1.* from t1; diff --git a/mysql-test/include/common-tests.inc b/mysql-test/include/common-tests.inc index 204b6d4dd6b..c0ed1427215 100644 --- a/mysql-test/include/common-tests.inc +++ b/mysql-test/include/common-tests.inc @@ -14,13 +14,13 @@ drop table if exists t1,t2,t3,t4; --enable_warnings CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, + Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; +select period_ from t1; select * from t1; select t1.* from t1; @@ -1349,7 +1349,7 @@ select fld1,fld3 from t2 where fld1 like "25050_"; select distinct companynr from t2; select distinct companynr from t2 order by companynr; select distinct companynr from t2 order by companynr desc; -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; select distinct fld3 from t2 where companynr = 34 order by fld3; select distinct fld3 from t2 limit 10; @@ -1362,26 +1362,26 @@ select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10; # make a big table. create table t3 ( - period int not null, + period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), - key (period), + key (period_), key (name) ); --disable_query_log -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1001,"Iranizes",37,5987435,234724); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1002,"violinist",37,28357832,8723648); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1003,"extramarital",37,39654943,235872); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1004,"spates",78,726498,72987523); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1005,"cloakroom",78,98439034,823742); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1006,"gazer",101,834598,27348324); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1007,"hand",154,983543950,29837423); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1008,"tucked",311,234298,3275892); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1009,"gems",447,2374834,9872392); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1010,"clinker",512,786542,76234234); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1001,"Iranizes",37,5987435,234724); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1002,"violinist",37,28357832,8723648); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1003,"extramarital",37,39654943,235872); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1004,"spates",78,726498,72987523); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1005,"cloakroom",78,98439034,823742); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1006,"gazer",101,834598,27348324); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1007,"hand",154,983543950,29837423); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1008,"tucked",311,234298,3275892); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1009,"gems",447,2374834,9872392); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1010,"clinker",512,786542,76234234); --enable_query_log create temporary table tmp engine = myisam select * from t3; @@ -1450,39 +1450,39 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 # Some test with ORDER BY and limit # -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; # # Search with a constant table. # -select period from t1; -select period from t1 where period=1900; -select fld3,period from t1,t2 where fld1 = 011401 order by period; +select period_ from t1; +select period_ from t1 where period_=1900; +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; # # Search with a constant table and several keyparts. (Rows are read only once # in the beginning of the search) # -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; # # Search with a constant table and several rows from another table # -select fld3,period from t2,t1 where companynr*10 = 37*10; +select fld3,period_ from t2,t1 where companynr*10 = 37*10; # # Search with a table reference and without a key. # t3 will be the main table. # -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; # # Search with an interval on a table with full key on reference table. @@ -1490,7 +1490,7 @@ select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1 # t2nr will be checked. # -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; # # We need another table for join stuff.. @@ -1588,18 +1588,18 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= # each record # -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; # # Test of many parenthesis levels # -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; @@ -1657,7 +1657,7 @@ select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 grou # Calculation with group functions # -select sum(Period)/count(*) from t1; +select sum(Period_)/count(*) from t1; select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg; @@ -1747,13 +1747,13 @@ select max(t2nr) from t3 where price=983543950; # Test of alias # -select t1.period from t3 = t1 limit 1; -select t1.period from t1 as t1 limit 1; -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -select period as ok_period from t1 limit 1; -select period as ok_period from t1 group by ok_period limit 1; +select t1.period_ from t3 = t1 limit 1; +select t1.period_ from t1 as t1 limit 1; +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +select period_ as ok_period from t1 limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; select 1+1 as summa from t1 group by summa limit 1; -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; # # Some simple show commands diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1b072ef7dc7..a3f2d98d18e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -197,6 +197,7 @@ my @DEFAULT_SUITES= qw( sql_sequence- unit- vcol- + versioning- wsrep- galera- ); @@ -220,6 +221,7 @@ our @opt_extra_mysqld_opt; our @opt_mysqld_envs; my $opt_stress; +my $opt_tail_lines= 20; my $opt_dry_run; @@ -1204,6 +1206,7 @@ sub command_line_setup { 'report-times' => \$opt_report_times, 'result-file' => \$opt_resfile, 'stress=s' => \$opt_stress, + 'tail-lines=i' => \$opt_tail_lines, 'dry-run' => \$opt_dry_run, 'help|h' => \$opt_usage, @@ -4870,7 +4873,7 @@ sub report_failure_and_restart ($) { $tinfo->{comment}.= "The result from queries just before the failure was:". "\n< snip >\n". - mtr_lastlinesfromfile($log_file_name, 20)."\n"; + mtr_lastlinesfromfile($log_file_name, $opt_tail_lines)."\n"; } } } @@ -5543,7 +5546,7 @@ sub start_mysqltest ($) { mtr_add_arg($args, "--test-file=%s", $tinfo->{'path'}); # Number of lines of resut to include in failure report - mtr_add_arg($args, "--tail-lines=20"); + mtr_add_arg($args, "--tail-lines=%d", $opt_tail_lines); if ( defined $tinfo->{'result_file'} ) { mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'}); @@ -6191,6 +6194,8 @@ Misc options phases of test execution. stress=ARGS Run stress test, providing options to mysql-stress-test.pl. Options are separated by comma. + tail-lines=N Number of lines of the result to include in a failure + report. Some options that control enabling a feature for normal test runs, can be turned off by prepending 'no' to the option, e.g. --notimer. diff --git a/mysql-test/r/1st.result b/mysql-test/r/1st.result index f9e4b37aa94..1c4000c9a6a 100644 --- a/mysql-test/r/1st.result +++ b/mysql-test/r/1st.result @@ -37,3 +37,4 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template diff --git a/mysql-test/r/alter_user.result b/mysql-test/r/alter_user.result index ac668bba8fa..6bbe8185cdd 100644 --- a/mysql-test/r/alter_user.result +++ b/mysql-test/r/alter_user.result @@ -1,25 +1,25 @@ select * from mysql.user where user = 'root' and host = 'localhost'; -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 -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 # Test syntax # # These 2 selects should have no changes from the first one. alter user CURRENT_USER; select * from mysql.user where user = 'root' and host = 'localhost'; -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 -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 alter user CURRENT_USER(); select * from mysql.user where user = 'root' and host = 'localhost'; -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 -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 create user foo; 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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 alter user foo; 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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 # Test super privilege works correctly with a read only database. SET @start_read_only = @@global.read_only; SET GLOBAL read_only=1; @@ -50,44 +50,44 @@ Note 1396 Operation ALTER USER failed for 'boo' # Test password related altering. alter user foo identified by 'something'; 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 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N 0 0 0 0 N N 0.000000 alter user foo identified by 'something2'; 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 *9CD58369E930E28C8996A89DB18B63294E6DC10C 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 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *9CD58369E930E28C8996A89DB18B63294E6DC10C 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 N 0 0 0 0 N N 0.000000 alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; 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 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N 0 0 0 0 N N 0.000000 alter user foo identified with 'somecoolplugin'; 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 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 0 0 0 0 somecoolplugin N N 0.000000 +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 Delete_versioning_rows_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 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 N 0 0 0 0 somecoolplugin N N 0.000000 alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; 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 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 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000 +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 Delete_versioning_rows_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 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 N 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000 # Test ssl related altering. alter user foo identified by 'something' require SSL; 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 ANY 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N ANY 0 0 0 0 N N 0.000000 alter user foo identified by 'something' require X509; 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 X509 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N X509 0 0 0 0 N N 0.000000 alter user foo identified by 'something' require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; 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 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N SPECIFIED text foo_issuer foo_subject 0 0 0 0 N N 0.000000 # Test resource limits altering. alter user foo with MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40; 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 +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 Delete_versioning_rows_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 N SPECIFIED text foo_issuer foo_subject 10 20 30 40 N N 0.000000 drop user foo; diff --git a/mysql-test/r/compress.result b/mysql-test/r/compress.result index 762ab6630d8..b16a95cc702 100644 --- a/mysql-test/r/compress.result +++ b/mysql-test/r/compress.result @@ -7,18 +7,18 @@ VARIABLE_NAME VARIABLE_VALUE COMPRESSION ON drop table if exists t1,t2,t3,t4; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -282,8 +282,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -487,12 +487,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -606,35 +606,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1223,8 +1223,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1284,8 +1284,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1325,7 +1325,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1440,23 +1440,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1713,8 +1713,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2044,26 +2044,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index dfe4406605e..e3e2e4db39c 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -33,6 +33,7 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template connect con2,localhost,root,,test; show tables; Tables_in_test @@ -80,6 +81,7 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template connect con4,localhost,test,gambling,test; show tables; Tables_in_test @@ -139,6 +141,7 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template connect con6,localhost,test,gambling3,test; show tables; Tables_in_test diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index dca48c07fe9..7459936eabb 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -132,7 +132,7 @@ drop table t2; create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f; describe t2; Field Type Null Key Default Extra -a datetime NO NULL +a datetime YES NULL b time NO NULL c date NO NULL d int(3) NO NULL diff --git a/mysql-test/r/create_user.result b/mysql-test/r/create_user.result index 1411f2e8792..6bc09a91f17 100644 --- a/mysql-test/r/create_user.result +++ b/mysql-test/r/create_user.result @@ -1,57 +1,57 @@ create user foo; 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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password'; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password' require SSL; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N ANY 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N ANY 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password' require X509; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N X509 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N X509 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password' require CIPHER 'cipher'; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password' require ISSUER 'issuer'; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED issuer 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED issuer 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password' require SUBJECT 'subject'; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED subject 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED subject 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password' require CIPHER 'cipher' SUBJECT 'subject'; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher subject 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher subject 0 0 0 0 N N 0.000000 drop user foo; create user foo identified by 'password' require CIPHER 'cipher' AND SUBJECT 'subject' AND ISSUER 'issuer'; 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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 drop user foo; create user foo, foo2 identified by 'password' require CIPHER 'cipher' AND SUBJECT 'subject' AND ISSUER 'issuer'; select * from mysql.user where user like '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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 #--warning ER_USER_CREATE_EXISTS create user if not exists foo, foo2 identified by 'password2' require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; @@ -59,14 +59,14 @@ Warnings: Note 1973 Can't create user 'foo'@'%'; it already exists Note 1973 Can't create user 'foo2'@'%'; it already exists select * from mysql.user where user like '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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +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 Delete_versioning_rows_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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 drop user foo, foo2; create user foo with MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40; select * from mysql.user where user like '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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 40 N N 0.000000 +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 Delete_versioning_rows_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 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 40 N N 0.000000 drop user foo; diff --git a/mysql-test/r/ctype_upgrade.result b/mysql-test/r/ctype_upgrade.result index 53cb858035b..e56cfaa617d 100644 --- a/mysql-test/r/ctype_upgrade.result +++ b/mysql-test/r/ctype_upgrade.result @@ -258,6 +258,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -316,6 +317,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 9221c6240bd..250a5093284 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2310,6 +2310,8 @@ Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' DROP TABLE t1; SET SESSION optimizer_switch= @save_optimizer_switch; # diff --git a/mysql-test/r/events_grant.result b/mysql-test/r/events_grant.result index a054e58494b..51b80742737 100644 --- a/mysql-test/r/events_grant.result +++ b/mysql-test/r/events_grant.result @@ -23,7 +23,7 @@ SHOW GRANTS; Grants for ev_test@localhost GRANT USAGE ON *.* TO 'ev_test'@'localhost' GRANT ALL PRIVILEGES ON `events_test`.* TO 'ev_test'@'localhost' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, TRIGGER ON `events_test2`.* TO 'ev_test'@'localhost' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, TRIGGER, DELETE VERSIONING ROWS ON `events_test2`.* TO 'ev_test'@'localhost' "Here comes an error:"; SHOW EVENTS; ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_test2' diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 7ee5a68ca90..fa09d13b868 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -49,7 +49,7 @@ a b Full-text indexes are called collections Only MyISAM tables support collections select * from t1 where MATCH(a,b) AGAINST ("indexes" IN BOOLEAN MODE WITH QUERY EXPANSION); -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 'QUERY EXPANSION)' at line 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 'WITH QUERY EXPANSION)' at line 1 explain select * from t1 where MATCH(a,b) AGAINST ("collections"); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 fulltext a a 0 1 Using where diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 3340328cad6..d8b6581b022 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -787,7 +787,7 @@ drop table t2; create table t2 select f2 from (select now() f2 from t1) a; show columns from t2; Field Type Null Key Default Extra -f2 datetime NO NULL +f2 datetime YES NULL drop table t2, t1; CREATE TABLE t1( id int PRIMARY KEY, diff --git a/mysql-test/r/func_time_hires.result b/mysql-test/r/func_time_hires.result index 0f822456724..17c55d554bc 100644 --- a/mysql-test/r/func_time_hires.result +++ b/mysql-test/r/func_time_hires.result @@ -39,14 +39,14 @@ t1 CREATE TABLE `t1` ( `sec_to_time(12345)` time DEFAULT NULL, `sec_to_time(12345.6789)` time(4) DEFAULT NULL, `sec_to_time(1234567e-2)` time(6) DEFAULT NULL, - `now()` datetime NOT NULL, + `now()` datetime DEFAULT NULL, `curtime(0)` time NOT NULL, - `utc_timestamp(1)` datetime(1) NOT NULL, + `utc_timestamp(1)` datetime(1) DEFAULT NULL, `utc_time(2)` time(2) NOT NULL, `current_time(3)` time(3) NOT NULL, - `current_timestamp(4)` datetime(4) NOT NULL, - `localtime(5)` datetime(5) NOT NULL, - `localtimestamp(6)` datetime(6) NOT NULL, + `current_timestamp(4)` datetime(4) DEFAULT NULL, + `localtime(5)` datetime(5) DEFAULT NULL, + `localtimestamp(6)` datetime(6) DEFAULT NULL, `time_to_sec(123456)` bigint(17) DEFAULT NULL, `time_to_sec('12:34:56.789')` decimal(19,3) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 5b239f09172..e78f435278a 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -49,6 +49,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type SPECIFIED ssl_cipher EDH-RSA-DES-CBC3-SHA x509_issuer @@ -124,6 +125,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -175,6 +177,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -223,7 +226,7 @@ revoke LOCK TABLES, ALTER on mysqltest.* from mysqltest_1@localhost; show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user='mysqltest_1'; flush privileges; @@ -609,6 +612,7 @@ Create temporary tables Databases To use CREATE TEMPORARY TABLE Create view Tables To create new views Create user Server Admin To create new users Delete Tables To delete existing rows +Delete versioning rows Tables To delete versioning table historical rows Drop Databases,Tables To drop databases, tables, and views Event Server Admin To create, alter, drop and execute events Execute Functions,Procedures To execute stored routines @@ -664,8 +668,8 @@ SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE = '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; TABLE_SCHEMA TABLE_NAME PRIVILEGES -mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE -mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE +mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DELETE VERSIONING ROWS, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE +mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DELETE VERSIONING ROWS, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE FLUSH PRIVILEGES; SHOW GRANTS FOR dummy@localhost; Grants for dummy@localhost @@ -676,8 +680,8 @@ SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE = '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; TABLE_SCHEMA TABLE_NAME PRIVILEGES -mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE -mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE +mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DELETE VERSIONING ROWS, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE +mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DELETE VERSIONING ROWS, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, UPDATE SHOW FIELDS FROM mysql.tables_priv; Field Type Null Key Default Extra Host char(60) NO PRI @@ -686,7 +690,7 @@ User char(80) NO PRI Table_name char(64) NO PRI Grantor char(141) NO MUL Timestamp timestamp NO current_timestamp() on update current_timestamp() -Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') NO +Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') NO Column_priv set('Select','Insert','Update','References') NO use test; REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; @@ -769,7 +773,7 @@ flush privileges; use test; set @user123="non-existent"; select * from mysql.db where user=@user123; -Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv +Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv Delete_versioning_rows_priv set names koi8r; create database ÂÄ; grant select on ÂÄ.* to root@localhost; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 1c073881a9d..6f25e264d9e 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -123,6 +123,7 @@ time_zone_transition time_zone_transition_type user v1 +vtmd_template select c,table_name from v1 inner join information_schema.TABLES v2 on (v1.c=v2.table_name) where v1.c like "t%"; @@ -487,6 +488,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE 'mysqltest_1'@'localhost' def test ALTER ROUTINE YES 'mysqltest_1'@'localhost' def test EVENT YES 'mysqltest_1'@'localhost' def test TRIGGER YES +'mysqltest_1'@'localhost' def test DELETE VERSIONING ROWS YES select * from information_schema.TABLE_PRIVILEGES where grantee like '%mysqltest_1%'; GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE 'mysqltest_1'@'localhost' def test t1 SELECT NO @@ -743,6 +745,7 @@ Lock_tables_priv select,insert,update,references Show_view_priv select,insert,update,references Create_routine_priv select,insert,update,references Alter_routine_priv select,insert,update,references +Delete_versioning_rows_priv select,insert,update,references max_questions select,insert,update,references max_connections select,insert,update,references max_user_connections select,insert,update,references @@ -1334,12 +1337,12 @@ DROP PROCEDURE p1; DROP USER mysql_bug20230@localhost; SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test') and table_name not like 'xtradb%'; MAX(table_name) -VIEWS +vtmd_template SELECT table_name from information_schema.tables WHERE table_name=(SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test') and table_name not like 'xtradb%'); table_name -VIEWS +vtmd_template DROP TABLE IF EXISTS bug23037; DROP FUNCTION IF EXISTS get_value; SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037'; diff --git a/mysql-test/r/information_schema_all_engines.result b/mysql-test/r/information_schema_all_engines.result index 126a6f4bccd..8a92f0226ff 100644 --- a/mysql-test/r/information_schema_all_engines.result +++ b/mysql-test/r/information_schema_all_engines.result @@ -454,4 +454,4 @@ Wildcard: inf_rmation_schema SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA; table_schema count(*) information_schema 64 -mysql 30 +mysql 31 diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index df48dbba605..046674d5569 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -762,6 +762,7 @@ user User def mysql 0 mysql PRIMARY 2 A NULL NULL BTREE def mysql '' NO char 8 Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' drop table t1; drop table t2; drop table t3; diff --git a/mysql-test/r/log_tables_upgrade.result b/mysql-test/r/log_tables_upgrade.result index a56d067c2cd..a8352824aa4 100644 --- a/mysql-test/r/log_tables_upgrade.result +++ b/mysql-test/r/log_tables_upgrade.result @@ -43,6 +43,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' diff --git a/mysql-test/r/lowercase_table_grant.result b/mysql-test/r/lowercase_table_grant.result index 009965c0c8e..7e2ac238cf7 100644 --- a/mysql-test/r/lowercase_table_grant.result +++ b/mysql-test/r/lowercase_table_grant.result @@ -7,8 +7,8 @@ Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' GRANT ALL PRIVILEGES ON `mysqltest`.* TO 'mysqltest_1'@'localhost' select * from db where user = 'mysqltest_1'; -Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv -localhost mysqltest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y Y Y +Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv Delete_versioning_rows_priv +localhost mysqltest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y Y Y Y update db set db = 'MYSQLtest' where db = 'mysqltest' and user = 'mysqltest_1' and host = 'localhost'; flush privileges; show grants for mysqltest_1@localhost; @@ -16,8 +16,8 @@ Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' GRANT ALL PRIVILEGES ON `mysqltest`.* TO 'mysqltest_1'@'localhost' select * from db where user = 'mysqltest_1'; -Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv -localhost MYSQLtest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y Y Y +Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv Delete_versioning_rows_priv +localhost MYSQLtest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y Y Y Y delete from db where db = 'MYSQLtest' and user = 'mysqltest_1' and host = 'localhost'; flush privileges; drop user mysqltest_1@localhost; diff --git a/mysql-test/r/mysql_upgrade-6984.result b/mysql-test/r/mysql_upgrade-6984.result index 59c9a865b7c..2b995ad5364 100644 --- a/mysql-test/r/mysql_upgrade-6984.result +++ b/mysql-test/r/mysql_upgrade-6984.result @@ -34,6 +34,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Repairing tables mysql.innodb_index_stats @@ -42,6 +45,9 @@ error : Corrupt mysql.innodb_table_stats Error : Unknown storage engine 'InnoDB' error : Corrupt +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index a6a5da8f8c8..47a3231542f 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -31,6 +31,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -79,6 +80,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -127,6 +129,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -180,6 +183,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -234,6 +238,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -291,6 +296,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -343,6 +349,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views... Skipped Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -387,6 +394,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -452,6 +460,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -534,6 +543,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -552,7 +562,7 @@ OK # Should return 2 SELECT count(*) FROM information_schema.tables where ENGINE="InnoDB"; count(*) -2 +3 SHOW CREATE TABLE test.t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/mysql_upgrade_no_innodb.result b/mysql-test/r/mysql_upgrade_no_innodb.result index 6ad818278f8..22e88e27775 100644 --- a/mysql-test/r/mysql_upgrade_no_innodb.result +++ b/mysql-test/r/mysql_upgrade_no_innodb.result @@ -34,6 +34,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Repairing tables mysql.innodb_index_stats @@ -42,6 +45,9 @@ error : Corrupt mysql.innodb_table_stats Error : Unknown storage engine 'InnoDB' error : Corrupt +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views... Skipped Phase 4/7: Running 'mysql_fix_privilege_tables' diff --git a/mysql-test/r/mysql_upgrade_noengine.result b/mysql-test/r/mysql_upgrade_noengine.result index 09e705abb69..582147d09df 100644 --- a/mysql-test/r/mysql_upgrade_noengine.result +++ b/mysql-test/r/mysql_upgrade_noengine.result @@ -81,6 +81,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -167,6 +168,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -253,6 +255,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Upgrading from a version before MariaDB-10.1 Phase 2/7: Installing used storage engines Checking for tables with unknown storage engine diff --git a/mysql-test/r/mysql_upgrade_ssl.result b/mysql-test/r/mysql_upgrade_ssl.result index 918a24ffc71..0285d4ac095 100644 --- a/mysql-test/r/mysql_upgrade_ssl.result +++ b/mysql-test/r/mysql_upgrade_ssl.result @@ -32,6 +32,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views Phase 4/7: Running 'mysql_fix_privilege_tables' diff --git a/mysql-test/r/mysql_upgrade_view.result b/mysql-test/r/mysql_upgrade_view.result index dc31592566a..0092a772bf9 100644 --- a/mysql-test/r/mysql_upgrade_view.result +++ b/mysql-test/r/mysql_upgrade_view.result @@ -98,6 +98,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Repairing tables mysql.innodb_index_stats @@ -106,6 +109,9 @@ error : Corrupt mysql.innodb_table_stats Error : Unknown storage engine 'InnoDB' error : Corrupt +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views test.v1 OK @@ -242,6 +248,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Repairing tables mysql.innodb_index_stats @@ -250,6 +259,9 @@ error : Corrupt mysql.innodb_table_stats Error : Unknown storage engine 'InnoDB' error : Corrupt +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views from mysql test.v1 OK @@ -361,6 +373,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Repairing tables mysql.innodb_index_stats @@ -369,6 +384,9 @@ error : Corrupt mysql.innodb_table_stats Error : Unknown storage engine 'InnoDB' error : Corrupt +mysql.vtmd_template +Error : Unknown storage engine 'InnoDB' +error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views from mysql test.v1 OK diff --git a/mysql-test/r/mysqlbinlog_row_compressed.result b/mysql-test/r/mysqlbinlog_row_compressed.result index 24fff723ec8..fc44934ef3f 100644 --- a/mysql-test/r/mysqlbinlog_row_compressed.result +++ b/mysql-test/r/mysqlbinlog_row_compressed.result @@ -61,7 +61,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (10, 1, 2, 3, 4, 5, 6, 7, "") #<date> server id 1 end_log_pos 899 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 899 -#<date> server id 1 end_log_pos 967 CRC32 XXX Write_compressed_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 967 CRC32 XXX Write_compressed_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -89,7 +89,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (11, 1, 2, 3, 4, 5, 6, 7, NULL) #<date> server id 1 end_log_pos 1214 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 1214 -#<date> server id 1 end_log_pos 1281 CRC32 XXX Write_compressed_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 1281 CRC32 XXX Write_compressed_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=11 /* INT meta=0 nullable=0 is_null=0 */ @@ -117,7 +117,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (12, 1, 2, 3, NULL, 5, 6, 7, "A") #<date> server id 1 end_log_pos 1530 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 1530 -#<date> server id 1 end_log_pos 1596 CRC32 XXX Write_compressed_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 1596 CRC32 XXX Write_compressed_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=12 /* INT meta=0 nullable=0 is_null=0 */ @@ -145,7 +145,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (13, 1, 2, 3, 0, 5, 6, 7, "A") #<date> server id 1 end_log_pos 1842 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 1842 -#<date> server id 1 end_log_pos 1909 CRC32 XXX Write_compressed_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 1909 CRC32 XXX Write_compressed_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=13 /* INT meta=0 nullable=0 is_null=0 */ @@ -173,7 +173,7 @@ BEGIN #Q> INSERT INTO t2 SELECT * FROM t1 #<date> server id 1 end_log_pos 2134 CRC32 XXX Table_map: `test`.`t2` mapped to number num # at 2134 -#<date> server id 1 end_log_pos 2225 CRC32 XXX Write_compressed_rows: table id 31 flags: STMT_END_F +#<date> server id 1 end_log_pos 2225 CRC32 XXX Write_compressed_rows: table id 32 flags: STMT_END_F ### INSERT INTO `test`.`t2` ### SET ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -234,7 +234,7 @@ BEGIN #Q> UPDATE t2 SET f4=5 WHERE f4>0 or f4 is NULL #<date> server id 1 end_log_pos 2462 CRC32 XXX Table_map: `test`.`t2` mapped to number num # at 2462 -#<date> server id 1 end_log_pos 2561 CRC32 XXX Update_compressed_rows: table id 31 flags: STMT_END_F +#<date> server id 1 end_log_pos 2561 CRC32 XXX Update_compressed_rows: table id 32 flags: STMT_END_F ### UPDATE `test`.`t2` ### WHERE ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -314,7 +314,7 @@ BEGIN #Q> DELETE FROM t1 #<date> server id 1 end_log_pos 2769 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 2769 -#<date> server id 1 end_log_pos 2861 CRC32 XXX Delete_compressed_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 2861 CRC32 XXX Delete_compressed_rows: table id 31 flags: STMT_END_F ### DELETE FROM `test`.`t1` ### WHERE ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -375,7 +375,7 @@ BEGIN #Q> DELETE FROM t2 #<date> server id 1 end_log_pos 3069 CRC32 XXX Table_map: `test`.`t2` mapped to number num # at 3069 -#<date> server id 1 end_log_pos 3154 CRC32 XXX Delete_compressed_rows: table id 31 flags: STMT_END_F +#<date> server id 1 end_log_pos 3154 CRC32 XXX Delete_compressed_rows: table id 32 flags: STMT_END_F ### DELETE FROM `test`.`t2` ### WHERE ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ diff --git a/mysql-test/r/mysqlbinlog_row_minimal.result b/mysql-test/r/mysqlbinlog_row_minimal.result index ca8e43bfb33..9cdac056078 100644 --- a/mysql-test/r/mysqlbinlog_row_minimal.result +++ b/mysql-test/r/mysqlbinlog_row_minimal.result @@ -59,7 +59,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (10, 1, 2, 3, 4, 5, 6, 7, "") #<date> server id 1 end_log_pos 946 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 946 -#<date> server id 1 end_log_pos 1015 CRC32 XXX Write_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 1015 CRC32 XXX Write_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -87,7 +87,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (11, 1, 2, 3, 4, 5, 6, 7, NULL) #<date> server id 1 end_log_pos 1262 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 1262 -#<date> server id 1 end_log_pos 1330 CRC32 XXX Write_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 1330 CRC32 XXX Write_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=11 /* INT meta=0 nullable=0 is_null=0 */ @@ -115,7 +115,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (12, 1, 2, 3, NULL, 5, 6, 7, "A") #<date> server id 1 end_log_pos 1579 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 1579 -#<date> server id 1 end_log_pos 1646 CRC32 XXX Write_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 1646 CRC32 XXX Write_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=12 /* INT meta=0 nullable=0 is_null=0 */ @@ -143,7 +143,7 @@ BEGIN #Q> INSERT INTO t1 VALUES (13, 1, 2, 3, 0, 5, 6, 7, "A") #<date> server id 1 end_log_pos 1892 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 1892 -#<date> server id 1 end_log_pos 1962 CRC32 XXX Write_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 1962 CRC32 XXX Write_rows: table id 31 flags: STMT_END_F ### INSERT INTO `test`.`t1` ### SET ### @1=13 /* INT meta=0 nullable=0 is_null=0 */ @@ -171,7 +171,7 @@ BEGIN #Q> INSERT INTO t2 SELECT * FROM t1 #<date> server id 1 end_log_pos 2187 CRC32 XXX Table_map: `test`.`t2` mapped to number num # at 2187 -#<date> server id 1 end_log_pos 2354 CRC32 XXX Write_rows: table id 31 flags: STMT_END_F +#<date> server id 1 end_log_pos 2354 CRC32 XXX Write_rows: table id 32 flags: STMT_END_F ### INSERT INTO `test`.`t2` ### SET ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -232,7 +232,7 @@ BEGIN #Q> UPDATE t2 SET f4=5 WHERE f4>0 or f4 is NULL #<date> server id 1 end_log_pos 2591 CRC32 XXX Table_map: `test`.`t2` mapped to number num # at 2591 -#<date> server id 1 end_log_pos 2665 CRC32 XXX Update_rows: table id 31 flags: STMT_END_F +#<date> server id 1 end_log_pos 2665 CRC32 XXX Update_rows: table id 32 flags: STMT_END_F ### UPDATE `test`.`t2` ### WHERE ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -267,7 +267,7 @@ BEGIN #Q> DELETE FROM t1 #<date> server id 1 end_log_pos 2873 CRC32 XXX Table_map: `test`.`t1` mapped to number num # at 2873 -#<date> server id 1 end_log_pos 2927 CRC32 XXX Delete_rows: table id 30 flags: STMT_END_F +#<date> server id 1 end_log_pos 2927 CRC32 XXX Delete_rows: table id 31 flags: STMT_END_F ### DELETE FROM `test`.`t1` ### WHERE ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ @@ -296,7 +296,7 @@ BEGIN #Q> DELETE FROM t2 #<date> server id 1 end_log_pos 3135 CRC32 XXX Table_map: `test`.`t2` mapped to number num # at 3135 -#<date> server id 1 end_log_pos 3189 CRC32 XXX Delete_rows: table id 31 flags: STMT_END_F +#<date> server id 1 end_log_pos 3189 CRC32 XXX Delete_rows: table id 32 flags: STMT_END_F ### DELETE FROM `test`.`t2` ### WHERE ### @1=10 /* INT meta=0 nullable=0 is_null=0 */ diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index ff9cc5d5c81..a2967bd5e5b 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -32,6 +32,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK mtr.global_suppressions Table is already up to date mtr.test_suppressions Table is already up to date mysql.column_stats OK @@ -66,6 +67,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template +note : Table does not support optimize, doing recreate + analyze instead +status : OK mysql.column_stats OK mysql.columns_priv OK mysql.db OK @@ -94,6 +98,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.vtmd_template OK mysql.column_stats Table is already up to date mysql.columns_priv Table is already up to date mysql.db Table is already up to date @@ -126,6 +131,9 @@ mysql.time_zone_name Table is already up to date mysql.time_zone_transition Table is already up to date mysql.time_zone_transition_type Table is already up to date mysql.user Table is already up to date +mysql.vtmd_template +note : Table does not support optimize, doing recreate + analyze instead +status : OK create table t1 (a int) engine=myisam; create view v1 as select * from t1; test.t1 OK @@ -448,6 +456,7 @@ mysql.time_zone_name Table is already up to date mysql.time_zone_transition Table is already up to date mysql.time_zone_transition_type Table is already up to date mysql.user Table is already up to date +mysql.vtmd_template OK mysqltest1.t1 warning : Table is marked as crashed warning : Size of datafile is: 4 Should be: 0 diff --git a/mysql-test/r/named_pipe.result b/mysql-test/r/named_pipe.result index 66da9a874b4..b6c409e4590 100644 --- a/mysql-test/r/named_pipe.result +++ b/mysql-test/r/named_pipe.result @@ -1,18 +1,18 @@ connect pipe_con,localhost,root,,,,,PIPE; drop table if exists t1,t2,t3,t4; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -276,8 +276,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -481,12 +481,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -600,35 +600,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1217,8 +1217,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1278,8 +1278,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1319,7 +1319,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1434,23 +1434,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1707,8 +1707,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2038,26 +2038,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/no_password_column-mdev-11170.result b/mysql-test/r/no_password_column-mdev-11170.result index 81eecc95558..7336244e9f3 100644 --- a/mysql-test/r/no_password_column-mdev-11170.result +++ b/mysql-test/r/no_password_column-mdev-11170.result @@ -42,6 +42,7 @@ Create_user_priv enum('N','Y') NO N Event_priv enum('N','Y') NO N Trigger_priv enum('N','Y') NO N Create_tablespace_priv enum('N','Y') NO N +Delete_versioning_rows_priv enum('N','Y') NO N ssl_type enum('','ANY','X509','SPECIFIED') NO ssl_cipher blob NO NULL x509_issuer blob NO NULL diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index f197fbe6a19..c57e2c2c803 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -64,10 +64,8 @@ create table MIN(a int); 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 'MIN(a int)' at line 1 create table MIN (a int); drop table MIN; -create table NOW(a int); -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 'NOW(a int)' at line 1 create table NOW (a int); -drop table NOW; +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 'NOW (a int)' at line 1 create table POSITION(a int); 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 'POSITION(a int)' at line 1 create table POSITION (a int); diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index f398ef07d56..c7d2fba95e4 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1459,7 +1459,7 @@ ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setti create table t1 (a int) partition by hash (a) (partition p0 (subpartition sp0)); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning create table t1 (a int) partition by range (a) (partition p0 values less than (1)); diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 349e9771367..94d1e384d62 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1023,7 +1023,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by key (b); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning select load_file('$MYSQLD_DATADIR/test/t1.par'); load_file('$MYSQLD_DATADIR/test/t1.par') NULL @@ -1034,7 +1034,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by key (a, b); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning select load_file('$MYSQLD_DATADIR/test/t1.par'); load_file('$MYSQLD_DATADIR/test/t1.par') NULL @@ -1045,7 +1045,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by hash (a+b); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning select load_file('$MYSQLD_DATADIR/test/t1.par'); load_file('$MYSQLD_DATADIR/test/t1.par') NULL @@ -1056,7 +1056,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by key (b); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning select load_file('$MYSQLD_DATADIR/test/t1.par'); load_file('$MYSQLD_DATADIR/test/t1.par') NULL @@ -1067,7 +1067,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by key (a, b); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning select load_file('$MYSQLD_DATADIR/test/t1.par'); load_file('$MYSQLD_DATADIR/test/t1.par') NULL @@ -1078,7 +1078,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by hash (a+b); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning select load_file('$MYSQLD_DATADIR/test/t1.par'); load_file('$MYSQLD_DATADIR/test/t1.par') NULL @@ -1135,7 +1135,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by hash (3+4); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning CREATE TABLE t1 ( a int not null, b int not null, diff --git a/mysql-test/r/pool_of_threads.result b/mysql-test/r/pool_of_threads.result index b25d8d1e50e..85ab577829a 100644 --- a/mysql-test/r/pool_of_threads.result +++ b/mysql-test/r/pool_of_threads.result @@ -2,18 +2,18 @@ SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch='outer_join_with_cache=off'; drop table if exists t1,t2,t3,t4; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -277,8 +277,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -482,12 +482,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -601,35 +601,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1218,8 +1218,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1279,8 +1279,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1320,7 +1320,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1435,23 +1435,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1708,8 +1708,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2039,26 +2039,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 4cb5bb79982..f16d2928c2e 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1207,22 +1207,25 @@ SET @aux= "SELECT COUNT(*) prepare my_stmt from @aux; execute my_stmt; COUNT(*) -46 +47 Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' execute my_stmt; COUNT(*) -46 +47 Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' execute my_stmt; COUNT(*) -46 +47 Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' deallocate prepare my_stmt; drop procedure if exists p1| drop table if exists t1| diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index c7156ddae91..bd209057b05 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -5,18 +5,18 @@ SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch=ifnull(@optimizer_switch_for_select_test,'outer_join_with_cache=off'); set join_cache_level=1; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -280,8 +280,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -485,12 +485,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -604,35 +604,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1221,8 +1221,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1282,8 +1282,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1323,7 +1323,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1435,23 +1435,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1708,8 +1708,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2039,26 +2039,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result index 92be057c62c..987290cf14a 100644 --- a/mysql-test/r/select_jcl6.result +++ b/mysql-test/r/select_jcl6.result @@ -16,18 +16,18 @@ SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch=ifnull(@optimizer_switch_for_select_test,'outer_join_with_cache=off'); set join_cache_level=@join_cache_level_for_select_test; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -291,8 +291,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -496,12 +496,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -615,35 +615,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 ALL period NULL NULL NULL 41810 Using temporary; Using filesort -1 SIMPLE t1 ref period period 4 test.t3.period 4181 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 ALL period_ NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -select period from t1; -period +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1232,8 +1232,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1293,8 +1293,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1334,7 +1334,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1446,23 +1446,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 hash_ALL NULL #hash#$hj 1 func 1199 Using where; Using join buffer (flat, BNLH join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1719,8 +1719,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2050,26 +2050,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result index c7156ddae91..bd209057b05 100644 --- a/mysql-test/r/select_pkeycache.result +++ b/mysql-test/r/select_pkeycache.result @@ -5,18 +5,18 @@ SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch=ifnull(@optimizer_switch_for_select_test,'outer_join_with_cache=off'); set join_cache_level=1; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -280,8 +280,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -485,12 +485,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -604,35 +604,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1221,8 +1221,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1282,8 +1282,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1323,7 +1323,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1435,23 +1435,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1708,8 +1708,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2039,26 +2039,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/shm.result b/mysql-test/r/shm.result index 65187b6b19b..4a2286a8104 100644 --- a/mysql-test/r/shm.result +++ b/mysql-test/r/shm.result @@ -1,18 +1,18 @@ connect shm_con,localhost,root,,,,$shm_name,SHM; drop table if exists t1,t2,t3,t4; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -276,8 +276,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -481,12 +481,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -600,35 +600,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1217,8 +1217,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1278,8 +1278,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1319,7 +1319,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1434,23 +1434,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1707,8 +1707,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2038,26 +2038,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index c6c241413d6..9a8e0422ca2 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -531,7 +531,7 @@ SET SESSION SQL_MODE = @OLD_SQL_MODE; DROP USER 'user_no_PCTFL'@'localhost'; FLUSH PRIVILEGES; SELECT * FROM mysql.db WHERE Host = 'localhost' AND User LIKE 'user_%PCTFL'; -Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv +Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv Delete_versioning_rows_priv SELECT * FROM mysql.tables_priv WHERE Host = 'localhost' AND User LIKE 'user_%PCTFL'; Host Db User Table_name Grantor Timestamp Table_priv Column_priv SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%PCTFL'; diff --git a/mysql-test/r/ssl.result b/mysql-test/r/ssl.result index 5de9e5174d8..abd4d7a5d27 100644 --- a/mysql-test/r/ssl.result +++ b/mysql-test/r/ssl.result @@ -10,18 +10,18 @@ Variable_name Value Ssl_server_not_after Apr 20 20:52:21 2037 GMT drop table if exists t1,t2,t3,t4; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -285,8 +285,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -490,12 +490,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -609,35 +609,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1226,8 +1226,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1287,8 +1287,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1328,7 +1328,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1443,23 +1443,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1716,8 +1716,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2047,26 +2047,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/ssl_compress.result b/mysql-test/r/ssl_compress.result index 4e37cc68a24..d195816caa9 100644 --- a/mysql-test/r/ssl_compress.result +++ b/mysql-test/r/ssl_compress.result @@ -7,18 +7,18 @@ Variable_name Value Compression ON drop table if exists t1,t2,t3,t4; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null auto_increment, @@ -282,8 +282,8 @@ companynr 34 29 00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period_ obliterates 9410 offload 9410 opaquely 9410 @@ -487,12 +487,12 @@ acu Ade adj create table t3 ( -period int not null, +period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), -key (period), +key (period_), key (name) ); create temporary table tmp engine = myisam select * from t3; @@ -606,35 +606,35 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +1 SIMPLE t1 ALL period_ NULL NULL NULL 41810 Using filesort +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +1 SIMPLE t3 index period_ period_ 4 NULL 1 +1 SIMPLE t1 ref period_ period_ 4 test.t3.period_ 4181 +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period +1 SIMPLE t1 index period_ period_ 4 NULL 1 +1 SIMPLE t3 ref period_ period_ 4 test.t1.period_ 4181 +select period_ from t1; +period_ 9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period +select period_ from t1 where period_=1900; +period_ +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; +fld3 period_ breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; +fld3 period_ breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period +1 SIMPLE t3 const PRIMARY,period_ PRIMARY 4 const 1 +select fld3,period_ from t2,t1 where companynr*10 = 37*10; +fld3 period_ breaking 9410 Romans 9410 intercepted 9410 @@ -1223,8 +1223,8 @@ dusted 9410 encompasses 9410 presentation 9410 Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; +fld3 period_ price price2 admonishing 1002 28357832 8723648 analyzable 1002 28357832 8723648 annihilates 1001 5987435 234724 @@ -1284,8 +1284,8 @@ ventilate 1001 5987435 234724 wallet 1001 5987435 234724 Weissmuller 1002 28357832 8723648 Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; +fld1 fld3 period_ price price2 018201 relaxing 1001 5987435 234724 018601 vacuuming 1001 5987435 234724 018801 inch 1001 5987435 234724 @@ -1325,7 +1325,7 @@ companynr companyname 65 company 9 68 company 10 select * from t1,t1 t12; -Period Varor_period Period Varor_period +Period_ Varor_period Period_ Varor_period 9410 9412 9410 9412 select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; fld1 fld1 @@ -1440,23 +1440,23 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; +fld1 companynr fld3 period_ 038008 37 reporters 1008 038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +period_ 9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); +period_ 9410 select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; fld1 @@ -1713,8 +1713,8 @@ companynr companyname count(*) select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; fld1 count(*) 158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) +select sum(Period_)/count(*) from t1; +sum(Period_)/count(*) 9410.0000 select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; companynr count sum diff func @@ -2044,26 +2044,26 @@ t2nr count(*) select max(t2nr) from t3 where price=983543950; max(t2nr) 41807 -select t1.period from t3 = t1 limit 1; -period +select t1.period_ from t3 = t1 limit 1; +period_ 1001 -select t1.period from t1 as t1 limit 1; -period +select t1.period_ from t1 as t1 limit 1; +period_ 9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +Nuvarande period_ 9410 -select period as ok_period from t1 limit 1; +select period_ as ok_period from t1 limit 1; ok_period 9410 -select period as ok_period from t1 group by ok_period limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; ok_period 9410 select 1+1 as summa from t1 group by summa limit 1; summa 2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; +Nuvarande period_ 9410 show tables; Tables_in_test diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 7ba77e60e42..58c5b460012 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -30,6 +30,7 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template show create table db; Table Create Table db CREATE TABLE `db` ( @@ -55,6 +56,7 @@ db CREATE TABLE `db` ( `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' @@ -118,6 +120,7 @@ user CREATE TABLE `user` ( `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', `ssl_cipher` blob NOT NULL, `x509_issuer` blob NOT NULL, @@ -152,7 +155,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') CHARACTER SET utf8 NOT NULL DEFAULT '', `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) diff --git a/mysql-test/r/system_mysql_db_fix40123.result b/mysql-test/r/system_mysql_db_fix40123.result index 7ba77e60e42..8f49c3265c6 100644 --- a/mysql-test/r/system_mysql_db_fix40123.result +++ b/mysql-test/r/system_mysql_db_fix40123.result @@ -30,6 +30,7 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template show create table db; Table Create Table db CREATE TABLE `db` ( @@ -55,6 +56,7 @@ db CREATE TABLE `db` ( `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' @@ -117,6 +119,7 @@ user CREATE TABLE `user` ( `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', `ssl_cipher` blob NOT NULL, @@ -152,7 +155,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') CHARACTER SET utf8 NOT NULL DEFAULT '', `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) diff --git a/mysql-test/r/system_mysql_db_fix50030.result b/mysql-test/r/system_mysql_db_fix50030.result index ad74cf6a09d..d060e33e483 100644 --- a/mysql-test/r/system_mysql_db_fix50030.result +++ b/mysql-test/r/system_mysql_db_fix50030.result @@ -30,6 +30,7 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template show create table db; Table Create Table db CREATE TABLE `db` ( @@ -55,6 +56,7 @@ db CREATE TABLE `db` ( `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' @@ -117,6 +119,7 @@ user CREATE TABLE `user` ( `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', `ssl_cipher` blob NOT NULL, @@ -152,7 +155,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') CHARACTER SET utf8 NOT NULL DEFAULT '', `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) diff --git a/mysql-test/r/system_mysql_db_fix50117.result b/mysql-test/r/system_mysql_db_fix50117.result index 7ba77e60e42..8f49c3265c6 100644 --- a/mysql-test/r/system_mysql_db_fix50117.result +++ b/mysql-test/r/system_mysql_db_fix50117.result @@ -30,6 +30,7 @@ time_zone_name time_zone_transition time_zone_transition_type user +vtmd_template show create table db; Table Create Table db CREATE TABLE `db` ( @@ -55,6 +56,7 @@ db CREATE TABLE `db` ( `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' @@ -117,6 +119,7 @@ user CREATE TABLE `user` ( `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_versioning_rows_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', `ssl_cipher` blob NOT NULL, @@ -152,7 +155,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') CHARACTER SET utf8 NOT NULL DEFAULT '', `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index dde58ed0ab2..a0683e400ef 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -1577,171 +1577,6 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; End of 5.1 tests - -# -# Bug#34828: OF is taken as OFF and a value of 0 is set for variable SQL_notes. -# - -# Checking sql_notes... -SET @sql_notes_saved = @@sql_notes; - -SET @@sql_notes = ON; -SELECT @@sql_notes; -@@sql_notes -1 - -SET @@sql_notes = OF; -ERROR 42000: Variable 'sql_notes' can't be set to the value of 'OF' -SELECT @@sql_notes; -@@sql_notes -1 - -SET @@sql_notes = OFF; -SELECT @@sql_notes; -@@sql_notes -0 - -SET @@sql_notes = @sql_notes_saved; - -# Checking delay_key_write... -SET @delay_key_write_saved = @@delay_key_write; - -SET GLOBAL delay_key_write = ON; -SELECT @@delay_key_write; -@@delay_key_write -ON - -SET GLOBAL delay_key_write = OF; -ERROR 42000: Variable 'delay_key_write' can't be set to the value of 'OF' -SELECT @@delay_key_write; -@@delay_key_write -ON - -SET GLOBAL delay_key_write = AL; -ERROR 42000: Variable 'delay_key_write' can't be set to the value of 'AL' -SELECT @@delay_key_write; -@@delay_key_write -ON - -SET GLOBAL delay_key_write = OFF; -SELECT @@delay_key_write; -@@delay_key_write -OFF - -SET GLOBAL delay_key_write = ALL; -SELECT @@delay_key_write; -@@delay_key_write -ALL - -SET GLOBAL delay_key_write = @delay_key_write_saved; - -# Checking sql_safe_updates... -SET @sql_safe_updates_saved = @@sql_safe_updates; - -SET @@sql_safe_updates = ON; -SELECT @@sql_safe_updates; -@@sql_safe_updates -1 - -SET @@sql_safe_updates = OF; -ERROR 42000: Variable 'sql_safe_updates' can't be set to the value of 'OF' -SELECT @@sql_safe_updates; -@@sql_safe_updates -1 - -SET @@sql_safe_updates = OFF; -SELECT @@sql_safe_updates; -@@sql_safe_updates -0 - -SET @@sql_safe_updates = @sql_safe_updates_saved; - -# Checking foreign_key_checks... -SET @foreign_key_checks_saved = @@foreign_key_checks; - -SET @@foreign_key_checks = ON; -SELECT @@foreign_key_checks; -@@foreign_key_checks -1 - -SET @@foreign_key_checks = OF; -ERROR 42000: Variable 'foreign_key_checks' can't be set to the value of 'OF' -SELECT @@foreign_key_checks; -@@foreign_key_checks -1 - -SET @@foreign_key_checks = OFF; -SELECT @@foreign_key_checks; -@@foreign_key_checks -0 - -SET @@foreign_key_checks = @foreign_key_checks_saved; - -# Checking unique_checks... -SET @unique_checks_saved = @@unique_checks; - -SET @@unique_checks = ON; -SELECT @@unique_checks; -@@unique_checks -1 - -SET @@unique_checks = OF; -ERROR 42000: Variable 'unique_checks' can't be set to the value of 'OF' -SELECT @@unique_checks; -@@unique_checks -1 - -SET @@unique_checks = OFF; -SELECT @@unique_checks; -@@unique_checks -0 - -SET @@unique_checks = @unique_checks_saved; - -# Checking sql_buffer_result... -SET @sql_buffer_result_saved = @@sql_buffer_result; - -SET @@sql_buffer_result = ON; -SELECT @@sql_buffer_result; -@@sql_buffer_result -1 - -SET @@sql_buffer_result = OF; -ERROR 42000: Variable 'sql_buffer_result' can't be set to the value of 'OF' -SELECT @@sql_buffer_result; -@@sql_buffer_result -1 - -SET @@sql_buffer_result = OFF; -SELECT @@sql_buffer_result; -@@sql_buffer_result -0 - -SET @@sql_buffer_result = @sql_buffer_result_saved; - -# Checking sql_quote_show_create... -SET @sql_quote_show_create_saved = @@sql_quote_show_create; - -SET @@sql_quote_show_create = ON; -SELECT @@sql_quote_show_create; -@@sql_quote_show_create -1 - -SET @@sql_quote_show_create = OF; -ERROR 42000: Variable 'sql_quote_show_create' can't be set to the value of 'OF' -SELECT @@sql_quote_show_create; -@@sql_quote_show_create -1 - -SET @@sql_quote_show_create = OFF; -SELECT @@sql_quote_show_create; -@@sql_quote_show_create -0 - -SET @@sql_quote_show_create = @sql_quote_show_create_saved; - -# End of Bug#34828. - # Make sure we can manipulate with autocommit in the # along with other variables. drop table if exists t1; diff --git a/mysql-test/suite/archive/archive.result b/mysql-test/suite/archive/archive.result index d294d3dfe58..f0ef14495fa 100644 --- a/mysql-test/suite/archive/archive.result +++ b/mysql-test/suite/archive/archive.result @@ -3,18 +3,18 @@ call mtr.add_suppression("Table 't1' is marked as crashed and should be repaired DROP TABLE if exists t1,t2,t3,t4,t5,t6; SET storage_engine=ARCHIVE; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE=archive; INSERT INTO t1 VALUES (9410,9412); -select period FROM t1; -period +select period_ FROM t1; +period_ 9410 select * FROM t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* FROM t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int, diff --git a/mysql-test/suite/archive/archive.test b/mysql-test/suite/archive/archive.test index 30f2766507e..19b46195682 100644 --- a/mysql-test/suite/archive/archive.test +++ b/mysql-test/suite/archive/archive.test @@ -15,13 +15,13 @@ SET storage_engine=ARCHIVE; let $MYSQLD_DATADIR= `SELECT @@datadir`; CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, + Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE=archive; INSERT INTO t1 VALUES (9410,9412); -select period FROM t1; +select period_ FROM t1; select * FROM t1; select t1.* FROM t1; diff --git a/mysql-test/suite/archive/disabled.def b/mysql-test/suite/archive/disabled.def new file mode 100644 index 00000000000..1aeb519e763 --- /dev/null +++ b/mysql-test/suite/archive/disabled.def @@ -0,0 +1,12 @@ +############################################################################## +# +# List the test cases that are to be disabled temporarily. +# +# Separate the test case name and the comment with ':'. +# +# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment> +# +# Do not use any TAB characters for whitespace. +# +############################################################################## +archive-big: versioning branch
\ No newline at end of file diff --git a/mysql-test/suite/binlog/r/binlog_stm_blackhole.result b/mysql-test/suite/binlog/r/binlog_stm_blackhole.result index feed949a71a..ac2b2003f30 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_blackhole.result +++ b/mysql-test/suite/binlog/r/binlog_stm_blackhole.result @@ -1,16 +1,16 @@ CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); drop table if exists t1,t2; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE=blackhole; INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ select * from t1; -Period Varor_period +Period_ Varor_period select t1.* from t1; -Period Varor_period +Period_ Varor_period CREATE TABLE t2 ( auto int NOT NULL auto_increment, fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL, diff --git a/mysql-test/suite/csv/csv.result b/mysql-test/suite/csv/csv.result index 220b84b222e..c9f7c617b40 100644 --- a/mysql-test/suite/csv/csv.result +++ b/mysql-test/suite/csv/csv.result @@ -3,18 +3,18 @@ call mtr.add_suppression("Table 'test_repair_table4' is marked as crashed and sh call mtr.add_suppression("Table 't1' is marked as crashed and should be repaired"); drop table if exists t1,t2,t3,t4; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE = CSV; INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 select * from t1; -Period Varor_period +Period_ Varor_period 9410 9412 select t1.* from t1; -Period Varor_period +Period_ Varor_period 9410 9412 CREATE TABLE t2 ( auto int not null, @@ -4919,12 +4919,12 @@ DROP TABLE t1; ALTER TABLE t2 RENAME t1; DROP TABLE t1; CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE = CSV; INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period +select period_ from t1; +period_ 9410 drop table if exists t1,t2,t3,t4; Warnings: diff --git a/mysql-test/suite/csv/csv.test b/mysql-test/suite/csv/csv.test index 3da9aca7b16..711351a32ae 100644 --- a/mysql-test/suite/csv/csv.test +++ b/mysql-test/suite/csv/csv.test @@ -17,13 +17,13 @@ drop table if exists t1,t2,t3,t4; --enable_warnings CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, + Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE = CSV; INSERT INTO t1 VALUES (9410,9412); -select period from t1; +select period_ from t1; select * from t1; select t1.* from t1; @@ -1308,13 +1308,13 @@ ALTER TABLE t2 RENAME t1; DROP TABLE t1; CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, + Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ) ENGINE = CSV; INSERT INTO t1 VALUES (9410,9412); -select period from t1; +select period_ from t1; drop table if exists t1,t2,t3,t4; diff --git a/mysql-test/suite/encryption/disabled.def b/mysql-test/suite/encryption/disabled.def index abbb82d51f6..d92d3495cb8 100644 --- a/mysql-test/suite/encryption/disabled.def +++ b/mysql-test/suite/encryption/disabled.def @@ -12,4 +12,3 @@ innodb_scrub : MDEV-8139 scrubbing does not work reliably innodb_scrub_background : MDEV-8139 scrubbing does not work reliably - diff --git a/mysql-test/suite/encryption/r/encrypt_and_grep.result b/mysql-test/suite/encryption/r/encrypt_and_grep.result index 05ebefd28b5..55309310f5e 100644 --- a/mysql-test/suite/encryption/r/encrypt_and_grep.result +++ b/mysql-test/suite/encryption/r/encrypt_and_grep.result @@ -15,6 +15,7 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_ NAME mysql/innodb_table_stats mysql/innodb_index_stats +mysql/vtmd_template test/t1 test/t2 innodb_system @@ -33,12 +34,13 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_ NAME mysql/innodb_table_stats mysql/innodb_index_stats -test/t2 +mysql/vtmd_template test/t3 innodb_system SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0; NAME test/t1 +test/t2 # t1 yes on expecting NOT FOUND NOT FOUND /foobarsecret/ in t1.ibd # t2 ... default expecting FOUND @@ -57,6 +59,7 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_ NAME mysql/innodb_table_stats mysql/innodb_index_stats +mysql/vtmd_template test/t1 test/t2 innodb_system diff --git a/mysql-test/suite/encryption/r/innodb-spatial-index.result b/mysql-test/suite/encryption/r/innodb-spatial-index.result index c2a41ac4c2e..3efea81acc8 100644 --- a/mysql-test/suite/encryption/r/innodb-spatial-index.result +++ b/mysql-test/suite/encryption/r/innodb-spatial-index.result @@ -38,6 +38,7 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_ NAME mysql/innodb_table_stats mysql/innodb_index_stats +mysql/vtmd_template test/t1 test/t2 innodb_system diff --git a/mysql-test/suite/encryption/t/debug_key_management.test b/mysql-test/suite/encryption/t/debug_key_management.test index 5001ac6a516..edc8745b5f6 100644 --- a/mysql-test/suite/encryption/t/debug_key_management.test +++ b/mysql-test/suite/encryption/t/debug_key_management.test @@ -8,13 +8,13 @@ if (`select count(*) = 0 from information_schema.plugins set global innodb_encrypt_tables=ON; show variables like 'innodb_encrypt%'; -let $wait_condition= select count(*) = 3 from information_schema.innodb_tablespaces_encryption where current_key_version=1; +let $wait_condition= select count(*) = 4 from information_schema.innodb_tablespaces_encryption where current_key_version=1; --source include/wait_condition.inc select count(*) from information_schema.innodb_tablespaces_encryption where current_key_version <> 1; set global debug_key_management_version=10; -let $wait_condition= select count(*) = 3 from information_schema.innodb_tablespaces_encryption where current_key_version=10; +let $wait_condition= select count(*) = 4 from information_schema.innodb_tablespaces_encryption where current_key_version=10; --source include/wait_condition.inc select count(*) from information_schema.innodb_tablespaces_encryption where current_key_version <> 10; diff --git a/mysql-test/suite/encryption/t/encrypt_and_grep.test b/mysql-test/suite/encryption/t/encrypt_and_grep.test index b0bf41a640d..f7a01192e33 100644 --- a/mysql-test/suite/encryption/t/encrypt_and_grep.test +++ b/mysql-test/suite/encryption/t/encrypt_and_grep.test @@ -27,7 +27,7 @@ insert t3 values (repeat('dummysecret', 12)); --echo # Wait max 10 min for key encryption threads to encrypt all spaces --let $wait_timeout= 600 ---let $wait_condition=SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 +--let $wait_condition=SELECT COUNT(*) <= 2 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 --source include/wait_condition.inc SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0; diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_03.result b/mysql-test/suite/funcs_1/r/innodb_trig_03.result index 98f599da3e5..7666b86bc94 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_03.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_03.result @@ -78,7 +78,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke TRIGGER on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.t1 to test_yesprivs@localhost; @@ -168,7 +168,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke UPDATE on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER, UPDATE on *.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; @@ -183,7 +183,7 @@ test_noprivs@localhost use priv_db; show grants; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' select f1 from t1 order by f1; f1 insert 3.5.3.2-no @@ -248,7 +248,7 @@ connection no_privs_424b; show grants; Grants for test_noprivs@localhost GRANT USAGE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' use priv_db; create trigger trg4b_1 before UPDATE on t1 for each row set new.f1 = 'trig 3.5.3.7-1b'; @@ -329,7 +329,7 @@ connection no_privs_424c; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' use priv_db; create trigger trg4c_1 before INSERT on t1 for each row set new.f1 = 'trig 3.5.3.7-1c'; @@ -441,7 +441,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke SELECT on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER, SELECT on *.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; @@ -457,7 +457,7 @@ test_noprivs@localhost use priv_db; show grants; Grants for test_noprivs@localhost -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' create trigger trg5a_1 before INSERT on t1 for each row set @test_var = new.f1; connection default; @@ -503,7 +503,7 @@ revoke SELECT on priv_db.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.* to test_yesprivs@localhost; @@ -518,7 +518,7 @@ connection no_privs_425b; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' use priv_db; create trigger trg5b_1 before UPDATE on t1 for each row set @test_var= new.f1; @@ -565,7 +565,7 @@ revoke SELECT on priv_db.t1 from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.t1 to test_yesprivs@localhost; @@ -580,7 +580,7 @@ connection no_privs_425c; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' use priv_db; create trigger trg5c_1 before INSERT on t1 for each row set @test_var= new.f1; diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_03e.result b/mysql-test/suite/funcs_1/r/innodb_trig_03e.result index b29c0271fdc..90dabe044e8 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_03e.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_03e.result @@ -603,7 +603,7 @@ trig 1_1-yes revoke TRIGGER on *.* from test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' disconnect yes_privs; connect yes_privs,localhost,test_yesprivs,PWD,test,$MASTER_MYPORT,$MASTER_MYSOCK; select current_user; @@ -656,7 +656,7 @@ root@localhost grant TRIGGER on priv_db.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' GRANT TRIGGER ON `priv_db`.* TO 'test_yesprivs'@'localhost' trigger privilege on db level for create: @@ -929,7 +929,7 @@ grant TRIGGER on priv1_db.t1 to test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost GRANT USAGE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT ON `priv1_db`.* TO 'test_yesprivs'@'localhost' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, DELETE VERSIONING ROWS ON `priv1_db`.* TO 'test_yesprivs'@'localhost' GRANT SELECT, UPDATE ON `priv2_db`.* TO 'test_yesprivs'@'localhost' GRANT TRIGGER ON `priv1_db`.`t1` TO 'test_yesprivs'@'localhost' diff --git a/mysql-test/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result index 5a27cb65b3d..7468d5db0be 100644 --- a/mysql-test/suite/funcs_1/r/innodb_views.result +++ b/mysql-test/suite/funcs_1/r/innodb_views.result @@ -3551,11 +3551,11 @@ CREATE VIEW v1 or REPLACE AS Select * from tb2 my_table; 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 'or REPLACE AS Select * from tb2 my_table' at line 1 CREATE VIEW v1 WITH CASCADED CHECK OPTION AS Select * from tb2 my_table limit 50; -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 'CASCADED CHECK OPTION AS Select * +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 'WITH CASCADED CHECK OPTION AS Select * from tb2 my_table limit 50' at line 1 CREATE VIEW v1 WITH LOCAL CHECK OPTION AS Select * from tb2 my_table limit 50; -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 'LOCAL CHECK OPTION AS Select * +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 'WITH LOCAL CHECK OPTION AS Select * from tb2 my_table limit 50' at line 1 SELECT * FROM tb2 my_table CREATE VIEW As v1; 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 'CREATE VIEW As v1' at line 1 @@ -3585,7 +3585,7 @@ FROM test.tb2 my_table CHECK OPTION WITH CASCADED; 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 'CHECK OPTION WITH CASCADED' at line 2 CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table; -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 'CASCADED CHECK OPTION +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 'WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table' at line 1 CREATE OR REPLACE AS SELECT F59, F60 FROM test.tb2 my_table VIEW v1 WITH CASCADED CHECK OPTION; @@ -3614,7 +3614,7 @@ FROM test.tb2 my_table CHECK OPTION WITH LOCAL; 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 'CHECK OPTION WITH LOCAL' at line 2 CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table; -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 'CASCADED CHECK OPTION +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 'WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table' at line 1 CREATE OR REPLACE AS SELECT F59, F60 FROM test.tb2 my_table VIEW v1 WITH LOCAL CHECK OPTION; diff --git a/mysql-test/suite/funcs_1/r/is_column_privileges.result b/mysql-test/suite/funcs_1/r/is_column_privileges.result index a56ef002935..033fb64f689 100644 --- a/mysql-test/suite/funcs_1/r/is_column_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_column_privileges.result @@ -140,6 +140,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE 'testuser3'@'localhost' def db_datadict CREATE TEMPORARY TABLES NO 'testuser3'@'localhost' def db_datadict CREATE VIEW NO 'testuser3'@'localhost' def db_datadict DELETE NO +'testuser3'@'localhost' def db_datadict DELETE VERSIONING ROWS NO 'testuser3'@'localhost' def db_datadict DROP NO 'testuser3'@'localhost' def db_datadict EVENT NO 'testuser3'@'localhost' def db_datadict EXECUTE NO diff --git a/mysql-test/suite/funcs_1/r/is_columns.result b/mysql-test/suite/funcs_1/r/is_columns.result index 982f4de5116..f1c784e2839 100644 --- a/mysql-test/suite/funcs_1/r/is_columns.result +++ b/mysql-test/suite/funcs_1/r/is_columns.result @@ -106,6 +106,7 @@ table_catalog table_schema table_name column_name Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' ############################################################################### # Testcase 3.2.6.2 + 3.2.6.3: INFORMATION_SCHEMA.COLUMNS accessible information ############################################################################### diff --git a/mysql-test/suite/funcs_1/r/is_key_column_usage.result b/mysql-test/suite/funcs_1/r/is_key_column_usage.result index fa2a738788e..84a226dd0ef 100644 --- a/mysql-test/suite/funcs_1/r/is_key_column_usage.result +++ b/mysql-test/suite/funcs_1/r/is_key_column_usage.result @@ -143,6 +143,7 @@ def mysql PRIMARY def mysql time_zone_transition_type Time_zone_id def mysql PRIMARY def mysql time_zone_transition_type Transition_type_id def mysql PRIMARY def mysql user Host def mysql PRIMARY def mysql user User +def mysql PRIMARY def mysql vtmd_template end ######################################################################################## # Testcase 3.2.7.2 + 3.2.7.3: INFORMATION_SCHEMA.KEY_COLUMN_USAGE accessible information ######################################################################################## diff --git a/mysql-test/suite/funcs_1/r/is_schema_privileges.result b/mysql-test/suite/funcs_1/r/is_schema_privileges.result index cf9b70308de..1339639106f 100644 --- a/mysql-test/suite/funcs_1/r/is_schema_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_schema_privileges.result @@ -68,6 +68,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE ''@'%' def test CREATE ROUTINE ''@'%' def test EVENT ''@'%' def test TRIGGER +''@'%' def test DELETE VERSIONING ROWS ''@'%' def test\_% SELECT ''@'%' def test\_% INSERT ''@'%' def test\_% UPDATE @@ -84,6 +85,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE ''@'%' def test\_% CREATE ROUTINE ''@'%' def test\_% EVENT ''@'%' def test\_% TRIGGER +''@'%' def test\_% DELETE VERSIONING ROWS ############################################################################### # Testcase 3.2.15.2-3.2.15.4 INFORMATION_SCHEMA.SCHEMA_PRIVILEGES accessibility ############################################################################### diff --git a/mysql-test/suite/funcs_1/r/is_schema_privileges_is_mysql_test.result b/mysql-test/suite/funcs_1/r/is_schema_privileges_is_mysql_test.result index 38257899a4b..528a770e0eb 100644 --- a/mysql-test/suite/funcs_1/r/is_schema_privileges_is_mysql_test.result +++ b/mysql-test/suite/funcs_1/r/is_schema_privileges_is_mysql_test.result @@ -16,6 +16,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE ''@'%' def test CREATE TEMPORARY TABLES NO ''@'%' def test CREATE VIEW NO ''@'%' def test DELETE NO +''@'%' def test DELETE VERSIONING ROWS NO ''@'%' def test DROP NO ''@'%' def test EVENT NO ''@'%' def test INDEX NO diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result index 749b09fa87d..8f82c04e3da 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics.result +++ b/mysql-test/suite/funcs_1/r/is_statistics.result @@ -154,6 +154,7 @@ def mysql user mysql PRIMARY Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' #################################################################################### # Testcase 3.2.14.2 + 3.2.14.3: INFORMATION_SCHEMA.STATISTICS accessible information #################################################################################### diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result index dc3ed5f9839..b5f9096aa47 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result @@ -79,6 +79,8 @@ def mysql time_zone_transition_type 0 mysql PRIMARY 1 Time_zone_id A #CARD# NULL def mysql time_zone_transition_type 0 mysql PRIMARY 2 Transition_type_id A #CARD# NULL NULL BTREE def mysql user 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE def mysql user 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE +def mysql vtmd_template 1 mysql archive_name 1 archive_name A #CARD# NULL NULL YES BTREE +def mysql vtmd_template 0 mysql PRIMARY 1 end A #CARD# NULL NULL BTREE connect testuser1,localhost,testuser1,,db_datadict; SELECT * FROM information_schema.statistics WHERE table_schema = 'mysql' diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints.result b/mysql-test/suite/funcs_1/r/is_table_constraints.result index 0553b4344c8..bd55e1c0b10 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result @@ -88,6 +88,7 @@ def mysql PRIMARY mysql time_zone_name def mysql PRIMARY mysql time_zone_transition def mysql PRIMARY mysql time_zone_transition_type def mysql PRIMARY mysql user +def mysql PRIMARY mysql vtmd_template ######################################################################################### # Testcase 3.2.7.2 + 3.2.7.3: INFORMATION_SCHEMA.TABLE_CONSTRAINTS accessible information ######################################################################################### diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result index e54de0671a2..9998f99ab1b 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result @@ -38,6 +38,7 @@ def mysql PRIMARY mysql time_zone_name PRIMARY KEY def mysql PRIMARY mysql time_zone_transition PRIMARY KEY def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY def mysql PRIMARY mysql user PRIMARY KEY +def mysql PRIMARY mysql vtmd_template PRIMARY KEY connect testuser1,localhost,testuser1,,db_datadict; SELECT * FROM information_schema.table_constraints WHERE table_schema = 'mysql' diff --git a/mysql-test/suite/funcs_1/r/is_table_privileges.result b/mysql-test/suite/funcs_1/r/is_table_privileges.result index 340aead9aba..c448241e14e 100644 --- a/mysql-test/suite/funcs_1/r/is_table_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_table_privileges.result @@ -96,6 +96,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE 'testuser2'@'localhost' def db_datadict tb1 CREATE YES 'testuser2'@'localhost' def db_datadict tb1 CREATE VIEW YES 'testuser2'@'localhost' def db_datadict tb1 DELETE YES +'testuser2'@'localhost' def db_datadict tb1 DELETE VERSIONING ROWS YES 'testuser2'@'localhost' def db_datadict tb1 DROP YES 'testuser2'@'localhost' def db_datadict tb1 INDEX YES 'testuser2'@'localhost' def db_datadict tb1 INSERT YES @@ -131,6 +132,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE 'testuser2'@'localhost' def db_datadict tb1 CREATE YES 'testuser2'@'localhost' def db_datadict tb1 CREATE VIEW YES 'testuser2'@'localhost' def db_datadict tb1 DELETE YES +'testuser2'@'localhost' def db_datadict tb1 DELETE VERSIONING ROWS YES 'testuser2'@'localhost' def db_datadict tb1 DROP YES 'testuser2'@'localhost' def db_datadict tb1 INDEX YES 'testuser2'@'localhost' def db_datadict tb1 INSERT YES @@ -184,6 +186,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE 'testuser1'@'localhost' def test t1_table CREATE NO 'testuser1'@'localhost' def test t1_table CREATE VIEW NO 'testuser1'@'localhost' def test t1_table DELETE NO +'testuser1'@'localhost' def test t1_table DELETE VERSIONING ROWS NO 'testuser1'@'localhost' def test t1_table DROP NO 'testuser1'@'localhost' def test t1_table INDEX NO 'testuser1'@'localhost' def test t1_table INSERT NO @@ -196,6 +199,7 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE 'testuser1'@'localhost' def test t1_view CREATE NO 'testuser1'@'localhost' def test t1_view CREATE VIEW NO 'testuser1'@'localhost' def test t1_view DELETE NO +'testuser1'@'localhost' def test t1_view DELETE VERSIONING ROWS NO 'testuser1'@'localhost' def test t1_view DROP NO 'testuser1'@'localhost' def test t1_view INDEX NO 'testuser1'@'localhost' def test t1_view INSERT NO diff --git a/mysql-test/suite/funcs_1/r/is_tables_mysql.result b/mysql-test/suite/funcs_1/r/is_tables_mysql.result index 8e0c9b64dab..704bb51f70a 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_tables_mysql.result @@ -700,6 +700,29 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# user_comment Users and global privileges Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA mysql +TABLE_NAME vtmd_template +TABLE_TYPE BASE TABLE +ENGINE InnoDB +VERSION 10 +ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_bin +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment +Separator ----------------------------------------------------- DROP USER testuser1@localhost; CREATE USER testuser1@localhost; GRANT SELECT ON test1.* TO testuser1@localhost; diff --git a/mysql-test/suite/funcs_1/r/is_triggers.result b/mysql-test/suite/funcs_1/r/is_triggers.result index 8e5842742cb..2eb352ceb07 100644 --- a/mysql-test/suite/funcs_1/r/is_triggers.result +++ b/mysql-test/suite/funcs_1/r/is_triggers.result @@ -144,7 +144,7 @@ connect testuser2, localhost, testuser2, , db_datadict; SHOW GRANTS FOR 'testuser2'@'localhost'; Grants for testuser2@localhost GRANT USAGE ON *.* TO 'testuser2'@'localhost' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW ON `db_datadict`.`t1` TO 'testuser2'@'localhost' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, DELETE VERSIONING ROWS ON `db_datadict`.`t1` TO 'testuser2'@'localhost' # No TRIGGER Privilege --> no result for query SELECT * FROM information_schema.triggers WHERE trigger_name = 'trg1'; diff --git a/mysql-test/suite/funcs_1/r/is_user_privileges.result b/mysql-test/suite/funcs_1/r/is_user_privileges.result index a300a1f73e7..655b6d9e209 100644 --- a/mysql-test/suite/funcs_1/r/is_user_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result @@ -119,6 +119,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -165,6 +166,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -211,6 +213,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -281,6 +284,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -327,6 +331,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -373,6 +378,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -429,6 +435,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -475,6 +482,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -521,6 +529,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -599,6 +608,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -645,6 +655,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -691,6 +702,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -761,6 +773,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -807,6 +820,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -853,6 +867,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -909,6 +924,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -955,6 +971,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1001,6 +1018,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1109,6 +1127,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1155,6 +1174,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1201,6 +1221,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1304,6 +1325,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1350,6 +1372,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1396,6 +1419,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1452,6 +1476,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1498,6 +1523,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1544,6 +1570,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1607,6 +1634,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1653,6 +1681,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1699,6 +1728,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1777,6 +1807,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1823,6 +1854,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer @@ -1869,6 +1901,7 @@ Create_user_priv N Event_priv N Trigger_priv N Create_tablespace_priv N +Delete_versioning_rows_priv N ssl_type ssl_cipher x509_issuer diff --git a/mysql-test/suite/funcs_1/r/memory_trig_03.result b/mysql-test/suite/funcs_1/r/memory_trig_03.result index 8fd3e034735..b86315a1a7d 100644 --- a/mysql-test/suite/funcs_1/r/memory_trig_03.result +++ b/mysql-test/suite/funcs_1/r/memory_trig_03.result @@ -78,7 +78,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke TRIGGER on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.t1 to test_yesprivs@localhost; @@ -168,7 +168,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke UPDATE on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER, UPDATE on *.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; @@ -183,7 +183,7 @@ test_noprivs@localhost use priv_db; show grants; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' select f1 from t1 order by f1; f1 insert 3.5.3.2-no @@ -248,7 +248,7 @@ connection no_privs_424b; show grants; Grants for test_noprivs@localhost GRANT USAGE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' use priv_db; create trigger trg4b_1 before UPDATE on t1 for each row set new.f1 = 'trig 3.5.3.7-1b'; @@ -329,7 +329,7 @@ connection no_privs_424c; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' use priv_db; create trigger trg4c_1 before INSERT on t1 for each row set new.f1 = 'trig 3.5.3.7-1c'; @@ -441,7 +441,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke SELECT on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER, SELECT on *.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; @@ -457,7 +457,7 @@ test_noprivs@localhost use priv_db; show grants; Grants for test_noprivs@localhost -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' create trigger trg5a_1 before INSERT on t1 for each row set @test_var = new.f1; connection default; @@ -503,7 +503,7 @@ revoke SELECT on priv_db.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.* to test_yesprivs@localhost; @@ -518,7 +518,7 @@ connection no_privs_425b; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' use priv_db; create trigger trg5b_1 before UPDATE on t1 for each row set @test_var= new.f1; @@ -565,7 +565,7 @@ revoke SELECT on priv_db.t1 from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.t1 to test_yesprivs@localhost; @@ -580,7 +580,7 @@ connection no_privs_425c; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' use priv_db; create trigger trg5c_1 before INSERT on t1 for each row set @test_var= new.f1; diff --git a/mysql-test/suite/funcs_1/r/memory_trig_03e.result b/mysql-test/suite/funcs_1/r/memory_trig_03e.result index 83c36c6294f..ea0aaf0c86f 100644 --- a/mysql-test/suite/funcs_1/r/memory_trig_03e.result +++ b/mysql-test/suite/funcs_1/r/memory_trig_03e.result @@ -604,7 +604,7 @@ trig 1_1-yes revoke TRIGGER on *.* from test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' disconnect yes_privs; connect yes_privs,localhost,test_yesprivs,PWD,test,$MASTER_MYPORT,$MASTER_MYSOCK; select current_user; @@ -657,7 +657,7 @@ root@localhost grant TRIGGER on priv_db.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' GRANT TRIGGER ON `priv_db`.* TO 'test_yesprivs'@'localhost' trigger privilege on db level for create: @@ -930,7 +930,7 @@ grant TRIGGER on priv1_db.t1 to test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost GRANT USAGE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT ON `priv1_db`.* TO 'test_yesprivs'@'localhost' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, DELETE VERSIONING ROWS ON `priv1_db`.* TO 'test_yesprivs'@'localhost' GRANT SELECT, UPDATE ON `priv2_db`.* TO 'test_yesprivs'@'localhost' GRANT TRIGGER ON `priv1_db`.`t1` TO 'test_yesprivs'@'localhost' diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result index a2af9082c72..4c422d600bf 100644 --- a/mysql-test/suite/funcs_1/r/memory_views.result +++ b/mysql-test/suite/funcs_1/r/memory_views.result @@ -3552,11 +3552,11 @@ CREATE VIEW v1 or REPLACE AS Select * from tb2 my_table; 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 'or REPLACE AS Select * from tb2 my_table' at line 1 CREATE VIEW v1 WITH CASCADED CHECK OPTION AS Select * from tb2 my_table limit 50; -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 'CASCADED CHECK OPTION AS Select * +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 'WITH CASCADED CHECK OPTION AS Select * from tb2 my_table limit 50' at line 1 CREATE VIEW v1 WITH LOCAL CHECK OPTION AS Select * from tb2 my_table limit 50; -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 'LOCAL CHECK OPTION AS Select * +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 'WITH LOCAL CHECK OPTION AS Select * from tb2 my_table limit 50' at line 1 SELECT * FROM tb2 my_table CREATE VIEW As v1; 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 'CREATE VIEW As v1' at line 1 @@ -3586,7 +3586,7 @@ FROM test.tb2 my_table CHECK OPTION WITH CASCADED; 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 'CHECK OPTION WITH CASCADED' at line 2 CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table; -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 'CASCADED CHECK OPTION +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 'WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table' at line 1 CREATE OR REPLACE AS SELECT F59, F60 FROM test.tb2 my_table VIEW v1 WITH CASCADED CHECK OPTION; @@ -3615,7 +3615,7 @@ FROM test.tb2 my_table CHECK OPTION WITH LOCAL; 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 'CHECK OPTION WITH LOCAL' at line 2 CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table; -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 'CASCADED CHECK OPTION +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 'WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table' at line 1 CREATE OR REPLACE AS SELECT F59, F60 FROM test.tb2 my_table VIEW v1 WITH LOCAL CHECK OPTION; diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_03.result b/mysql-test/suite/funcs_1/r/myisam_trig_03.result index 8fd3e034735..b86315a1a7d 100644 --- a/mysql-test/suite/funcs_1/r/myisam_trig_03.result +++ b/mysql-test/suite/funcs_1/r/myisam_trig_03.result @@ -78,7 +78,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke TRIGGER on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.t1 to test_yesprivs@localhost; @@ -168,7 +168,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke UPDATE on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER, UPDATE on *.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; @@ -183,7 +183,7 @@ test_noprivs@localhost use priv_db; show grants; Grants for test_noprivs@localhost -GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' select f1 from t1 order by f1; f1 insert 3.5.3.2-no @@ -248,7 +248,7 @@ connection no_privs_424b; show grants; Grants for test_noprivs@localhost GRANT USAGE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' use priv_db; create trigger trg4b_1 before UPDATE on t1 for each row set new.f1 = 'trig 3.5.3.7-1b'; @@ -329,7 +329,7 @@ connection no_privs_424c; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT SELECT, INSERT, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' use priv_db; create trigger trg4c_1 before INSERT on t1 for each row set new.f1 = 'trig 3.5.3.7-1c'; @@ -441,7 +441,7 @@ grant ALL on *.* to test_noprivs@localhost; revoke SELECT on *.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER, SELECT on *.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; @@ -457,7 +457,7 @@ test_noprivs@localhost use priv_db; show grants; Grants for test_noprivs@localhost -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' create trigger trg5a_1 before INSERT on t1 for each row set @test_var = new.f1; connection default; @@ -503,7 +503,7 @@ revoke SELECT on priv_db.* from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.* to test_yesprivs@localhost; @@ -518,7 +518,7 @@ connection no_privs_425b; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `priv_db`.* TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.* TO 'test_noprivs'@'localhost' use priv_db; create trigger trg5b_1 before UPDATE on t1 for each row set @test_var= new.f1; @@ -565,7 +565,7 @@ revoke SELECT on priv_db.t1 from test_noprivs@localhost; show grants for test_noprivs@localhost; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost; grant TRIGGER on *.* to test_yesprivs@localhost; grant SELECT on priv_db.t1 to test_yesprivs@localhost; @@ -580,7 +580,7 @@ connection no_privs_425c; show grants; Grants for test_noprivs@localhost GRANT TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' +GRANT INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE VIEW, SHOW VIEW, TRIGGER, DELETE VERSIONING ROWS ON `priv_db`.`t1` TO 'test_noprivs'@'localhost' use priv_db; create trigger trg5c_1 before INSERT on t1 for each row set @test_var= new.f1; diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_03e.result b/mysql-test/suite/funcs_1/r/myisam_trig_03e.result index a4db9050c86..60e6031f0e2 100644 --- a/mysql-test/suite/funcs_1/r/myisam_trig_03e.result +++ b/mysql-test/suite/funcs_1/r/myisam_trig_03e.result @@ -604,7 +604,7 @@ trig 1_1-yes revoke TRIGGER on *.* from test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' disconnect yes_privs; connect yes_privs,localhost,test_yesprivs,PWD,test,$MASTER_MYPORT,$MASTER_MYSOCK; select current_user; @@ -657,7 +657,7 @@ root@localhost grant TRIGGER on priv_db.* to test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE, DELETE VERSIONING ROWS ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' GRANT TRIGGER ON `priv_db`.* TO 'test_yesprivs'@'localhost' trigger privilege on db level for create: @@ -930,7 +930,7 @@ grant TRIGGER on priv1_db.t1 to test_yesprivs@localhost; show grants for test_yesprivs@localhost; Grants for test_yesprivs@localhost GRANT USAGE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT ON `priv1_db`.* TO 'test_yesprivs'@'localhost' +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, DELETE VERSIONING ROWS ON `priv1_db`.* TO 'test_yesprivs'@'localhost' GRANT SELECT, UPDATE ON `priv2_db`.* TO 'test_yesprivs'@'localhost' GRANT TRIGGER ON `priv1_db`.`t1` TO 'test_yesprivs'@'localhost' diff --git a/mysql-test/suite/funcs_1/r/myisam_views-big.result b/mysql-test/suite/funcs_1/r/myisam_views-big.result index 3290b3dd36a..36c99148020 100644 --- a/mysql-test/suite/funcs_1/r/myisam_views-big.result +++ b/mysql-test/suite/funcs_1/r/myisam_views-big.result @@ -4054,11 +4054,11 @@ CREATE VIEW v1 or REPLACE AS Select * from tb2 my_table; 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 'or REPLACE AS Select * from tb2 my_table' at line 1 CREATE VIEW v1 WITH CASCADED CHECK OPTION AS Select * from tb2 my_table limit 50; -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 'CASCADED CHECK OPTION AS Select * +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 'WITH CASCADED CHECK OPTION AS Select * from tb2 my_table limit 50' at line 1 CREATE VIEW v1 WITH LOCAL CHECK OPTION AS Select * from tb2 my_table limit 50; -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 'LOCAL CHECK OPTION AS Select * +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 'WITH LOCAL CHECK OPTION AS Select * from tb2 my_table limit 50' at line 1 SELECT * FROM tb2 my_table CREATE VIEW As v1; 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 'CREATE VIEW As v1' at line 1 @@ -4088,7 +4088,7 @@ FROM test.tb2 my_table CHECK OPTION WITH CASCADED; 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 'CHECK OPTION WITH CASCADED' at line 2 CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table; -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 'CASCADED CHECK OPTION +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 'WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table' at line 1 CREATE OR REPLACE AS SELECT F59, F60 FROM test.tb2 my_table VIEW v1 WITH CASCADED CHECK OPTION; @@ -4117,7 +4117,7 @@ FROM test.tb2 my_table CHECK OPTION WITH LOCAL; 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 'CHECK OPTION WITH LOCAL' at line 2 CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table; -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 'CASCADED CHECK OPTION +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 'WITH CASCADED CHECK OPTION AS SELECT F59, F60 FROM test.tb2 my_table' at line 1 CREATE OR REPLACE AS SELECT F59, F60 FROM test.tb2 my_table VIEW v1 WITH LOCAL CHECK OPTION; diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result index 2c86e6c3e73..29d3b23211b 100644 --- a/mysql-test/suite/funcs_1/r/storedproc.result +++ b/mysql-test/suite/funcs_1/r/storedproc.result @@ -2807,7 +2807,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp SELECT * from t1 where f2=f1' at line 1 CREATE PROCEDURE with() SELECT * from t1 where f2=f1; -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 '() +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 'with() SELECT * from t1 where f2=f1' at line 1 CREATE PROCEDURE write() SELECT * from t1 where f2=f1; @@ -9222,7 +9222,7 @@ CREATE PROCEDURE sp1() BEGIN declare with char; END// -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 'char; +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 'with char; END' at line 3 DROP PROCEDURE IF EXISTS sp1; Warnings: @@ -11574,9 +11574,8 @@ BEGIN declare with condition for sqlstate '02000'; declare exit handler for with set @var2 = 1; END// -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 'condition for sqlstate '02000'; -declare exit handler for with set @var2 = 1; -END' at line 3 +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 'with condition for sqlstate '02000'; +declare exit handler for with set @var2 = 1' at line 3 DROP PROCEDURE IF EXISTS sp1; Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist @@ -13680,7 +13679,7 @@ CREATE PROCEDURE sp1( ) BEGIN declare with handler for sqlstate '02000' set @var2 = 1; END// -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 'handler for sqlstate '02000' set @var2 = 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 'with handler for sqlstate '02000' set @var2 = 1; END' at line 3 DROP PROCEDURE IF EXISTS sp1; Warnings: diff --git a/mysql-test/suite/handler/disabled.def b/mysql-test/suite/handler/disabled.def index 888298bbb09..1f648e74b06 100644 --- a/mysql-test/suite/handler/disabled.def +++ b/mysql-test/suite/handler/disabled.def @@ -9,3 +9,6 @@ # Do not use any TAB characters for whitespace. # ############################################################################## + +wl6501_1: versioning branch +wl6501_crash_3: versioning branch diff --git a/mysql-test/suite/innodb/t/innodb_skip_innodb_is_tables.test b/mysql-test/suite/innodb/t/innodb_skip_innodb_is_tables.test index 01ced047302..4954191d74a 100644 --- a/mysql-test/suite/innodb/t/innodb_skip_innodb_is_tables.test +++ b/mysql-test/suite/innodb/t/innodb_skip_innodb_is_tables.test @@ -1,4 +1,5 @@ --source include/not_embedded.inc +--source include/have_xtradb.inc select * from information_schema.innodb_trx; select * from information_schema.innodb_locks; diff --git a/mysql-test/suite/innodb_fts/r/fulltext.result b/mysql-test/suite/innodb_fts/r/fulltext.result index 42e294b3293..fcf196a0631 100644 --- a/mysql-test/suite/innodb_fts/r/fulltext.result +++ b/mysql-test/suite/innodb_fts/r/fulltext.result @@ -56,7 +56,7 @@ Only MyISAM tables support collections MySQL has now support for full-text search Full-text search in MySQL implements vector space model select * from t1 where MATCH(a,b) AGAINST ("indexes" IN BOOLEAN MODE WITH QUERY EXPANSION); -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 'QUERY EXPANSION)' at line 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 'WITH QUERY EXPANSION)' at line 1 explain select * from t1 where MATCH(a,b) AGAINST ("collections"); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 fulltext a a 0 1 Using where diff --git a/mysql-test/suite/parts/r/partition_syntax_innodb.result b/mysql-test/suite/parts/r/partition_syntax_innodb.result index a5d257f64e0..cc53aaff426 100644 --- a/mysql-test/suite/parts/r/partition_syntax_innodb.result +++ b/mysql-test/suite/parts/r/partition_syntax_innodb.result @@ -510,7 +510,7 @@ f_charbig VARCHAR(1000) ) PARTITION BY RANGE(f_int1) ( PARTITION part1 VALUES LESS THAN (1000) (SUBPARTITION subpart11)); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning #------------------------------------------------------------------------ # 2.2 Every partition must have the same number of subpartitions. # This is a limitation of MySQL 5.1, which could be removed in diff --git a/mysql-test/suite/parts/r/partition_syntax_myisam.result b/mysql-test/suite/parts/r/partition_syntax_myisam.result index 765280f35c6..58d3a6f593e 100644 --- a/mysql-test/suite/parts/r/partition_syntax_myisam.result +++ b/mysql-test/suite/parts/r/partition_syntax_myisam.result @@ -510,7 +510,7 @@ f_charbig VARCHAR(1000) ) PARTITION BY RANGE(f_int1) ( PARTITION part1 VALUES LESS THAN (1000) (SUBPARTITION subpart11)); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning #------------------------------------------------------------------------ # 2.2 Every partition must have the same number of subpartitions. # This is a limitation of MySQL 5.1, which could be removed in diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result index 1a269d72eb7..afe00ed7729 100644 --- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result +++ b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result @@ -5,7 +5,7 @@ alter table user drop column default_role; alter table user drop column max_statement_time; flush privileges; create role test_role; -ERROR HY000: Column count of mysql.user is wrong. Expected 44, found 43. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error +ERROR HY000: Column count of mysql.user is wrong. Expected 45, found 44. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error drop role test_role; ERROR HY000: Operation DROP ROLE failed for 'test_role' alter table user add column is_role enum('N', 'Y') default 'N' not null @@ -15,7 +15,7 @@ create role test_role; create user test_user@localhost; grant test_role to test_user@localhost; set default role test_role for root@localhost; -ERROR HY000: Column count of mysql.user is wrong. Expected 45, found 44. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error +ERROR HY000: Column count of mysql.user is wrong. Expected 46, found 45. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error drop role test_role; drop user test_user@localhost; alter table user add column default_role char(80) binary default '' not null diff --git a/mysql-test/suite/roles/set_role-recursive.result b/mysql-test/suite/roles/set_role-recursive.result index 53b28a25261..9cea63de3bf 100644 --- a/mysql-test/suite/roles/set_role-recursive.result +++ b/mysql-test/suite/roles/set_role-recursive.result @@ -16,11 +16,11 @@ Host User Role Admin_option test_role1 test_role2 N grant select on *.* to test_role2; select * from mysql.user where user like 'test_role1'; -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 - test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 +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 Delete_versioning_rows_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 + test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 select * from mysql.user where user like 'test_role2'; -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 - test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 +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 Delete_versioning_rows_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 + test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 select * from mysql.roles_mapping; ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping' show grants; diff --git a/mysql-test/suite/roles/set_role-simple.result b/mysql-test/suite/roles/set_role-simple.result index 29b176776e7..c26f06d1bfe 100644 --- a/mysql-test/suite/roles/set_role-simple.result +++ b/mysql-test/suite/roles/set_role-simple.result @@ -11,8 +11,8 @@ localhost root test_role1 Y localhost test_user test_role1 N grant select on *.* to test_role1; select * from mysql.user where user='test_role1'; -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 - test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 +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 Delete_versioning_rows_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 + test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 select * from mysql.roles_mapping; ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping' show grants; diff --git a/mysql-test/suite/sys_vars/r/delay_key_write_basic.result b/mysql-test/suite/sys_vars/r/delay_key_write_basic.result index 2258d7af078..7299737f63b 100644 --- a/mysql-test/suite/sys_vars/r/delay_key_write_basic.result +++ b/mysql-test/suite/sys_vars/r/delay_key_write_basic.result @@ -37,8 +37,8 @@ SET @@global.delay_key_write = FALSE0; ERROR 42000: Variable 'delay_key_write' can't be set to the value of 'FALSE0' SET @@global.delay_key_write = ONN; ERROR 42000: Variable 'delay_key_write' can't be set to the value of 'ONN' -SET @@global.delay_key_write = OF; -ERROR 42000: Variable 'delay_key_write' can't be set to the value of 'OF' +SET @@global.delay_key_write = OFFF; +ERROR 42000: Variable 'delay_key_write' can't be set to the value of 'OFFF' SET @@global.delay_key_write = ' '; ERROR 42000: Variable 'delay_key_write' can't be set to the value of ' ' SET @@global.delay_key_write = ""; diff --git a/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result b/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result index 834d693edb8..f33ef34a62a 100644 --- a/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result +++ b/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result @@ -43,8 +43,8 @@ SET @@session.foreign_key_checks = TRÜE; ERROR 42000: Variable 'foreign_key_checks' can't be set to the value of 'TRÜE' SET @@session.foreign_key_checks = ÕN; ERROR 42000: Variable 'foreign_key_checks' can't be set to the value of 'ÕN' -SET @@session.foreign_key_checks = OF; -ERROR 42000: Variable 'foreign_key_checks' can't be set to the value of 'OF' +SET @@session.foreign_key_checks = OFFF; +ERROR 42000: Variable 'foreign_key_checks' can't be set to the value of 'OFFF' SET @@session.foreign_key_checks = ÓFF; ERROR 42000: Variable 'foreign_key_checks' can't be set to the value of 'ÓFF' SET @@session.foreign_key_checks = '¹'; diff --git a/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result b/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result index 08dc5d7aaca..aec529aece2 100644 --- a/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result @@ -66,7 +66,7 @@ SET @@session.innodb_table_locks = TRÜE; ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of 'TRÜE' SET @@session.innodb_table_locks = ÕN; ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of 'ÕN' -SET @@session.innodb_table_locks = OF; +SET @@session.innodb_table_locks = OFF; SELECT @@session.innodb_table_locks; @@session.innodb_table_locks 0 @@ -84,7 +84,7 @@ SET @@global.innodb_table_locks = TRÜE; ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of 'TRÜE' SET @@global.innodb_table_locks = QN; ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of 'QN' -SET @@global.innodb_table_locks = OF; +SET @@global.innodb_table_locks = OFF; SELECT @@global.innodb_table_locks; @@global.innodb_table_locks 0 diff --git a/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result b/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result index b7deea88a9c..8e9f7308b73 100644 --- a/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result +++ b/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result @@ -101,8 +101,8 @@ SET @@session.keep_files_on_create = ONN; ERROR 42000: Variable 'keep_files_on_create' can't be set to the value of 'ONN' SET @@session.keep_files_on_create = ONF; ERROR 42000: Variable 'keep_files_on_create' can't be set to the value of 'ONF' -SET @@session.keep_files_on_create = OF; -ERROR 42000: Variable 'keep_files_on_create' can't be set to the value of 'OF' +SET @@session.keep_files_on_create = OFFF; +ERROR 42000: Variable 'keep_files_on_create' can't be set to the value of 'OFFF' SET @@session.keep_files_on_create = 'OFN'; ERROR 42000: Variable 'keep_files_on_create' can't be set to the value of 'OFN' SET @@session.keep_files_on_create = -2; diff --git a/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result b/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result index 7ed1b689f5a..d3d2e97d249 100644 --- a/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result +++ b/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result @@ -50,8 +50,8 @@ SET @@global.log_bin_trust_function_creators = 'ONN'; ERROR 42000: Variable 'log_bin_trust_function_creators' can't be set to the value of 'ONN' SET @@global.log_bin_trust_function_creators = "OFFF"; ERROR 42000: Variable 'log_bin_trust_function_creators' can't be set to the value of 'OFFF' -SET @@global.log_bin_trust_function_creators = OF; -ERROR 42000: Variable 'log_bin_trust_function_creators' can't be set to the value of 'OF' +SET @@global.log_bin_trust_function_creators = OFFF; +ERROR 42000: Variable 'log_bin_trust_function_creators' can't be set to the value of 'OFFF' SET @@global.log_bin_trust_function_creators = TTRUE; ERROR 42000: Variable 'log_bin_trust_function_creators' can't be set to the value of 'TTRUE' SET @@global.log_bin_trust_function_creators = FELSE; diff --git a/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result b/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result index 633dc274dec..9e514c8cb35 100644 --- a/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result +++ b/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result @@ -101,8 +101,8 @@ SET @@session.low_priority_updates = ONN; ERROR 42000: Variable 'low_priority_updates' can't be set to the value of 'ONN' SET @@session.low_priority_updates = ONF; ERROR 42000: Variable 'low_priority_updates' can't be set to the value of 'ONF' -SET @@session.low_priority_updates = OF; -ERROR 42000: Variable 'low_priority_updates' can't be set to the value of 'OF' +SET @@session.low_priority_updates = OFFF; +ERROR 42000: Variable 'low_priority_updates' can't be set to the value of 'OFFF' SET @@session.low_priority_updates = 'OFN'; ERROR 42000: Variable 'low_priority_updates' can't be set to the value of 'OFN' SET @@session.low_priority_updates = -2; diff --git a/mysql-test/suite/sys_vars/r/old_passwords_basic.result b/mysql-test/suite/sys_vars/r/old_passwords_basic.result index 26d0e79071b..dba84b18b11 100644 --- a/mysql-test/suite/sys_vars/r/old_passwords_basic.result +++ b/mysql-test/suite/sys_vars/r/old_passwords_basic.result @@ -97,8 +97,8 @@ SET @@session.old_passwords = ONN; ERROR 42000: Variable 'old_passwords' can't be set to the value of 'ONN' SET @@session.old_passwords = ONF; ERROR 42000: Variable 'old_passwords' can't be set to the value of 'ONF' -SET @@session.old_passwords = OF; -ERROR 42000: Variable 'old_passwords' can't be set to the value of 'OF' +SET @@session.old_passwords = OFFF; +ERROR 42000: Variable 'old_passwords' can't be set to the value of 'OFFF' SET @@session.old_passwords = 'OFN'; ERROR 42000: Variable 'old_passwords' can't be set to the value of 'OFN' SET @@session.old_passwords = -2; diff --git a/mysql-test/suite/sys_vars/r/optimizer_prune_level_basic.result b/mysql-test/suite/sys_vars/r/optimizer_prune_level_basic.result index 99843f0b93f..c22107292cd 100644 --- a/mysql-test/suite/sys_vars/r/optimizer_prune_level_basic.result +++ b/mysql-test/suite/sys_vars/r/optimizer_prune_level_basic.result @@ -104,7 +104,7 @@ SET @@session.optimizer_prune_level = ONF; ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' SET @@session.optimizer_prune_level = ON; ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' -SET @@session.optimizer_prune_level = OF; +SET @@session.optimizer_prune_level = OFFF; ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' SET @@session.optimizer_prune_level = 'OFN'; ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' diff --git a/mysql-test/suite/sys_vars/r/pseudo_slave_mode_basic.result b/mysql-test/suite/sys_vars/r/pseudo_slave_mode_basic.result index c98dd338909..cec880bf1d5 100644 --- a/mysql-test/suite/sys_vars/r/pseudo_slave_mode_basic.result +++ b/mysql-test/suite/sys_vars/r/pseudo_slave_mode_basic.result @@ -58,8 +58,8 @@ SET @@session.pseudo_slave_mode = TRÜE; ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of 'TRÜE' SET @@session.pseudo_slave_mode = ÕN; ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of 'ÕN' -SET @@session.pseudo_slave_mode = OF; -ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of 'OF' +SET @@session.pseudo_slave_mode = OFFF; +ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of 'OFFF' SET @@session.pseudo_slave_mode = ÓFF; ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of 'ÓFF' SET @@session.pseudo_slave_mode = '¹'; diff --git a/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result b/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result index 96f42bbbda3..26169b4b979 100644 --- a/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result +++ b/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result @@ -66,8 +66,8 @@ SET @@session.query_cache_wlock_invalidate = TRÜE; ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'TRÜE' SET @@session.query_cache_wlock_invalidate = ÕN; ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'ÕN' -SET @@session.query_cache_wlock_invalidate = OF; -ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'OF' +SET @@session.query_cache_wlock_invalidate = OFFF; +ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'OFFF' SET @@session.query_cache_wlock_invalidate = ÓFF; ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'ÓFF' SET @@global.query_cache_wlock_invalidate = -1; @@ -82,8 +82,8 @@ SET @@global.query_cache_wlock_invalidate = TRÜE; ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'TRÜE' SET @@global.query_cache_wlock_invalidate = ÕN; ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'ÕN' -SET @@global.query_cache_wlock_invalidate = OF; -ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'OF' +SET @@global.query_cache_wlock_invalidate = OFFF; +ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'OFFF' SET @@global.query_cache_wlock_invalidate = ÓFF; ERROR 42000: Variable 'query_cache_wlock_invalidate' can't be set to the value of 'ÓFF' '#-------------------FN_DYNVARS_135_05----------------------------#' diff --git a/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result b/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result index 98f05bda488..fc16ecc06f2 100644 --- a/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result @@ -43,8 +43,8 @@ SET @@session.sql_big_selects = TRÜE; ERROR 42000: Variable 'sql_big_selects' can't be set to the value of 'TRÜE' SET @@session.sql_big_selects = ÕN; ERROR 42000: Variable 'sql_big_selects' can't be set to the value of 'ÕN' -SET @@session.sql_big_selects = OF; -ERROR 42000: Variable 'sql_big_selects' can't be set to the value of 'OF' +SET @@session.sql_big_selects = OFFF; +ERROR 42000: Variable 'sql_big_selects' can't be set to the value of 'OFFF' SET @@session.sql_big_selects = ÓFF; ERROR 42000: Variable 'sql_big_selects' can't be set to the value of 'ÓFF' SET @@session.sql_big_selects = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result b/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result index 09553ae7d57..91081a78328 100644 --- a/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result @@ -48,7 +48,7 @@ SET @@session.sql_big_tables = TRÜE; ERROR 42000: Variable 'sql_big_tables' can't be set to the value of 'TRÜE' SET @@session.sql_big_tables = ÕN; ERROR 42000: Variable 'sql_big_tables' can't be set to the value of 'ÕN' -SET @@session.sql_big_tables = OF; +SET @@session.sql_big_tables = OFFF; ERROR 42000: Variable 'sql_big_tables' can't be set to the value of 'OF' SET @@session.sql_big_tables = ÓFF; ERROR 42000: Variable 'sql_big_tables' can't be set to the value of 'ÓFF' diff --git a/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result b/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result index 2dfdcb26898..83597ef47cb 100644 --- a/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result @@ -48,8 +48,8 @@ SET @@session.sql_buffer_result = TRÜE; ERROR 42000: Variable 'sql_buffer_result' can't be set to the value of 'TRÜE' SET @@session.sql_buffer_result = ÕN; ERROR 42000: Variable 'sql_buffer_result' can't be set to the value of 'ÕN' -SET @@session.sql_buffer_result = OF; -ERROR 42000: Variable 'sql_buffer_result' can't be set to the value of 'OF' +SET @@session.sql_buffer_result = OFFF; +ERROR 42000: Variable 'sql_buffer_result' can't be set to the value of 'OFFF' SET @@session.sql_buffer_result = ÓFF; ERROR 42000: Variable 'sql_buffer_result' can't be set to the value of 'ÓFF' SET @@session.sql_buffer_result = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result b/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result index 909c434340c..a909019fc50 100644 --- a/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result @@ -48,8 +48,8 @@ SET @@session.sql_log_bin = TRÜE; ERROR 42000: Variable 'sql_log_bin' can't be set to the value of 'TRÜE' SET @@session.sql_log_bin = ÕN; ERROR 42000: Variable 'sql_log_bin' can't be set to the value of 'ÕN' -SET @@session.sql_log_bin = OF; -ERROR 42000: Variable 'sql_log_bin' can't be set to the value of 'OF' +SET @@session.sql_log_bin = OFFF; +ERROR 42000: Variable 'sql_log_bin' can't be set to the value of 'OFFF' SET @@session.sql_log_bin = ÓFF; ERROR 42000: Variable 'sql_log_bin' can't be set to the value of 'ÓFF' SET @@session.sql_log_bin = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sql_log_off_basic.result b/mysql-test/suite/sys_vars/r/sql_log_off_basic.result index c2ffa17c5fe..0cb5b576127 100644 --- a/mysql-test/suite/sys_vars/r/sql_log_off_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_log_off_basic.result @@ -48,8 +48,8 @@ SET @@session.sql_log_off = TRÜE; ERROR 42000: Variable 'sql_log_off' can't be set to the value of 'TRÜE' SET @@session.sql_log_off = ÕN; ERROR 42000: Variable 'sql_log_off' can't be set to the value of 'ÕN' -SET @@session.sql_log_off = OF; -ERROR 42000: Variable 'sql_log_off' can't be set to the value of 'OF' +SET @@session.sql_log_off = OFFF; +ERROR 42000: Variable 'sql_log_off' can't be set to the value of 'OFFF' SET @@session.sql_log_off = ÓFF; ERROR 42000: Variable 'sql_log_off' can't be set to the value of 'ÓFF' SET @@session.sql_log_off = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result b/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result index 28bc53e5718..ed493e038ca 100644 --- a/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result @@ -63,7 +63,7 @@ SET @@session.sql_low_priority_updates = TRÜE; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'TRÜE' SET @@session.sql_low_priority_updates = ÕN; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'ÕN' -SET @@session.sql_low_priority_updates = OF; +SET @@session.sql_low_priority_updates = OFFF; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'OF' SET @@session.sql_low_priority_updates = ÓFF; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'ÓFF' @@ -79,7 +79,7 @@ SET @@global.sql_low_priority_updates = TRÜE; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'TRÜE' SET @@global.sql_low_priority_updates = ÕN; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'ÕN' -SET @@global.sql_low_priority_updates = OF; +SET @@global.sql_low_priority_updates = OFFF; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'OF' SET @@global.sql_low_priority_updates = ÓFF; ERROR 42000: Variable 'sql_low_priority_updates' can't be set to the value of 'ÓFF' diff --git a/mysql-test/suite/sys_vars/r/sql_notes_basic.result b/mysql-test/suite/sys_vars/r/sql_notes_basic.result index 7a54f90f8b7..18a846874ab 100644 --- a/mysql-test/suite/sys_vars/r/sql_notes_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_notes_basic.result @@ -48,8 +48,8 @@ SET @@session.sql_notes = TRÜE; ERROR 42000: Variable 'sql_notes' can't be set to the value of 'TRÜE' SET @@session.sql_notes = ÕN; ERROR 42000: Variable 'sql_notes' can't be set to the value of 'ÕN' -SET @@session.sql_notes = OF; -ERROR 42000: Variable 'sql_notes' can't be set to the value of 'OF' +SET @@session.sql_notes = OFFF; +ERROR 42000: Variable 'sql_notes' can't be set to the value of 'OFFF' SET @@session.sql_notes = ÓFF; ERROR 42000: Variable 'sql_notes' can't be set to the value of 'ÓFF' SET @@session.sql_notes = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result b/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result index 8cf99233ef9..97715ae2089 100644 --- a/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result @@ -48,8 +48,8 @@ SET @@session.sql_quote_show_create = TRÜE; ERROR 42000: Variable 'sql_quote_show_create' can't be set to the value of 'TRÜE' SET @@session.sql_quote_show_create = ÕN; ERROR 42000: Variable 'sql_quote_show_create' can't be set to the value of 'ÕN' -SET @@session.sql_quote_show_create = OF; -ERROR 42000: Variable 'sql_quote_show_create' can't be set to the value of 'OF' +SET @@session.sql_quote_show_create = OFFF; +ERROR 42000: Variable 'sql_quote_show_create' can't be set to the value of 'OFFF' SET @@session.sql_quote_show_create = ÓFF; ERROR 42000: Variable 'sql_quote_show_create' can't be set to the value of 'ÓFF' SET @@session.sql_quote_show_create = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result b/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result index 91bfcb2377e..4bdcc8f6b47 100644 --- a/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result @@ -48,8 +48,8 @@ SET @@session.sql_safe_updates = TRÜE; ERROR 42000: Variable 'sql_safe_updates' can't be set to the value of 'TRÜE' SET @@session.sql_safe_updates = ÕN; ERROR 42000: Variable 'sql_safe_updates' can't be set to the value of 'ÕN' -SET @@session.sql_safe_updates = OF; -ERROR 42000: Variable 'sql_safe_updates' can't be set to the value of 'OF' +SET @@session.sql_safe_updates = OFFF; +ERROR 42000: Variable 'sql_safe_updates' can't be set to the value of 'OFFF' SET @@session.sql_safe_updates = ÓFF; ERROR 42000: Variable 'sql_safe_updates' can't be set to the value of 'ÓFF' SET @@session.sql_safe_updates = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sql_warnings_basic.result b/mysql-test/suite/sys_vars/r/sql_warnings_basic.result index 762182336c3..f9cae0c7f7a 100644 --- a/mysql-test/suite/sys_vars/r/sql_warnings_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_warnings_basic.result @@ -46,8 +46,8 @@ SET @@session.sql_warnings = TRÜE; ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'TRÜE' SET @@session.sql_warnings = ÕN; ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'ÕN' -SET @@session.sql_warnings = OF; -ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'OF' +SET @@session.sql_warnings = OFFF; +ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'OFFF' SET @@session.sql_warnings = ÓFF; ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'ÓFF' SET @@session.sql_warnings = '¹'; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 69ecca3312f..65537aeaa55 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -5274,6 +5274,76 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NEVER,COMPLEMENTARY,PREFERABLY READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME VERSIONING_ALTER_HISTORY +SESSION_VALUE KEEP +GLOBAL_VALUE KEEP +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE KEEP +VARIABLE_SCOPE SESSION +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Versioning ALTER TABLE mode +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST KEEP,SURVIVE,DROP +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME VERSIONING_CURRENT_TIMESTAMP +SESSION_VALUE NOW +GLOBAL_VALUE NOW +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE now +VARIABLE_SCOPE SESSION +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Default AS OF value for versioned tables +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 VERSIONING_FORCE +SESSION_VALUE OFF +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Force system versioning for all created tables +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 VERSIONING_HIDE +SESSION_VALUE AUTO +GLOBAL_VALUE AUTO +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE AUTO +VARIABLE_SCOPE SESSION +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Hide system versioning from being displayed in table info. AUTO: hide implicit system fields only in non-versioned and AS OF queries; IMPLICIT: hide implicit system fields in all queries; FULL: hide any system fields in all queries and hide versioning info in SHOW commands; NEVER: don't hide system fields +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST AUTO,IMPLICIT,FULL,NEVER +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME VERSIONING_INNODB_ALGORITHM_SIMPLE +SESSION_VALUE ON +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Use simple algorithm of timestamp handling in InnoDB instead of TRX_SEES +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 WAIT_TIMEOUT SESSION_VALUE 28800 GLOBAL_VALUE 28800 diff --git a/mysql-test/suite/sys_vars/r/tx_read_only_basic.result b/mysql-test/suite/sys_vars/r/tx_read_only_basic.result index 3750145083f..e8f5da31c5a 100644 --- a/mysql-test/suite/sys_vars/r/tx_read_only_basic.result +++ b/mysql-test/suite/sys_vars/r/tx_read_only_basic.result @@ -102,8 +102,8 @@ SET @@session.tx_read_only = ONN; ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'ONN' SET @@session.tx_read_only = ONF; ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'ONF' -SET @@session.tx_read_only = OF; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'OF' +SET @@session.tx_read_only = OFFF; +ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'OFFF' SET @@session.tx_read_only = 'OFN'; ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'OFN' SET @@session.tx_read_only = -2; diff --git a/mysql-test/suite/sys_vars/t/delay_key_write_basic.test b/mysql-test/suite/sys_vars/t/delay_key_write_basic.test index 25176879eb1..2856993cb6c 100644 --- a/mysql-test/suite/sys_vars/t/delay_key_write_basic.test +++ b/mysql-test/suite/sys_vars/t/delay_key_write_basic.test @@ -90,7 +90,7 @@ SET @@global.delay_key_write = FALSE0; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.delay_key_write = ONN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.delay_key_write = OF; +SET @@global.delay_key_write = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.delay_key_write = ' '; diff --git a/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test b/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test index 8a327ab699b..b1fc9997cfa 100644 --- a/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test +++ b/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test @@ -94,7 +94,7 @@ SET @@session.foreign_key_checks = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.foreign_key_checks = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.foreign_key_checks = OF; +SET @@session.foreign_key_checks = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.foreign_key_checks = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test b/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test index e3e4bda345e..25be5daa552 100644 --- a/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test @@ -119,7 +119,7 @@ SET @@session.innodb_table_locks = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.innodb_table_locks = ÕN; -SET @@session.innodb_table_locks = OF; +SET @@session.innodb_table_locks = OFF; SELECT @@session.innodb_table_locks; --Error ER_WRONG_VALUE_FOR_VAR @@ -141,7 +141,7 @@ SET @@global.innodb_table_locks = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.innodb_table_locks = QN; -SET @@global.innodb_table_locks = OF; +SET @@global.innodb_table_locks = OFF; SELECT @@global.innodb_table_locks; --Error ER_WRONG_TYPE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test b/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test index e6141af4bbe..cfa50e72146 100644 --- a/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test +++ b/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test @@ -132,7 +132,7 @@ SET @@session.keep_files_on_create = ONN; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.keep_files_on_create = ONF; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.keep_files_on_create = OF; +SET @@session.keep_files_on_create = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.keep_files_on_create = 'OFN'; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test b/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test index 15ffad2742a..1db6bf41e6f 100644 --- a/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test +++ b/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test @@ -96,7 +96,7 @@ SET @@global.log_bin_trust_function_creators = 'ONN'; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.log_bin_trust_function_creators = "OFFF"; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.log_bin_trust_function_creators = OF; +SET @@global.log_bin_trust_function_creators = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.log_bin_trust_function_creators = TTRUE; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test b/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test index e00688ef974..703036b8e36 100644 --- a/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test +++ b/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test @@ -132,7 +132,7 @@ SET @@session.low_priority_updates = ONN; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.low_priority_updates = ONF; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.low_priority_updates = OF; +SET @@session.low_priority_updates = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.low_priority_updates = 'OFN'; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/old_passwords_basic.test b/mysql-test/suite/sys_vars/t/old_passwords_basic.test index f4965ad7528..038a77edf8f 100644 --- a/mysql-test/suite/sys_vars/t/old_passwords_basic.test +++ b/mysql-test/suite/sys_vars/t/old_passwords_basic.test @@ -131,7 +131,7 @@ SET @@session.old_passwords = ONN; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.old_passwords = ONF; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.old_passwords = OF; +SET @@session.old_passwords = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.old_passwords = 'OFN'; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/optimizer_prune_level_basic.test b/mysql-test/suite/sys_vars/t/optimizer_prune_level_basic.test index 1e3a8bc3d7f..374be2db6ae 100644 --- a/mysql-test/suite/sys_vars/t/optimizer_prune_level_basic.test +++ b/mysql-test/suite/sys_vars/t/optimizer_prune_level_basic.test @@ -140,7 +140,7 @@ SET @@session.optimizer_prune_level = ONF; --Error ER_WRONG_TYPE_FOR_VAR SET @@session.optimizer_prune_level = ON; --Error ER_WRONG_TYPE_FOR_VAR -SET @@session.optimizer_prune_level = OF; +SET @@session.optimizer_prune_level = OFFF; --Error ER_WRONG_TYPE_FOR_VAR SET @@session.optimizer_prune_level = 'OFN'; diff --git a/mysql-test/suite/sys_vars/t/pseudo_slave_mode_basic.test b/mysql-test/suite/sys_vars/t/pseudo_slave_mode_basic.test index 3ef39bb8667..6d1dca299c6 100644 --- a/mysql-test/suite/sys_vars/t/pseudo_slave_mode_basic.test +++ b/mysql-test/suite/sys_vars/t/pseudo_slave_mode_basic.test @@ -97,7 +97,7 @@ SET @@session.pseudo_slave_mode = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.pseudo_slave_mode = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.pseudo_slave_mode = OF; +SET @@session.pseudo_slave_mode = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.pseudo_slave_mode = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test b/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test index 055c3629d15..c883d9b789a 100644 --- a/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test +++ b/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test @@ -116,7 +116,7 @@ SET @@session.query_cache_wlock_invalidate = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.query_cache_wlock_invalidate = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.query_cache_wlock_invalidate = OF; +SET @@session.query_cache_wlock_invalidate = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.query_cache_wlock_invalidate = ÓFF; @@ -135,7 +135,7 @@ SET @@global.query_cache_wlock_invalidate = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.query_cache_wlock_invalidate = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.query_cache_wlock_invalidate = OF; +SET @@global.query_cache_wlock_invalidate = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.query_cache_wlock_invalidate = ÓFF; diff --git a/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test b/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test index 42331d766be..52345b71144 100644 --- a/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test @@ -94,7 +94,7 @@ SET @@session.sql_big_selects = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_big_selects = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_big_selects = OF; +SET @@session.sql_big_selects = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_big_selects = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test b/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test index f5f99efeb0a..2475bd9cd8a 100644 --- a/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test @@ -100,7 +100,7 @@ SET @@session.sql_buffer_result = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_buffer_result = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_buffer_result = OF; +SET @@session.sql_buffer_result = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_buffer_result = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test b/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test index 5f5e3920862..7e133200d5f 100644 --- a/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test @@ -98,7 +98,7 @@ SET @@session.sql_log_bin = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_log_bin = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_log_bin = OF; +SET @@session.sql_log_bin = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_log_bin = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/sql_log_off_basic.test b/mysql-test/suite/sys_vars/t/sql_log_off_basic.test index 38549ac35d2..a48d3bbfda6 100644 --- a/mysql-test/suite/sys_vars/t/sql_log_off_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_log_off_basic.test @@ -97,7 +97,7 @@ SET @@session.sql_log_off = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_log_off = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_log_off = OF; +SET @@session.sql_log_off = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_log_off = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/sql_notes_basic.test b/mysql-test/suite/sys_vars/t/sql_notes_basic.test index 9af5fa35ea2..204ebe3fe84 100644 --- a/mysql-test/suite/sys_vars/t/sql_notes_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_notes_basic.test @@ -99,7 +99,7 @@ SET @@session.sql_notes = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_notes = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_notes = OF; +SET @@session.sql_notes = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_notes = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test b/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test index 020b5f51e9f..8e8118b998b 100644 --- a/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test @@ -98,7 +98,7 @@ SET @@session.sql_quote_show_create = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_quote_show_create = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_quote_show_create = OF; +SET @@session.sql_quote_show_create = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_quote_show_create = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test b/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test index 66148b65aaf..89208cae0ef 100644 --- a/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test @@ -97,7 +97,7 @@ SET @@session.sql_safe_updates = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_safe_updates = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_safe_updates = OF; +SET @@session.sql_safe_updates = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_safe_updates = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/sql_warnings_basic.test b/mysql-test/suite/sys_vars/t/sql_warnings_basic.test index ced58f96e15..f32b6f33f89 100644 --- a/mysql-test/suite/sys_vars/t/sql_warnings_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_warnings_basic.test @@ -98,7 +98,7 @@ SET @@session.sql_warnings = TRÜE; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_warnings = ÕN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.sql_warnings = OF; +SET @@session.sql_warnings = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.sql_warnings = ÓFF; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/sys_vars/t/tx_read_only_basic.test b/mysql-test/suite/sys_vars/t/tx_read_only_basic.test index 0ebfcc31a89..8c6ab0e3d59 100644 --- a/mysql-test/suite/sys_vars/t/tx_read_only_basic.test +++ b/mysql-test/suite/sys_vars/t/tx_read_only_basic.test @@ -116,7 +116,7 @@ SET @@session.tx_read_only = ONN; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.tx_read_only = ONF; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = OF; +SET @@session.tx_read_only = OFFF; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.tx_read_only = 'OFN'; --Error ER_WRONG_VALUE_FOR_VAR diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc new file mode 100644 index 00000000000..ca3ccd41752 --- /dev/null +++ b/mysql-test/suite/versioning/common.inc @@ -0,0 +1,87 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); + +delimiter ~~; +create procedure if not exists verify_vtq() +begin + set @i= 0; + select + @i:= @i + 1 as No, + transaction_id > 0 as A, + commit_id > transaction_id as B, + begin_timestamp > @test_start as C, + commit_timestamp >= begin_timestamp as D + from information_schema.innodb_vtq + where transaction_id > @start_trx_id; + select ifnull(max(transaction_id), 0) + into @start_trx_id + from information_schema.innodb_vtq; +end~~ + +create function if not exists default_engine() +returns varchar(255) +deterministic +begin + declare e varchar(255); + select lower(engine) from information_schema.engines where support='DEFAULT' into e; + return e; +end~~ + +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin + if default_engine() = 'innodb' then + return 'bigint unsigned'; + elseif default_engine() = 'myisam' then + return 'timestamp(6)'; + end if; + return NULL; +end~~ + +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin + if default_engine() = 'innodb' then + return concat('vtq_commit_ts(', sys_field, ')'); + elseif default_engine() = 'myisam' then + return sys_field; + end if; + return NULL; +end~~ + +create procedure if not exists innodb_verify_vtq(recs int) +begin + declare i int default 1; + if default_engine() = 'innodb' then + call verify_vtq; + elseif default_engine() = 'myisam' then + create temporary table tmp (No int, A bool, B bool, C bool, D bool); + while i <= recs do + insert into tmp values (i, 1, 1, 1, 1); + set i= i + 1; + end while; + select * from tmp; + drop table tmp; + end if; +end~~ + +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin + prepare stmt from concat(a, b); + execute stmt; + deallocate prepare stmt; +end~~ + +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin + prepare stmt from concat(a, b, c); + execute stmt; + deallocate prepare stmt; +end~~ +delimiter ;~~ + +let $default_engine= `select default_engine()`; +let sys_datatype= `select sys_datatype()`; diff --git a/mysql-test/suite/versioning/common.opt b/mysql-test/suite/versioning/common.opt new file mode 100644 index 00000000000..132aab2d0ec --- /dev/null +++ b/mysql-test/suite/versioning/common.opt @@ -0,0 +1,19 @@ +--innodb +--innodb-cmpmem +--innodb-cmp-per-index +--innodb-trx +--innodb-locks +--innodb-metrics +--innodb-buffer-pool-stats +--innodb-buffer-page +--innodb-buffer-page-lru +--innodb-sys-columns +--innodb-sys-fields +--innodb-sys-foreign +--innodb-sys-foreign-cols +--innodb-sys-indexes +--innodb-sys-tables +--innodb-sys-virtual +--innodb-vtq +--versioning-hide=implicit +--plugin-load=versioning diff --git a/mysql-test/suite/versioning/common_finish.inc b/mysql-test/suite/versioning/common_finish.inc new file mode 100644 index 00000000000..9a746f5a98c --- /dev/null +++ b/mysql-test/suite/versioning/common_finish.inc @@ -0,0 +1,7 @@ +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result new file mode 100644 index 00000000000..d6cbaf96b73 --- /dev/null +++ b/mysql-test/suite/versioning/r/alter.result @@ -0,0 +1,595 @@ +create table t( +a int +); +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t without system versioning; +ERROR HY000: Wrong parameters for `t`: table is not versioned +alter table t with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t without system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t +add column trx_start bigint(20) unsigned generated always as row start, +add column trx_end bigint(20) unsigned generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +ERROR HY000: `trx_start` must be of type `TIMESTAMP(6)` for versioned table `t` +alter table t +add column trx_start timestamp generated always as row start, +add column trx_end timestamp generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +ERROR HY000: `trx_start` must be of type `TIMESTAMP(6)` for versioned table `t` +alter table t +add column trx_start timestamp(6) not null generated always as row start, +add column trx_end timestamp(6) not null generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +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 'generated always as row start, +add column trx_end timestamp(6) not null generate' at line 2 +alter table t +add column trx_start timestamp(6) generated always as row start, +add column trx_end timestamp(6) generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`trx_start`, `trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t drop column trx_start, drop column trx_end; +alter table t without system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column b int; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column c int; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column d int first; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `d` int(11) DEFAULT NULL, + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column e int after d; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `d` int(11) DEFAULT NULL, + `e` int(11) DEFAULT NULL, + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t drop column a; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `d` int(11) DEFAULT NULL, + `e` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t ( +a int, +sys_trx_start timestamp(6) generated always as row start, +sys_trx_end timestamp(6) generated always as row end, +period for system_time(sys_trx_start, sys_trx_end)) +with system versioning; +select * from t for system_time all; +a sys_trx_start sys_trx_end +alter table t drop column sys_trx_start; +alter table t drop column sys_trx_end; +select * from t for system_time all; +a +alter table t drop column sys_trx_start; +ERROR 42000: Can't DROP COLUMN `sys_trx_start`; check that it exists +alter table t drop column sys_trx_end; +ERROR 42000: Can't DROP COLUMN `sys_trx_end`; check that it exists +create or replace table t ( +a int, +sys_trx_start timestamp(6) generated always as row start, +sys_trx_end timestamp(6) generated always as row end, +period for system_time(sys_trx_start, sys_trx_end)) +with system versioning; +select * from t for system_time all; +a sys_trx_start sys_trx_end +alter table t drop column sys_trx_start, drop column sys_trx_end; +select * from t for system_time all; +a +create or replace table t( +a int +); +insert into t values(1); +alter table t with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +insert into t values(2); +select * from t for system_time all; +a +1 +2 +select * from t; +a +1 +2 +update t set a=3 where a=1; +select * from t; +a +3 +2 +select * from t for system_time all; +a +3 +2 +1 +select sys_trx_start from t where a=3 into @tm; +alter table t add column b int; +select @tm=sys_trx_start from t where a=3; +@tm=sys_trx_start +1 +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t; +a b +3 NULL +2 NULL +select * from t for system_time all; +a b +3 NULL +2 NULL +1 NULL +alter table t without system versioning; +select * from t; +a b +3 NULL +2 NULL +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t modify a int with system versioning; +ERROR HY000: Wrong parameters for `t`: table is not versioned +alter table t modify a int without system versioning; +ERROR HY000: Wrong parameters for `t`: table is not versioned +alter table t with system versioning; +alter table t modify a int without system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING, + `b` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t modify a int with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create or replace table t( +a int +) engine=innodb; +insert into t values(1); +select * from t; +a +1 +alter table t +add column trx_start timestamp(6) generated always as row start, +add column trx_end timestamp(6) generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +ERROR HY000: `trx_start` must be of type `BIGINT(20) UNSIGNED` for versioned table `t` +alter table t +add column trx_start bigint(20) unsigned generated always as row start, +add column trx_end bigint(20) unsigned generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`trx_start`, `trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t drop column trx_start, drop column trx_end; +alter table t without system versioning; +alter table t with system versioning, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +update t set a=2; +select * from t for system_time all; +a +2 +1 +alter table t add column b int, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t; +a b +2 NULL +alter table t drop column b, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t for system_time all; +a +2 +1 +alter table t add column b int, algorithm=inplace; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t; +a b +2 NULL +alter table t drop column b, algorithm=inplace; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t for system_time all; +a +2 +1 +alter table t without system versioning, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +create or replace table t (a int) with system versioning engine=innodb; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b int auto_increment unique; +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +insert into t values (4, NULL); +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +4 2 +create or replace table t (a int) with system versioning; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b int auto_increment unique; +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +insert into t values (4, NULL); +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +4 2 +create or replace table t (a int) with system versioning engine=innodb; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b tinyint auto_increment unique; +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +insert into t values (4, NULL); +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +4 2 +create or replace table t (a int) with system versioning; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b tinyint auto_increment unique; +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +insert into t values (4, NULL); +select * from t for system_time all; +a b +1 -1 +2 -2 +3 1 +4 2 +create or replace table t (a int) engine innodb; +insert into t values (1); +alter table t with system versioning, algorithm=inplace; +select * from t for system_time all; +a +1 +update t set a=2; +select * from t for system_time all; +a +2 +1 +alter table t add column b int, algorithm=inplace; +select * from t for system_time all; +a b +2 NULL +1 NULL +alter table t without system versioning, algorithm=inplace; +select * from t; +a b +2 NULL +create or replace table t ( +a int, +sys_trx_start bigint(20) unsigned generated always as row start, +sys_trx_end bigint(20) unsigned generated always as row end, +period for system_time(sys_trx_start, sys_trx_end) +) with system versioning engine innodb; +alter table t change column sys_trx_start asdf bigint unsigned; +ERROR HY000: Can not change system versioning field 'sys_trx_start' +create or replace table t ( +a int, +sys_trx_start timestamp(6) generated always as row start, +sys_trx_end timestamp(6) generated always as row end, +period for system_time(sys_trx_start, sys_trx_end) +) with system versioning engine myisam; +alter table t change column sys_trx_start asdf timestamp(6); +ERROR HY000: Can not change system versioning field 'sys_trx_start' +create or replace table t ( +a int, +sys_trx_start timestamp(6) generated always as row start, +sys_trx_end timestamp(6) generated always as row end, +period for system_time(sys_trx_start, sys_trx_end) +) with system versioning; +select * from t; +a sys_trx_start sys_trx_end +alter table t without system versioning; +ERROR HY000: System versioning field 'sys_trx_start' is not hidden +alter table t drop column sys_trx_start; +select * from t; +a sys_trx_end +alter table t without system versioning; +ERROR HY000: System versioning field 'sys_trx_end' is not hidden +alter table t drop column sys_trx_end; +select * from t; +a +alter table t without system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +set versioning_alter_history = DROP; +create or replace table t (a int) with system versioning engine innodb; +insert into t values (1); +update t set a = 2; +select * from t for system_time all; +a +2 +1 +alter table t add column b int; +select * from t for system_time all; +a b +2 NULL +create or replace table t (a int) with system versioning engine myisam; +insert into t values (1); +update t set a = 2; +select * from t for system_time all; +a +2 +1 +alter table t add column b int; +select * from t for system_time all; +a b +2 NULL +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +12 1 1 1 1 +13 1 1 1 1 +14 1 1 1 1 +drop table t; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/auto_increment.result b/mysql-test/suite/versioning/r/auto_increment.result new file mode 100644 index 00000000000..533a5cc45af --- /dev/null +++ b/mysql-test/suite/versioning/r/auto_increment.result @@ -0,0 +1,201 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure test_01( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1( + id int unsigned auto_increment primary key, + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @str= concat(' + create table t2( + id int unsigned auto_increment primary key, + x int unsigned, + y int unsigned) + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(x, y) values(1, 11); +insert into t2(x, y) values(1, 11); +insert into t1(x, y) values(2, 12); +insert into t2(x, y) values(2, 12); +insert into t1(x, y) values(3, 13); +insert into t2(x, y) values(3, 13); +insert into t1(x, y) values(4, 14); +insert into t2(x, y) values(4, 14); +insert into t1(x, y) values(5, 15); +insert into t2(x, y) values(5, 15); +insert into t1(x, y) values(6, 16); +insert into t2(x, y) values(6, 16); +insert into t1(x, y) values(7, 17); +insert into t2(x, y) values(7, 17); +insert into t1(x, y) values(8, 18); +insert into t2(x, y) values(8, 18); +insert into t1(x, y) values(9, 19); +insert into t2(x, y) values(9, 19); +select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id; +delete from t1 where x = 2; +delete from t2 where x = 2; +select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id; +delete from t1 where x > 7; +delete from t2 where x > 7; +select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id; +drop table t1; +drop table t2; +end~~ +call test_01('timestamp(6)', 'myisam', 'sys_end'); +A x y x y +1 1 11 1 11 +1 2 12 2 12 +1 3 13 3 13 +1 4 14 4 14 +1 5 15 5 15 +1 6 16 6 16 +1 7 17 7 17 +1 8 18 8 18 +1 9 19 9 19 +A x y x y +1 1 11 1 11 +1 3 13 3 13 +1 4 14 4 14 +1 5 15 5 15 +1 6 16 6 16 +1 7 17 7 17 +1 8 18 8 18 +1 9 19 9 19 +A x y x y +1 1 11 1 11 +1 3 13 3 13 +1 4 14 4 14 +1 5 15 5 15 +1 6 16 6 16 +1 7 17 7 17 +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +A x y x y +1 1 11 1 11 +1 2 12 2 12 +1 3 13 3 13 +1 4 14 4 14 +1 5 15 5 15 +1 6 16 6 16 +1 7 17 7 17 +1 8 18 8 18 +1 9 19 9 19 +A x y x y +1 1 11 1 11 +1 3 13 3 13 +1 4 14 4 14 +1 5 15 5 15 +1 6 16 6 16 +1 7 17 7 17 +1 8 18 8 18 +1 9 19 9 19 +A x y x y +1 1 11 1 11 +1 3 13 3 13 +1 4 14 4 14 +1 5 15 5 15 +1 6 16 6 16 +1 7 17 7 17 +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +drop procedure test_01; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/commit_id.result b/mysql-test/suite/versioning/r/commit_id.result new file mode 100644 index 00000000000..56ca1f4bec3 --- /dev/null +++ b/mysql-test/suite/versioning/r/commit_id.result @@ -0,0 +1,173 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create table t1( +id int auto_increment primary key) +with system versioning +engine innodb; +insert into t1 values (); +set @ts0= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx0; +select transaction_id = @tx0 from information_schema.innodb_vtq limit 1; +transaction_id = @tx0 +1 +set @ts1= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx1; +select transaction_id = @tx1 from information_schema.innodb_vtq limit 1; +transaction_id = @tx1 +1 +set @ts2= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx2; +select transaction_id = @tx2 from information_schema.innodb_vtq limit 1; +transaction_id = @tx2 +1 +set @ts3= now(6); +select +vtq_trx_id(@ts0) < @tx0 as A, +vtq_trx_id(@ts0, true) = @tx0 as B, +vtq_trx_id(@ts1) = @tx0 as C, +vtq_trx_id(@ts1, true) = @tx1 as D, +vtq_trx_id(@ts2) = @tx1 as E, +vtq_trx_id(@ts2, true) = @tx2 as F, +vtq_trx_id(@ts3) = @tx2 as G, +vtq_trx_id(@ts3, true) is null as H; +A B C D E F G H +1 1 1 1 1 1 1 1 +select +vtq_commit_id(@ts0) < @tx0 as A, +vtq_commit_id(@ts0, true) = vtq_commit_id(null, @tx0) as B, +vtq_commit_id(@ts1) = vtq_commit_id(null, @tx0) as C, +vtq_commit_id(@ts1, true) = vtq_commit_id(null, @tx1) as D, +vtq_commit_id(@ts2) = vtq_commit_id(null, @tx1) as E, +vtq_commit_id(@ts2, true) = vtq_commit_id(null, @tx2) as F, +vtq_commit_id(@ts3) = vtq_commit_id(null, @tx2) as G, +vtq_commit_id(@ts3, true) is null as H; +A B C D E F G H +1 1 1 1 1 1 1 1 +select +vtq_trx_sees(@tx1, @tx0) as A, +not vtq_trx_sees(@tx0, @tx1) as B, +vtq_trx_sees_eq(@tx1, @tx1) as C, +not vtq_trx_sees(@tx1, @tx1) as D, +vtq_trx_sees(@tx2, 0) as E, +vtq_trx_sees(0, @tx2) is null as F, +vtq_trx_sees(-1, @tx2) as H; +A B C D E F H +1 1 1 1 1 1 1 +set transaction isolation level read uncommitted; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx3; +select isolation_level = 'READ-UNCOMMITTED' from information_schema.innodb_vtq where transaction_id = @tx3; +isolation_level = 'READ-UNCOMMITTED' +1 +set transaction isolation level read committed; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx4; +select isolation_level = 'READ-COMMITTED' from information_schema.innodb_vtq where transaction_id = @tx4; +isolation_level = 'READ-COMMITTED' +1 +set transaction isolation level serializable; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx5; +select isolation_level = 'SERIALIZABLE' from information_schema.innodb_vtq where transaction_id = @tx5; +isolation_level = 'SERIALIZABLE' +1 +set transaction isolation level repeatable read; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx6; +select isolation_level = 'REPEATABLE-READ' from information_schema.innodb_vtq where transaction_id = @tx6; +isolation_level = 'REPEATABLE-READ' +1 +drop table t1; +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result new file mode 100644 index 00000000000..a190ac30fd9 --- /dev/null +++ b/mysql-test/suite/versioning/r/create.result @@ -0,0 +1,376 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +drop table if exists t1; +create function if not exists non_default_engine() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'myisam'; +end if; +return 'innodb'; +end~~ +create table t1 ( +x1 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start comment 'start', +Sys_end SYS_TRX_TYPE generated always as row end comment 'end', +period for system_time (Sys_start, Sys_end) +) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x1` int(10) unsigned DEFAULT NULL, + `Sys_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START COMMENT 'start', + `Sys_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END COMMENT 'end', + PERIOD FOR SYSTEM_TIME (`Sys_start`, `Sys_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +# Implicit fields test +create or replace table t1 ( +x2 int unsigned +) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x2` int(10) unsigned DEFAULT NULL, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t1 ( +x3 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start, +Sys_start2 SYS_TRX_TYPE generated always as row start, +Sys_end SYS_TRX_TYPE generated always as row end, +period for system_time (Sys_start, Sys_end) +) with system versioning; +ERROR HY000: Wrong parameters for `t1`: mismatch 'PERIOD FOR SYSTEM_TIME' and 'AS ROW START' +create or replace table t1 ( +x4 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start, +Sys_end2 SYS_TRX_TYPE generated always as row end, +period for system_time (Sys_start, Sys_end) +) with system versioning; +ERROR HY000: Wrong parameters for `t1`: mismatch 'PERIOD FOR SYSTEM_TIME' and 'AS ROW END' +create or replace table t1 ( +x5 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start, +Sys_end SYS_TRX_TYPE generated always as row end, +Sys_end2 SYS_TRX_TYPE generated always as row end, +period for system_time (Sys_start, Sys_end) +) with system versioning; +ERROR HY000: Wrong parameters for `t1`: mismatch 'PERIOD FOR SYSTEM_TIME' and 'AS ROW END' +create or replace table t1 ( +x6 int unsigned, +period for system_time (Sys_start, Sys_end) +) with system versioning; +ERROR HY000: Wrong parameters for `t1`: missing 'AS ROW START' +create or replace table t1 ( +x7 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start, +Sys_end SYS_TRX_TYPE generated always as row end, +Sys_end2 SYS_TRX_TYPE generated always as row end, +period for system_time (Sys_start, Sys_end) +); +ERROR HY000: Wrong parameters for `t1`: missing 'WITH SYSTEM VERSIONING' +create or replace table t1 ( +x8 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start, +Sys_end SYS_TRX_TYPE generated always as row end, +period for system_time (sys_insert, sys_remove) +) with system versioning; +ERROR HY000: Wrong parameters for `t1`: mismatch 'PERIOD FOR SYSTEM_TIME' and 'AS ROW START' +create or replace table t1 ( +x9 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start, +Sys_end SYS_TRX_TYPE generated always as row end, +period for system_time (Sys_start, Sys_end) +); +ERROR HY000: Wrong parameters for `t1`: missing 'WITH SYSTEM VERSIONING' +create or replace table t1 ( +x10 int unsigned, +Sys_start SYS_TRX_TYPE generated always as row start, +Sys_end SYS_TRX_TYPE generated always as row end, +period for system_time (Sys_start, Sys_start) +); +ERROR HY000: Wrong parameters for `t1`: missing 'WITH SYSTEM VERSIONING' +create or replace table t1 ( +x11 int unsigned, +Sys_start bigint unsigned generated always as row start, +Sys_end timestamp(6) generated always as row end, +period for system_time (Sys_start, Sys_end) +) with system versioning; +Got one of the listed errors +create or replace table t1 ( +x12 int unsigned, +Sys_start timestamp(6) generated always as row start, +Sys_end bigint unsigned generated always as row end, +period for system_time (Sys_start, Sys_end) +) with system versioning; +Got one of the listed errors +create or replace table t1 ( +x13 int unsigned, +Sys_start bigint generated always as row start, +Sys_end bigint unsigned generated always as row end, +period for system_time (Sys_start, Sys_end) +) with system versioning engine innodb; +ERROR HY000: `Sys_start` must be of type `BIGINT(20) UNSIGNED` for versioned table `t1` +create or replace table t1 ( +x14 int unsigned, +Sys_start bigint unsigned generated always as row start, +Sys_end bigint generated always as row end, +period for system_time (Sys_start, Sys_end) +) with system versioning engine innodb; +ERROR HY000: `Sys_end` must be of type `BIGINT(20) UNSIGNED` for versioned table `t1` +create or replace table t1 ( +A1 int with system versioning, +B int +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `A1` int(11) DEFAULT NULL, + `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t1 ( +A2 int with system versioning, +B int +) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `A2` int(11) DEFAULT NULL, + `B` int(11) DEFAULT NULL, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t1 ( +A3 int, +B int without system versioning +); +create or replace table t1 ( +A4 int, +B int without system versioning +) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `A4` int(11) DEFAULT NULL, + `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t1 ( +A5 int with system versioning, +B int without system versioning +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `A5` int(11) DEFAULT NULL, + `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t1 ( +A6 int with system versioning, +B int without system versioning +) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `A6` int(11) DEFAULT NULL, + `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t1 ( +A7 int without system versioning +); +create or replace table t1 ( +A8 int without system versioning +) with system versioning; +ERROR HY000: Wrong parameters for `t1`: no columns defined 'WITH SYSTEM VERSIONING' +create table t( +a11 int +) without system versioning; +ERROR HY000: Wrong parameters for `t`: not allowed 'WITHOUT SYSTEM VERSIONING' +create or replace table t1 (a int) with system versioning; +create temporary table tmp with system versioning select * from t1; +create or replace table t1 (a int) with system versioning; +create table tt1 like t1; +show create table tt1; +Table Create Table +tt1 CREATE TABLE `tt1` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +drop table tt1; +create or replace table t1 (x int) with system versioning; +create or replace table t0( +y int, +st SYS_TRX_TYPE generated always as row start, +en SYS_TRX_TYPE generated always as row end, +period for system_time (st, en) +) with system versioning; +create or replace table t2 as select * from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `x` int(11) DEFAULT NULL +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 +create or replace table t3 as select * from t0; +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `y` int(11) DEFAULT NULL +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 +insert into t1 values (1); +insert into t0 values (2); +create or replace table t2 with system versioning as select * from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `x` int(11) DEFAULT NULL, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t2; +x +1 +create or replace table t3 with system versioning as select * from t0; +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `y` int(11) DEFAULT NULL, + `st` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `en` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`st`, `en`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t3 where y > 2; +y st en +delete from t0; +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int); +create or replace table t3 with system versioning select * from t1 for system_time all, t2; +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `x` int(11) DEFAULT NULL, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + `y` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t2 with system versioning as select * from t0; +create or replace table t3 with system versioning select x, y, t1.sys_trx_start, t2.en from t1, t2; +ERROR HY000: Wrong parameters for `t3`: system fields selected from different tables +insert into t2 values (1), (2); +delete from t2 where y = 2; +create or replace table t3 select * from t2 for system_time all; +select st, en from t2 where y = 1 into @st, @en; +select y from t2 for system_time all where st = @st and en = @en; +y +1 +select st, en from t2 for system_time all where y = 2 into @st, @en; +select y from t2 for system_time all where st = @st and en = @en; +y +2 +create or replace table t1 (a int) with system versioning engine INNODB_OR_MYISAM; +create or replace table t2 as select a, sys_trx_start, sys_trx_end from t1 for system_time all; +create or replace table t2 with system versioning engine INNODB_OR_MYISAM as select a, sys_trx_start, sys_trx_end from t1 for system_time all; +ERROR HY000: `sys_trx_start` must be of type `SYS_TRX_TYPE` for versioned table `t2` +create or replace table t1 (a int, id int) with system versioning engine INNODB_OR_MYISAM; +create or replace table t2 (b int, id int); +create or replace table t3 as +select t2.b, t1.a, t1.sys_trx_start, t1.sys_trx_end from t2 inner join t1 on t2.id=t1.id; +create or replace table t (sys_trx_start int); +alter table t with system versioning; +ERROR 42S21: Duplicate column name 'sys_trx_start' +create or replace table t (sys_trx_end int); +alter table t with system versioning; +ERROR 42S21: Duplicate column name 'sys_trx_end' +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/r/cte.result b/mysql-test/suite/versioning/r/cte.result new file mode 100644 index 00000000000..161255aeaa7 --- /dev/null +++ b/mysql-test/suite/versioning/r/cte.result @@ -0,0 +1,99 @@ +create or replace table dept ( +dept_id int(10) primary key, +name varchar(100) +) +with system versioning; +create or replace table emp ( +emp_id int(10) primary key, +dept_id int(10) not null, +name varchar(100) not null, +mgr int(10), +salary int(10) not null, +constraint `dept-emp-fk` + foreign key (dept_id) references dept (dept_id) +on delete cascade +on update restrict, +constraint `mgr-fk` + foreign key (mgr) references emp (emp_id) +on delete restrict +on update restrict +) +with system versioning; +insert into dept (dept_id, name) values (10, "accounting"); +insert into emp (emp_id, name, salary, dept_id, mgr) values +(1, "bill", 1000, 10, null), +(20, "john", 500, 10, 1), +(30, "jane", 750, 10,1 ); +select vtq_commit_ts(max(sys_trx_start)) into @ts_1 from emp; +update emp set mgr=30 where name ="john"; +select vtq_commit_ts(sys_trx_start) into @ts_2 from emp where name="john"; +/* All report to 'Bill' */ +with recursive +ancestors +as +( +select e.emp_id, e.name, e.mgr, e.salary +from emp for system_time as of timestamp @ts_1 as e +where name = 'bill' + union +select e.emp_id, e.name, e.mgr, e.salary +from emp for system_time as of timestamp @ts_1 as e, +ancestors as a +where e.mgr = a.emp_id +) +select * from ancestors for system_time as of now; +emp_id name mgr salary +1 bill NULL 1000 +30 jane 1 750 +/* Expected 3 rows */ +with recursive +ancestors +as +( +select e.emp_id, e.name, e.mgr, e.salary +from emp for system_time as of timestamp @ts_2 as e +where name = 'bill' + union +select e.emp_id, e.name, e.mgr, e.salary +from emp for system_time as of timestamp @ts_2 as e, +ancestors as a +where e.mgr = a.emp_id +) +select * from ancestors; +emp_id name mgr salary +1 bill NULL 1000 +30 jane 1 750 +20 john 30 500 +create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning; +create or replace table addr ( emp_id int, address varchar(100)) with system versioning; +insert emp values (1, 'bill', 0), (2, 'bill', 1), (3, 'kate', 1); +insert addr values (1, 'Moscow'), (2, 'New York'), (3, 'London'); +set @ts=now(6); +delete from emp; +delete from addr; +insert emp values (4, 'john', 1); +insert addr values (4, 'Paris'); +with ancestors as (select * from emp natural join addr) select * from ancestors; +emp_id name mgr address +4 john 1 Paris +with ancestors as (select * from emp natural join addr) select * from ancestors for system_time all; +emp_id name mgr address +1 bill 0 Moscow +2 bill 1 New York +3 kate 1 London +4 john 1 Paris +with ancestors as (select * from emp natural join addr system_time all) select * from ancestors; +emp_id name mgr address +1 bill 0 Moscow +2 bill 1 New York +3 kate 1 London +4 john 1 Paris +select * from emp natural join addr system_time all; +emp_id name mgr address +1 bill 0 Moscow +2 bill 1 New York +3 kate 1 London +4 john 1 Paris +drop table emp; +drop table dept; +drop table addr; diff --git a/mysql-test/suite/versioning/r/ddl.result b/mysql-test/suite/versioning/r/ddl.result new file mode 100644 index 00000000000..759cb5f449a --- /dev/null +++ b/mysql-test/suite/versioning/r/ddl.result @@ -0,0 +1,211 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create function get_archive_table_name() +returns varchar(255) +begin +return (select archive_name from t_vtmd for system_time all where archive_name is not NULL +order by start desc limit 1); +end~~ +create procedure drop_last_archive() +begin +call concat_exec2('drop table ', get_archive_table_name()); +end~~ +set versioning_alter_history= survive; +create or replace table t (a int) with system versioning; +insert into t values (1); +update t set a=2 where a=1; +select sys_trx_start from t where a=2 into @tm; +alter table t add column b int; +select * from t; +a b +2 NULL +call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all'); +a +2 +1 +call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2'); +@tm=sys_trx_start +1 +select @tm<sys_trx_start from t where a=2; +@tm<sys_trx_start +1 +select sys_trx_start from t where a=2 into @tm; +call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2'); +@tm=sys_trx_end +1 +call drop_last_archive(); +set versioning_alter_history= keep; +drop table t_vtmd; +drop table t; +set versioning_alter_history= survive; +create or replace table t (a int) with system versioning; +insert into t values (1); +update t set a=2 where a=1; +select sys_trx_start from t where a=2 into @tm; +alter table t add column b int; +select * from t; +a b +2 NULL +call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all'); +a +2 +1 +call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2'); +@tm=sys_trx_start +1 +select @tm<sys_trx_start from t where a=2; +@tm<sys_trx_start +1 +select sys_trx_start from t where a=2 into @tm; +call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2'); +@tm=sys_trx_end +1 +call drop_last_archive(); +set versioning_alter_history= keep; +drop table t_vtmd; +drop table t; +set versioning_alter_history= survive; +create or replace table t (a int) with system versioning engine innodb; +insert into t values (1); +update t set a=2 where a=1; +select sys_trx_start from t where a=2 into @tm; +alter table t add column b int; +select * from t; +a b +2 NULL +call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all'); +a +2 +1 +call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2'); +@tm=sys_trx_start +1 +select @tm<sys_trx_start from t where a=2; +@tm<sys_trx_start +1 +select sys_trx_start from t where a=2 into @tm; +call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2'); +@tm=sys_trx_end +1 +call drop_last_archive(); +set versioning_alter_history= keep; +drop table t_vtmd; +drop table t; +set versioning_alter_history= survive; +create or replace table t (a int) with system versioning engine innodb; +insert into t values (1); +update t set a=2 where a=1; +alter table t add column b int, algorithm=inplace; +set versioning_alter_history = keep; +drop function get_archive_table_name; +drop procedure drop_last_archive; +select * from mysql.vtmd_template; +start end name archive_name col_renames +show create table mysql.vtmd_template; +Table Create Table +vtmd_template CREATE TABLE `vtmd_template` ( + `start` bigint(20) unsigned GENERATED ALWAYS AS ROW START COMMENT 'TRX_ID of table lifetime start', + `end` bigint(20) unsigned GENERATED ALWAYS AS ROW END NOT NULL COMMENT 'TRX_ID of table lifetime end', + `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT 'Table name during period [start, end)', + `archive_name` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT 'Name of archive table', + `col_renames` blob DEFAULT NULL COMMENT 'Column name mappings from previous lifetime', + PRIMARY KEY (`end`), + KEY `archive_name` (`archive_name`), + PERIOD FOR SYSTEM_TIME (`start`, `end`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 WITH SYSTEM VERSIONING +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +12 1 1 1 1 +drop table t; +drop table t_vtmd; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/delete.result b/mysql-test/suite/versioning/r/delete.result new file mode 100644 index 00000000000..910d99c8643 --- /dev/null +++ b/mysql-test/suite/versioning/r/delete.result @@ -0,0 +1,374 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create or replace procedure test_01( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create or replace table t1( + XNo int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(XNo) values(0); +insert into t1(XNo) values(1); +insert into t1(XNo) values(2); +insert into t1(XNo) values(3); +insert into t1(XNo) values(4); +insert into t1(XNo) values(5); +insert into t1(XNo) values(6); +insert into t1(XNo) values(7); +insert into t1(XNo) values(8); +insert into t1(XNo) values(9); +set @str= concat('select XNo, ', +fields, " < '2038-01-19 03:14:07' + from t1 for system_time + between timestamp '0000-0-0 0:0:0' + and timestamp '2038-01-19 04:14:07'"); +prepare stmt from @str; execute stmt; +delete from t1 where XNo = 0; +execute stmt; +delete from t1 where XNo = 1; +execute stmt; +delete from t1 where XNo > 5; +create view vt1 as select XNo from t1; +select XNo from vt1; +delete from vt1 where XNo = 3; +select XNo from vt1; +execute stmt; drop prepare stmt; +drop view vt1; +drop table t1; +end~~ +create or replace procedure test_02( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat('create or replace table t1 ( + x int, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(x) values (1); +select sys_start into @sys_start from t1; +delete from t1; +select * from t1; +select x = 1 as A, sys_start = @sys_start as B, sys_end > sys_start as C +from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07'; +drop table t1; +end~~ +create or replace procedure test_03( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str0= concat('( + x int, + y int, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +set @str= concat('create or replace table t1', @str0); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @str= concat('create or replace table t2', @str0); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(x, y) values (1, 1), (2, 2), (3, 3), (14, 4); +insert into t2(x, y) values (11, 1), (12, 2), (13, 32), (14, 4); +delete t1, t2 from t1 join t2 where t1.y = 3 and t2.y = 32; +select x as t1_x from t1; +select x as t2_x from t2; +delete t1, t2 from t1 join t2 where t1.x = t2.x; +select x as t1_x from t1; +select x as t2_x from t2; +select x as t1_x_all from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07'; +select x as t2_x_all from t2 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07'; +drop table t1; +drop table t2; +end~~ +# Basic + delete from view +call test_01('timestamp(6)', 'myisam', 'sys_end'); +XNo sys_end < '2038-01-19 03:14:07' +0 0 +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +XNo sys_end < '2038-01-19 03:14:07' +0 1 +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +XNo sys_end < '2038-01-19 03:14:07' +0 1 +1 1 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +XNo +2 +3 +4 +5 +XNo +2 +4 +5 +XNo sys_end < '2038-01-19 03:14:07' +0 1 +1 1 +2 0 +3 1 +4 0 +5 0 +6 1 +7 1 +8 1 +9 1 +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' +0 0 +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' +0 1 +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' +0 1 +1 1 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +XNo +2 +3 +4 +5 +XNo +2 +4 +5 +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' +0 1 +1 1 +2 0 +3 1 +4 0 +5 0 +6 1 +7 1 +8 1 +9 1 +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +12 1 1 1 1 +13 1 1 1 1 +14 1 1 1 1 +# Check sys_start, sys_end +call test_02('timestamp(6)', 'myisam', 'sys_end'); +x sys_start sys_end +A B C +1 1 1 +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x sys_start sys_end +A B C +1 1 1 +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +# Multi-delete +call test_03('timestamp(6)', 'myisam', 'sys_end'); +t1_x +1 +2 +14 +t2_x +11 +12 +14 +t1_x +1 +2 +t2_x +11 +12 +t1_x_all +1 +2 +3 +14 +t2_x_all +11 +12 +13 +14 +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +t1_x +1 +2 +14 +t2_x +11 +12 +14 +t1_x +1 +2 +t2_x +11 +12 +t1_x_all +1 +2 +3 +14 +t2_x_all +11 +12 +13 +14 +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +drop procedure test_01; +drop procedure test_02; +drop procedure test_03; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/derived.result b/mysql-test/suite/versioning/r/derived.result new file mode 100644 index 00000000000..04a237f6428 --- /dev/null +++ b/mysql-test/suite/versioning/r/derived.result @@ -0,0 +1,181 @@ +create table emp +( +emp_id int, +name varchar(127), +mgr int +) with system versioning; +insert into emp values (1, 'bill', 0), +(2, 'bill', 1), +(3, 'kate', 1); +set @ts=now(6); +delete from emp; +insert into emp values (4, 'john', 1); +with ancestors as (select * from emp) select * from ancestors; +emp_id name mgr +4 john 1 +set @tmp= "with ancestors as (select * from emp) select * from ancestors"; +prepare stmt from @tmp; +execute stmt; +emp_id name mgr +4 john 1 +drop prepare stmt; +with ancestors as (select * from emp for system_time all) select * from ancestors; +emp_id name mgr +1 bill 0 +2 bill 1 +3 kate 1 +4 john 1 +set @tmp= "with ancestors as (select * from emp for system_time all) select * from ancestors"; +prepare stmt from @tmp; +execute stmt; +emp_id name mgr +1 bill 0 +2 bill 1 +3 kate 1 +4 john 1 +drop prepare stmt; +with recursive ancestors as (select * from emp) select * from ancestors; +emp_id name mgr +4 john 1 +set @tmp= "with recursive ancestors as (select * from emp) select * from ancestors"; +prepare stmt from @tmp; +execute stmt; +emp_id name mgr +4 john 1 +drop prepare stmt; +select emp_id from (select emp_id from emp where sys_trx_end>'2031-1-1') as tmp; +emp_id +4 +set @tmp= "select emp_id from (select emp_id from emp where sys_trx_end>'2031-1-1') as tmp"; +prepare stmt from @tmp; +execute stmt; +emp_id +4 +drop prepare stmt; +with recursive +ancestors +as +( +select e.emp_id, e.name, e.mgr +from emp as e +where name = 'john' + union +select ee.emp_id, ee.name, ee.mgr +from emp as ee, ancestors as a +where ee.mgr = a.emp_id +) +select * from ancestors; +emp_id name mgr +4 john 1 +set @tmp= " +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr + from emp as e + where name = 'john' + union + select ee.emp_id, ee.name, ee.mgr + from emp as ee, ancestors as a + where ee.mgr = a.emp_id +) +select * from ancestors"; +prepare stmt from @tmp; +execute stmt; +emp_id name mgr +4 john 1 +drop prepare stmt; +with recursive +ancestors +as +( +select e.emp_id, e.name, e.mgr +from emp as e +where name = 'bill' + system_time as of timestamp @ts +union +select ee.emp_id, ee.name, ee.mgr +from emp as ee, ancestors as a +where ee.mgr = a.emp_id +system_time as of timestamp @ts +) +select * from ancestors; +emp_id name mgr +1 bill 0 +2 bill 1 +3 kate 1 +set @tmp= " +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr + from emp as e + where name = 'bill' + system_time as of timestamp @ts + union + select ee.emp_id, ee.name, ee.mgr + from emp as ee, ancestors as a + where ee.mgr = a.emp_id + system_time as of timestamp @ts +) +select * from ancestors"; +prepare stmt from @tmp; +execute stmt; +emp_id name mgr +1 bill 0 +2 bill 1 +3 kate 1 +drop prepare stmt; +drop table emp; +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int) with system versioning; +insert into t1 values (1); +set @t0= now(6); +insert into t1 values (2); +delete from t1 where x = 1; +insert into t2 values (10); +select * from (select *, t1.sys_trx_end, t1.sys_trx_end as endo from t1) as s0; +ERROR HY000: Derived table is prohibited: multiple end system fields `t1.sys_trx_end`, `t1.sys_trx_end` in query! +select * from (select *, t1.sys_trx_end, t2.sys_trx_start from t1, t2) as s0; +ERROR HY000: Derived table is prohibited: system fields from multiple tables `t1`, `t2` in query! +select * from (select * from t1 for system_time as of timestamp @t0, t2) as s0; +x y +1 10 +with s1 as (select * from t1 for system_time as of timestamp @t0, t2) select * from s1; +x y +1 10 +select * from (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) as s2; +y x +10 1 +with s3 as (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) select * from s3; +y x +10 1 +select * from (select *, t1.sys_trx_start from t2 for system_time as of now, t1) as s4 system_time as of timestamp @t0; +y x +10 1 +with s5 as (select *, t1.sys_trx_start from t2 for system_time as of now, t1) select * from s5 for system_time as of timestamp @t0; +y x +10 1 +with s6 as (select *, t1.sys_trx_start from t2 for system_time as of now, t1) select * from s6 system_time as of timestamp @t0; +y x +10 1 +set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'"); +prepare q from @q; +execute q; +drop prepare q; +select * from vt1; +x +1 +select * from (select * from vt1, t2) as s0; +x y +1 10 +select * from (select *, vt1.sys_trx_end from t2, vt1) as s0; +y x +10 1 +select * from (select *, vt1.sys_trx_start from t2 for system_time as of now, vt1) as s0 system_time as of timestamp @t0; +y x +10 1 +drop table t1, t2; +drop view vt1; diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result new file mode 100644 index 00000000000..3903bee2f00 --- /dev/null +++ b/mysql-test/suite/versioning/r/foreign.result @@ -0,0 +1,172 @@ +create table parent( +id int unique key +) engine innodb; +create table child( +parent_id int, +foreign key(parent_id) references parent(id) +on delete restrict +on update restrict +) engine innodb with system versioning; +insert into parent values(1); +insert into child values(1); +delete from parent where id = 1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +delete from child where parent_id = 1; +delete from parent where id = 1; +insert into parent values(1); +insert into child values(1); +update parent set id=id+1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +delete from child; +update parent set id=id+1; +select * from child for system_time from timestamp '1-1-1' to timestamp now(6); +parent_id +1 +1 +drop table child; +drop table parent; +create table parent( +id int(10) unsigned unique key +) engine innodb; +create table child( +parent_id int(10) unsigned primary key, +foreign key(parent_id) references parent(id) +) engine innodb with system versioning; +insert into parent values(1); +insert into child values(1); +delete from parent where id = 1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +drop table child; +drop table parent; +create table parent( +id int unique key +) engine innodb; +create table child( +parent_id int, +foreign key(parent_id) references parent(id) +on delete cascade +on update cascade +) engine innodb with system versioning; +insert into parent values(1); +insert into child values(1); +delete from parent where id = 1; +select * from child; +parent_id +select * from child for system_time all; +parent_id +1 +insert into parent values(1); +insert into child values(1); +update parent set id = id + 1; +select * from child; +parent_id +2 +select * from child for system_time all; +parent_id +1 +2 +drop table child; +drop table parent; +create or replace table parent ( +id int primary key +) with system versioning +engine innodb; +create or replace table child ( +x int, +parent_id int not null, +constraint `parent-fk` + foreign key (parent_id) references parent (id) +on delete cascade +on update restrict +) +engine innodb; +insert into parent (id) values (2); +insert into child (x, parent_id) values (2, 2); +delete from parent; +select * from child; +x parent_id +drop table child; +drop table parent; +create or replace table parent ( +id int primary key +) +engine innodb; +create or replace table child ( +id int primary key, +parent_id int not null, +constraint `parent-fk` + foreign key (parent_id) references parent (id) +on delete cascade +on update restrict +) with system versioning +engine innodb; +insert into parent (id) values (3); +insert into child (id, parent_id) values (3, 3); +delete from parent; +select * from child; +id parent_id +select * from child for system_time all; +id parent_id +3 3 +drop table child; +drop table parent; +create table parent( +id int unique key +) engine innodb; +create table child( +parent_id int, +foreign key(parent_id) references parent(id) +on delete set null +on update set null +) engine innodb with system versioning; +insert into parent values(1); +insert into child values(1); +delete from child; +insert into child values(1); +delete from parent where id = 1; +select * from child; +parent_id +NULL +select * from child for system_time from timestamp '1-1-1' to timestamp now(6); +parent_id +1 +NULL +delete from child; +insert into parent values(1); +insert into child values(1); +update parent set id=id+1; +select * from child; +parent_id +NULL +select * from child for system_time from timestamp '1-1-1' to timestamp now(6); +parent_id +1 +NULL +NULL +drop table child; +drop table parent; +create or replace table parent( +id int unique key +) engine innodb with system versioning; +create or replace table child( +parent_id int, +foreign key(parent_id) references parent(id) +) engine innodb; +insert into parent values(1); +insert into child values(1); +delete from parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +update parent set id=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +delete from child; +delete from parent; +insert into child values(1); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +insert into parent values(1); +insert into child values(1); +delete from parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +update parent set id=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)) +drop table child; +drop table parent; diff --git a/mysql-test/suite/versioning/r/insert.result b/mysql-test/suite/versioning/r/insert.result new file mode 100644 index 00000000000..4bfa4fe0720 --- /dev/null +++ b/mysql-test/suite/versioning/r/insert.result @@ -0,0 +1,371 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure test_01( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(x, y) values(3, 4); +insert into t1(x, y) values(2, 3); +insert into t1 values(40, 33); +set @str= concat('select x, y, ', fields, ' from t1'); +prepare stmt from @str; execute stmt; drop prepare stmt; +drop table t1; +end~~ +create procedure test_02( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1( + id int unsigned auto_increment primary key, + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(x, y) values(33, 44); +insert into t1(id, x, y) values(20, 33, 44); +insert into t1 values(40, 33, 44); +set @str= concat('select id, x, y, ', fields, ' from t1'); +prepare stmt from @str; execute stmt; drop prepare stmt; +drop table t1; +end~~ +create procedure test_03( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +create view vt1_1 as select x, y from t1; +insert into t1(x, y) values(8001, 9001); +insert into vt1_1(x, y) values(1001, 2001); +insert into vt1_1 values(1002, 2002); +set @str= concat('select x, y, ', fields, ' from t1'); +prepare stmt from @str; execute stmt; drop prepare stmt; +select x, y from vt1_1; +end~~ +create procedure test_04( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1( + id bigint primary key, + a int, + b int) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1 values(1, 1, 1); +select sys_trx_start, sys_trx_end from t1 into @sys_start, @sys_end; +select id, a, b from t1; +insert into t1 values(2, 2, 2); +select id, a, b, sys_trx_start > @sys_start as C, sys_trx_end = @sys_end as D from t1 where id = 2; +drop table t1; +end~~ +create procedure test_05( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat('( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +set @str2= concat('create table t1', @str); +prepare stmt from @str2; execute stmt; drop prepare stmt; +set @str2= concat('create table t2', @str); +prepare stmt from @str2; execute stmt; drop prepare stmt; +insert into t1(x, y) values +(1, 1000), +(2, 2000), +(3, 3000), +(4, 4000), +(5, 5000), +(6, 6000), +(7, 7000), +(8, 8000), +(9, 9000); +delete from t1 where x >= 1; +insert into t1(x, y) values +(1, 1001), +(2, 2001), +(3, 3001), +(4, 4001), +(5, 5001), +(6, 6001), +(7, 7001), +(8, 8001), +(9, 9001); +insert into t2 select x, y from t1 for system_time between timestamp '0000-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; +select x, y from t1; +select x, y from t2; +drop table t1; +drop table t2; +end~~ +call test_01('timestamp(6)', 'myisam', 'sys_end'); +x y sys_end +3 4 2038-01-19 03:14:07.999999 +2 3 2038-01-19 03:14:07.999999 +40 33 2038-01-19 03:14:07.999999 +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y vtq_commit_ts(sys_end) +3 4 2038-01-19 03:14:07.999999 +2 3 2038-01-19 03:14:07.999999 +40 33 2038-01-19 03:14:07.999999 +call test_02('timestamp(6)', 'myisam', 'sys_end'); +id x y sys_end +1 33 44 2038-01-19 03:14:07.999999 +20 33 44 2038-01-19 03:14:07.999999 +40 33 44 2038-01-19 03:14:07.999999 +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +id x y vtq_commit_ts(sys_end) +1 33 44 2038-01-19 03:14:07.999999 +20 33 44 2038-01-19 03:14:07.999999 +40 33 44 2038-01-19 03:14:07.999999 +call test_03('timestamp(6)', 'myisam', 'sys_end'); +x y sys_end +8001 9001 2038-01-19 03:14:07.999999 +1001 2001 2038-01-19 03:14:07.999999 +1002 2002 2038-01-19 03:14:07.999999 +x y +8001 9001 +1001 2001 +1002 2002 +drop table t1; +drop view vt1_1; +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y vtq_commit_ts(sys_end) +8001 9001 2038-01-19 03:14:07.999999 +1001 2001 2038-01-19 03:14:07.999999 +1002 2002 2038-01-19 03:14:07.999999 +x y +8001 9001 +1001 2001 +1002 2002 +drop table t1; +drop view vt1_1; +call test_04('timestamp(6)', 'myisam', 'sys_end'); +id a b +1 1 1 +id a b C D +2 2 2 1 1 +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +id a b +1 1 1 +id a b C D +2 2 2 1 1 +call test_05('timestamp(6)', 'myisam', 'sys_end'); +x y +1 1001 +2 2001 +3 3001 +4 4001 +5 5001 +6 6001 +7 7001 +8 8001 +9 9001 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +1 1001 +2 2001 +3 3001 +4 4001 +5 5001 +6 6001 +7 7001 +8 8001 +9 9001 +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y +1 1001 +2 2001 +3 3001 +4 4001 +5 5001 +6 6001 +7 7001 +8 8001 +9 9001 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +1 1001 +2 2001 +3 3001 +4 4001 +5 5001 +6 6001 +7 7001 +8 8001 +9 9001 +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +12 1 1 1 1 +13 1 1 1 1 +14 1 1 1 1 +15 1 1 1 1 +create table t1( +x int unsigned, +sys_start bigint unsigned generated always as row start, +sys_end bigint unsigned generated always as row end, +period for system_time (sys_start, sys_end)) +with system versioning engine=innodb; +create table t2(x int unsigned) engine=innodb; +start transaction; +insert into t1(x) values(1); +commit; +call verify_vtq; +No A B C D +1 1 1 1 1 +start transaction; +insert into t2(x) values(1); +savepoint a; +insert into t1(x) values(1); +rollback to a; +commit; +call verify_vtq; +No A B C D +drop table t1; +drop table t2; +drop procedure test_01; +drop procedure test_02; +drop procedure test_03; +drop procedure test_04; +drop procedure test_05; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/optimized.result b/mysql-test/suite/versioning/r/optimized.result new file mode 100644 index 00000000000..a89180bbabd --- /dev/null +++ b/mysql-test/suite/versioning/r/optimized.result @@ -0,0 +1,126 @@ +create table t ( +a int, +b int without system versioning +) with system versioning; +insert into t values(1, 2); +insert into t values(3, 4); +select * from t; +a b +1 2 +3 4 +select a from t for system_time as of timestamp now(6); +a +1 +3 +select a, b, b+0 from t for system_time as of timestamp now(6); +a b b+0 +1 NULL NULL +3 NULL NULL +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +select * from t for system_time as of timestamp now(6); +a b +1 NULL +3 NULL +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select count(*) from t group by b system_time as of timestamp now(6); +count(*) +2 +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select * from t for system_time as of timestamp now(6) order by b asc; +a b +1 NULL +3 NULL +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +select * from t for system_time as of timestamp now(6) order by b desc; +a b +1 NULL +3 NULL +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +select * from t group by a having a=2 system_time as of timestamp now(6); +a b +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select * from t group by b having b=2 system_time as of timestamp now(6); +a b +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +select a from t where b=2 system_time as of timestamp now(6); +a +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select a from t where b=NULL system_time as of timestamp now(6); +a +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select a from t where b is NULL system_time as of timestamp now(6); +a +1 +3 +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select count(*), b from t group by b having b=NULL system_time as of timestamp now(6); +count(*) b +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +select a, b from t; +a b +1 2 +3 4 +select count(*) from t for system_time as of timestamp now(6) group by b; +count(*) +2 +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select * from t for system_time as of timestamp now(6) group by b having b=2; +a b +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +select a from t for system_time as of timestamp now(6) where b=2; +a +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select a from t for system_time as of timestamp now(6) where b=NULL; +a +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select a from t for system_time as of timestamp now(6) where b is NULL; +a +1 +3 +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select count(*), b from t for system_time as of timestamp now(6) group by b having b=NULL; +count(*) b +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +create or replace table t ( +a int, +b int not null without system versioning +) with system versioning; +insert into t values (1, 2), (3, 4); +select * from t for system_time as of timestamp now(6); +a b +1 NULL +3 NULL +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +select * from t for system_time as of timestamp now(6) where b is NULL; +a b +1 NULL +3 NULL +Warnings: +Warning 4102 Attempt to read unversioned field `b` in historical query +Warning 4102 Attempt to read unversioned field `b` in historical query +drop table t; diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result new file mode 100644 index 00000000000..2ba2b870ae9 --- /dev/null +++ b/mysql-test/suite/versioning/r/partition.result @@ -0,0 +1,378 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create table t1 (x int) +with system versioning +partition by range columns (x) ( +partition p0 values less than (100), +partition p1 values less than (1000)); +insert into t1 values (3), (300); +select * from t1; +x +3 +300 +select * from t1 partition (p0); +x +3 +select * from t1 partition (p1); +x +300 +delete from t1; +select * from t1; +x +select * from t1 for system_time all; +x +3 +300 +select * from t1 partition (p0) for system_time all; +x +3 +select * from t1 partition (p1) for system_time all; +x +300 +create or replace table t1 (x int) +partition by system_time ( +partition p0 versioning, +partition pn as of now); +ERROR HY000: System Versioning required: t1 +create or replace table t1 (x int); +alter table t1 +partition by system_time ( +partition p0 versioning, +partition pn as of now); +Got one of the listed errors +create or replace table t1 (x int) +with system versioning +partition by system_time ( +partition p0 as of now); +ERROR HY000: Wrong partitions consistency for `t1`: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW' +create or replace table t1 (x int) +with system versioning +partition by system_time ( +partition p0 as of now, +partition p1 as of now); +ERROR HY000: Wrong partitions consistency for `t1`: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW' +create or replace table t1 (x int) +with system versioning +partition by system_time ( +partition p0 versioning, +partition p1 versioning); +ERROR HY000: Wrong partitions consistency for `t1`: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW' +create or replace table t1 (x int) +with system versioning +partition by system_time ( +partition pn as of now, +partition p0 versioning); +ERROR HY000: Wrong partitions consistency for `t1`: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW' +create or replace table t1 (x int) +with system versioning +partition by system_time ( +partition p0 versioning, +partition pn as of now); +alter table t1 add partition ( +partition p1 as of now); +ERROR HY000: Wrong partitions consistency for `t1`: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW' +alter table t1 add partition ( +partition p1 versioning); +Warnings: +Warning 4078 Maybe missing parameters: no rotation condition for multiple `VERSIONING` partitions. +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x` int(11) DEFAULT NULL, + `sys_trx_start` ${SYS_TRX_TYPE} GENERATED ALWAYS AS ROW START, + `sys_trx_end` ${SYS_TRX_TYPE} GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=${INNODB_OR_MYISAM} DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING + PARTITION BY SYSTEM_TIME +(PARTITION p0 VERSIONING ENGINE = ${INNODB_OR_MYISAM}, + PARTITION p1 VERSIONING ENGINE = ${INNODB_OR_MYISAM}, + PARTITION pn AS OF NOW ENGINE = ${INNODB_OR_MYISAM}) +insert into t1 values (1), (2); +alter table t1 drop partition pn; +ERROR HY000: Wrong partitions consistency for `t1`: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW' +alter table t1 drop partition p1; +alter table t1 drop partition p0; +ERROR HY000: Wrong partitions consistency for `t1`: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW' +select x from t1; +x +1 +2 +create or replace table t1 (x int) +with system versioning +partition by system_time limit 1 ( +partition p0 versioning, +partition pn as of now); +alter table t1 change x big int; +create or replace table t1 (x int) +with system versioning +partition by system_time ( +partition p0 versioning, +partition pn as of now); +set @now= now(6); +insert into t1 values (1); +set @ts_start= sys_commit_ts('sys_trx_start'); +set @ts_end= sys_commit_ts('sys_trx_end'); +set @str= concat('select x, ', @ts_start, ' < @now as A, ', @ts_end, ' > @now as B from t1 partition (p0) for system_time all'); +prepare select_p0 from @str; +set @str= concat('select x, ', @ts_start, ' > @now as C, ', @ts_end, ' = timestamp\'2038-01-19 03:14:07.999999\' as D from t1 partition (pn) for system_time all'); +prepare select_pn from @str; +execute select_p0; +x A B +execute select_pn; +x C D +1 1 1 +explain partitions select * from t1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pn system NULL NULL NULL NULL 1 +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @now= now(6); +delete from t1; +execute select_p0; +x A B +1 1 1 +execute select_pn; +x C D +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all into @ts1'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +select @ts0 = @ts1; +@ts0 = @ts1 +1 +set @now= now(6); +insert into t1 values (2); +execute select_p0; +x A B +1 1 0 +execute select_pn; +x C D +2 1 1 +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @now= now(6); +update t1 set x = x + 1; +execute select_p0; +x A B +1 1 0 +2 1 1 +execute select_pn; +x C D +3 1 1 +drop prepare select_p0; +drop prepare select_pn; +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all where x = 2 into @ts1'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @str= concat('select ', @ts_end, ' from t1 partition (p0) for system_time all where x = 2 into @ts2'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts3'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +select @ts0 = @ts1; +@ts0 = @ts1 +1 +select @ts2 = @ts3; +@ts2 = @ts3 +1 +create or replace table t1 (x int) +with system versioning +partition by system_time limit 0 ( +partition p0 versioning, +partition p1 versioning, +partition pn as of now); +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'LIMIT' +create or replace table t1 (x int) +with system versioning +partition by system_time limit 1 ( +partition p0 versioning, +partition p1 versioning, +partition pn as of now); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x` int(11) DEFAULT NULL, + `sys_trx_start` ${SYS_TRX_TYPE} GENERATED ALWAYS AS ROW START, + `sys_trx_end` ${SYS_TRX_TYPE} GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=${INNODB_OR_MYISAM} DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING + PARTITION BY SYSTEM_TIME LIMIT 1 +(PARTITION p0 VERSIONING ENGINE = ${INNODB_OR_MYISAM}, + PARTITION p1 VERSIONING ENGINE = ${INNODB_OR_MYISAM}, + PARTITION pn AS OF NOW ENGINE = ${INNODB_OR_MYISAM}) +alter table t1 drop partition non_existent; +ERROR HY000: Error in list of partitions to DROP +insert into t1 values (1), (2); +select * from t1 partition (pn); +x +1 +2 +delete from t1; +Warnings: +Note 4079 Switching from partition `p0` to `p1` +select * from t1 partition (p0) for system_time all; +x +1 +select * from t1 partition (p1) for system_time all; +x +2 +insert into t1 values (3); +delete from t1; +Warnings: +Warning 4077 Using full partition `p1`, need more VERSIONING partitions! +select * from t1 partition (p1) for system_time all; +x +2 +3 +create or replace table t1 (x int) +with system versioning +partition by system_time interval 0 second ( +partition p0 versioning, +partition p1 versioning, +partition pn as of now); +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL' +create or replace table t1 (x int) +with system versioning +partition by system_time interval 1 second ( +partition p0 versioning, +partition p1 versioning, +partition pn as of now); +insert into t1 values (1), (2), (3); +select * from t1 partition (pn); +x +1 +2 +3 +delete from t1; +select * from t1 partition (p0) for system_time all; +x +1 +2 +3 +insert into t1 values (4); +delete from t1; +Warnings: +Note 4079 Switching from partition `p0` to `p1` +select * from t1 partition (p1) for system_time all; +x +4 +create or replace table t1 (x int) +with system versioning +partition by system_time limit 1 +subpartition by key (x) +subpartitions 2 ( +partition p0 versioning, +partition p1 versioning, +partition pn as of now); +insert into t1 (x) values (1), (2), (3); +select * from t1 partition (pnsp0); +x +1 +3 +select * from t1 partition (pnsp1); +x +2 +delete from t1; +Warnings: +Note 4079 Switching from partition `p0` to `p1` +Warning 4077 Using full partition `p1`, need more VERSIONING partitions! +select * from t1 partition (p0sp0) for system_time all; +x +1 +select * from t1 partition (p0sp1) for system_time all; +x +select * from t1 partition (p1sp0) for system_time all; +x +3 +select * from t1 partition (p1sp1) for system_time all; +x +2 +drop table t1; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/rpl_mixed.result b/mysql-test/suite/versioning/r/rpl_mixed.result new file mode 100644 index 00000000000..b91c8fd33c8 --- /dev/null +++ b/mysql-test/suite/versioning/r/rpl_mixed.result @@ -0,0 +1,118 @@ +include/master-slave.inc +[connection master] +connection slave; +connection master; +CREATE TABLE t1 (x int) with system versioning; +insert into t1 values (1); +SELECT * FROM t1; +x +1 +delete from t1; +select * from t1; +x +select * from t1 for system_time all; +x +1 +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +connection master; +insert into t1 values (2); +connection slave; +select * from t1; +x +2 +connection master; +update t1 set x = 3; +connection slave; +select * from t1; +x +3 +select * from t1 for system_time all; +x +1 +3 +2 +connection master; +create or replace table t1 (x int primary key); +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +connection slave; +select * from t1; +x +1 +select * from t1 for system_time all; +x +1 +connection master; +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +1 +2 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +2 +connection master; +create or replace table t1 (x int); +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +2 +1 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +2 +1 +connection master; +create or replace table t1 (x int) with system versioning; +create or replace table t2 (x int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +update t1, t2 set t1.x=11, t2.x=22; +connection slave; +select * from t1; +x +11 +select * from t2; +x +22 +select * from t1 for system_time all; +x +11 +1 +select * from t2 for system_time all; +x +22 +2 +connection master; +drop table t1, t2; +include/rpl_end.inc diff --git a/mysql-test/suite/versioning/r/rpl_row.result b/mysql-test/suite/versioning/r/rpl_row.result new file mode 100644 index 00000000000..b91c8fd33c8 --- /dev/null +++ b/mysql-test/suite/versioning/r/rpl_row.result @@ -0,0 +1,118 @@ +include/master-slave.inc +[connection master] +connection slave; +connection master; +CREATE TABLE t1 (x int) with system versioning; +insert into t1 values (1); +SELECT * FROM t1; +x +1 +delete from t1; +select * from t1; +x +select * from t1 for system_time all; +x +1 +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +connection master; +insert into t1 values (2); +connection slave; +select * from t1; +x +2 +connection master; +update t1 set x = 3; +connection slave; +select * from t1; +x +3 +select * from t1 for system_time all; +x +1 +3 +2 +connection master; +create or replace table t1 (x int primary key); +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +connection slave; +select * from t1; +x +1 +select * from t1 for system_time all; +x +1 +connection master; +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +1 +2 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +2 +connection master; +create or replace table t1 (x int); +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +2 +1 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +2 +1 +connection master; +create or replace table t1 (x int) with system versioning; +create or replace table t2 (x int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +update t1, t2 set t1.x=11, t2.x=22; +connection slave; +select * from t1; +x +11 +select * from t2; +x +22 +select * from t1 for system_time all; +x +11 +1 +select * from t2 for system_time all; +x +22 +2 +connection master; +drop table t1, t2; +include/rpl_end.inc diff --git a/mysql-test/suite/versioning/r/rpl_stmt.result b/mysql-test/suite/versioning/r/rpl_stmt.result new file mode 100644 index 00000000000..b91c8fd33c8 --- /dev/null +++ b/mysql-test/suite/versioning/r/rpl_stmt.result @@ -0,0 +1,118 @@ +include/master-slave.inc +[connection master] +connection slave; +connection master; +CREATE TABLE t1 (x int) with system versioning; +insert into t1 values (1); +SELECT * FROM t1; +x +1 +delete from t1; +select * from t1; +x +select * from t1 for system_time all; +x +1 +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +connection master; +insert into t1 values (2); +connection slave; +select * from t1; +x +2 +connection master; +update t1 set x = 3; +connection slave; +select * from t1; +x +3 +select * from t1 for system_time all; +x +1 +3 +2 +connection master; +create or replace table t1 (x int primary key); +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +connection slave; +select * from t1; +x +1 +select * from t1 for system_time all; +x +1 +connection master; +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +1 +2 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +2 +connection master; +create or replace table t1 (x int); +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +2 +1 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +2 +1 +connection master; +create or replace table t1 (x int) with system versioning; +create or replace table t2 (x int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +update t1, t2 set t1.x=11, t2.x=22; +connection slave; +select * from t1; +x +11 +select * from t2; +x +22 +select * from t1 for system_time all; +x +11 +1 +select * from t2 for system_time all; +x +22 +2 +connection master; +drop table t1, t2; +include/rpl_end.inc diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result new file mode 100644 index 00000000000..6c179d2e166 --- /dev/null +++ b/mysql-test/suite/versioning/r/select.result @@ -0,0 +1,398 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create or replace table t1 ( +x int unsigned, +y int unsigned +) with system versioning; +insert into t1 (x, y) values +(0, 100), +(1, 101), +(2, 102), +(3, 103), +(4, 104), +(5, 105), +(6, 106), +(7, 107), +(8, 108), +(9, 109); +set @t0= now(6); +delete from t1 where x = 3; +delete from t1 where x > 7; +insert into t1(x, y) values(3, 33); +select sys_trx_start from t1 where x = 3 and y = 33 into @t1; +select x, y from t1; +x y +0 100 +1 101 +2 102 +4 104 +5 105 +6 106 +7 107 +3 33 +select x as ASOF_x, y from t1 for system_time as of timestamp @t0; +ASOF_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; +FROMTO_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +BETWAND_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +3 33 +select x as ALL_x, y from t1 for system_time all; +ALL_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +3 33 +ASOF2_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +FROMTO2_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +BETWAND2_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +3 33 +create or replace table t1 ( +x int unsigned, +y int unsigned +) with system versioning; +create or replace table t2 ( +x int unsigned, +y int unsigned +) with system versioning; +insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5); +insert into t2 values (1, 2), (2, 1), (3, 1); +set @t0= now(6); +select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x; +IJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x; +LJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +4 4 NULL NULL +5 5 NULL NULL +select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x; +RJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +NULL NULL 2 1 +NULL NULL 3 1 +delete from t1; +delete from t2; +select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x +system_time as of timestamp @t0; +IJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x +system_time as of timestamp @t0; +LJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +4 4 NULL NULL +5 5 NULL NULL +select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x +system_time as of timestamp @t0; +RJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +NULL NULL 2 1 +NULL NULL 3 1 +drop table t1; +drop table t2; +create table t1( +A int +) with system versioning; +insert into t1 values(1); +select * from t1; +A +1 +create or replace table t1 (x int); +insert into t1 values (1); +select * from t1 for system_time all; +ERROR HY000: System Versioning required: t1 +create or replace table t1 (x int) with system versioning; +insert into t1 values (1); +select * from t1 for system_time all for update; +ERROR HY000: Versioned SELECT write-locking of history rows +create or replace table t1 (a int not null auto_increment primary key) with system versioning; +select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; +a +create or replace table t1 (a int) with system versioning; +create or replace table t2 (a int) with system versioning; +insert into t1 values(1); +insert into t2 values(1); +create view v1 as select * from t2 inner join t1 using (a); +select * from v1; +a +1 +drop view v1; +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create view vt1 as select a from t1; +select * from t1 natural join vt1; +a +1 +drop view vt1; +create or replace table t1(x int) with system versioning; +select * from (t1 as r left join t1 as u using (x)), t1; +x x +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create trigger read_end after update on t1 +for each row set @end = old.sys_trx_end; +update t1 set a=2; +select @end; +@end +MAX_RESULT +create or replace table t1 (a int) with system versioning; +create or replace table t2 (b int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +select * from (select * from t1 cross join t2) as tmp; +a b +1 2 +select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; +a b +1 2 +select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp; +a b +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +select * from t1 for system_time all natural left join t2 for system_time all; +a1 a2 +1 1 +2 1 +1 2 +2 2 +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +create or replace view v1 as select a1 from t1; +select * from v1 natural join t2; +a1 a2 +1 1 +2 1 +1 2 +2 2 +select * from v1 natural left join t2; +a1 a2 +1 1 +2 1 +1 2 +2 2 +select * from v1 natural right join t2; +a2 a1 +1 1 +2 1 +1 2 +2 2 +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1; +a a +2 1 +3 1 +2 2 +3 2 +2 3 +3 3 +1 NULL +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int) with system versioning; +insert into t1 values (1), (2), (3); +delete from t1 where x = 3; +insert into t2 values (1); +select * from t1, t2 system_time all; +x y +1 1 +2 1 +3 1 +select * from t1 for system_time all, t2 for system_time all system_time all; +ERROR HY000: Unused clause: 'SYSTEM_TIME' +drop view v1; +drop table t1, t2; +call innodb_verify_vtq(27); +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +12 1 1 1 1 +13 1 1 1 1 +14 1 1 1 1 +15 1 1 1 1 +16 1 1 1 1 +17 1 1 1 1 +18 1 1 1 1 +19 1 1 1 1 +20 1 1 1 1 +21 1 1 1 1 +22 1 1 1 1 +23 1 1 1 1 +24 1 1 1 1 +25 1 1 1 1 +26 1 1 1 1 +27 1 1 1 1 +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/select_sp.result b/mysql-test/suite/versioning/r/select_sp.result new file mode 100644 index 00000000000..44b7d4e25b4 --- /dev/null +++ b/mysql-test/suite/versioning/r/select_sp.result @@ -0,0 +1,441 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure test_01() +begin +declare engine varchar(255) default default_engine(); +declare sys_type varchar(255) default sys_datatype(); +declare fields varchar(255) default sys_commit_ts('sys_start'); +set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1 (x, y) values +(0, 100), +(1, 101), +(2, 102), +(3, 103), +(4, 104), +(5, 105), +(6, 106), +(7, 107), +(8, 108), +(9, 109); +set @t0= now(6); +if engine = 'innodb' then +select sys_start from t1 limit 1 into @x0; +end if; +delete from t1 where x = 3; +delete from t1 where x > 7; +insert into t1(x, y) values(3, 33); +select sys_start from t1 where x = 3 and y = 33 into @t1; +if engine = 'innodb' then +set @x1= @t1; +select vtq_commit_ts(@x1) into @t1; +end if; +select x, y from t1; +select x as ASOF_x, y from t1 for system_time as of timestamp @t0; +select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as ALL_x, y from t1 for system_time all; +if engine = 'innodb' then +select x as ASOF2_x, y from t1 for system_time as of @x0; +select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1; +select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1; +else +select x as ASOF2_x, y from t1 for system_time as of @t0; +select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; +select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +end if; +drop table t1; +end~~ +create or replace procedure test_02() +begin +declare engine varchar(255) default default_engine(); +declare sys_type varchar(255) default sys_datatype(); +declare fields varchar(255) default sys_commit_ts('sys_start'); +set @str0= concat('( + x int, + y int, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +set @str= concat('create or replace table t1', @str0); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @str= concat('create or replace table t2', @str0); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5); +insert into t2 values (1, 2), (2, 1), (3, 1); +set @t0= now(6); +select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x; +select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x; +select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x; +delete from t1; +delete from t2; +select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x +system_time as of timestamp @t0; +select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x +system_time as of timestamp @t0; +select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x +system_time as of timestamp @t0; +drop table t1; +drop table t2; +end~~ +call test_01(); +x y +0 100 +1 101 +2 102 +4 104 +5 105 +6 106 +7 107 +3 33 +ASOF_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +FROMTO_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +BETWAND_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +3 33 +ALL_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +3 33 +ASOF2_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +FROMTO2_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +BETWAND2_x y +0 100 +1 101 +2 102 +3 103 +4 104 +5 105 +6 106 +7 107 +8 108 +9 109 +3 33 +call test_02(); +IJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +LJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +4 4 NULL NULL +5 5 NULL NULL +RJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +NULL NULL 2 1 +NULL NULL 3 1 +IJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +LJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +4 4 NULL NULL +5 5 NULL NULL +RJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +NULL NULL 2 1 +NULL NULL 3 1 +create table t1( +A int +) with system versioning; +insert into t1 values(1); +select * from t1; +A +1 +create or replace table t1 (x int); +insert into t1 values (1); +select * from t1 for system_time all; +ERROR HY000: System Versioning required: t1 +create or replace table t1 (x int) with system versioning; +insert into t1 values (1); +select * from t1 for system_time all for update; +ERROR HY000: Versioned SELECT write-locking of history rows +create or replace table t1 (a int not null auto_increment primary key) with system versioning; +select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; +a +create or replace table t1 (a int) with system versioning; +create or replace table t2 (a int) with system versioning; +insert into t1 values(1); +insert into t2 values(1); +create view v1 as select * from t2 inner join t1 using (a); +select * from v1; +a +1 +drop view v1; +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create view vt1 as select a from t1; +select * from t1 natural join vt1; +a +1 +drop view vt1; +create or replace table t1(x int) with system versioning; +select * from (t1 as r left join t1 as u using (x)), t1; +x x +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create trigger read_end after update on t1 +for each row set @end = old.sys_trx_end; +update t1 set a=2; +select @end; +@end +MAX_RESULT +create or replace table t1 (a int) with system versioning; +create or replace table t2 (b int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +select * from (select * from t1 cross join t2) as tmp; +a b +1 2 +select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; +a b +1 2 +select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp; +a b +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +select * from t1 for system_time all natural left join t2 for system_time all; +a1 a2 +1 1 +2 1 +1 2 +2 2 +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +create or replace view v1 as select a1 from t1; +select * from v1 natural join t2; +a1 a2 +1 1 +2 1 +1 2 +2 2 +select * from v1 natural left join t2; +a1 a2 +1 1 +2 1 +1 2 +2 2 +select * from v1 natural right join t2; +a2 a1 +1 1 +2 1 +1 2 +2 2 +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1; +a a +2 1 +3 1 +2 2 +3 2 +2 3 +3 3 +1 NULL +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int) with system versioning; +insert into t1 values (1), (2), (3); +delete from t1 where x = 3; +insert into t2 values (1); +select * from t1, t2 system_time all; +x y +1 1 +2 1 +3 1 +select * from t1 for system_time all, t2 for system_time all system_time all; +ERROR HY000: Unused clause: 'SYSTEM_TIME' +drop view v1; +drop table t1, t2; +call innodb_verify_vtq(27); +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +12 1 1 1 1 +13 1 1 1 1 +14 1 1 1 1 +15 1 1 1 1 +16 1 1 1 1 +17 1 1 1 1 +18 1 1 1 1 +19 1 1 1 1 +20 1 1 1 1 +21 1 1 1 1 +22 1 1 1 1 +23 1 1 1 1 +24 1 1 1 1 +25 1 1 1 1 +26 1 1 1 1 +27 1 1 1 1 +drop procedure test_01; +drop procedure test_02; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/simple.result b/mysql-test/suite/versioning/r/simple.result new file mode 100644 index 00000000000..e0af556f073 --- /dev/null +++ b/mysql-test/suite/versioning/r/simple.result @@ -0,0 +1,71 @@ +create or replace table dept ( +dept_id int(10) primary key, +name varchar(100) +) +with system versioning; +create or replace table emp ( +emp_id int(10) primary key, +dept_id int(10), +name varchar(100), +salary int(10), +constraint `dept-emp-fk` + foreign key (dept_id) references dept (dept_id) +on delete cascade +on update restrict +) +with system versioning; +select now() into @ts_0; +insert into dept (dept_id, name) values (10, "accounting"); +commit; +select vtq_commit_ts(sys_trx_start) into @ts_1 from dept where dept_id=10; +insert into emp (emp_id, name, salary, dept_id) values (1, "bill", 1000, 10); +commit; +select vtq_commit_ts(sys_trx_start) into @ts_2 from emp where name="bill"; +select * from emp; +emp_id dept_id name salary +1 10 bill 1000 +update emp set salary=2000 where name="bill"; +commit; +select vtq_commit_ts(sys_trx_start) into @ts_3 from emp where name="bill"; +select * from emp; +emp_id dept_id name salary +1 10 bill 2000 +select * from emp for system_time as of timestamp @ts_2; +emp_id dept_id name salary +1 10 bill 1000 +select * from emp for system_time as of timestamp @ts_3; +emp_id dept_id name salary +1 10 bill 2000 +select * from emp e, dept d +where d.dept_id = 10 +and d.dept_id = e.dept_id; +emp_id dept_id name salary dept_id name +1 10 bill 2000 10 accounting +select * from emp e, dept d +where d.dept_id = 10 +and d.dept_id = e.dept_id +system_time from timestamp @ts_1 to timestamp @ts_2; +emp_id dept_id name salary sys_trx_start sys_trx_end dept_id name sys_trx_start sys_trx_end +select * from emp e, dept d +where d.dept_id = 10 +and d.dept_id = e.dept_id +system_time as of timestamp @ts_0; +emp_id dept_id name salary dept_id name +select * from emp e, dept d +where d.dept_id = 10 +and d.dept_id = e.dept_id +system_time as of timestamp @ts_1; +emp_id dept_id name salary dept_id name +select * from emp e, dept d +where d.dept_id = 10 +and d.dept_id = e.dept_id +system_time as of timestamp @ts_2; +emp_id dept_id name salary dept_id name +1 10 bill 1000 10 accounting +select * from emp e, dept d +where d.dept_id = 10 +and d.dept_id = e.dept_id +system_time as of timestamp @ts_3; +emp_id dept_id name salary dept_id name +1 10 bill 2000 10 accounting +drop table emp, dept; diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result new file mode 100644 index 00000000000..a9cc7d3aec3 --- /dev/null +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -0,0 +1,150 @@ +create table t (a int) with system versioning; +insert into t values (1); +update t set a= 2; +show global variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp NOW +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp NOW +select * from t; +a +2 +set versioning_current_timestamp = '2031-1-1 0:0:0'; +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 2031-01-01 00:00:00.000000 +select * from t; +a +2 +set versioning_current_timestamp = '2011-1-1 0:0:0'; +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 2011-01-01 00:00:00.000000 +select * from t; +a +set versioning_current_timestamp = 'all'; +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp ALL +select * from t; +a +2 +1 +create view vt as select * from t; +select * from t; +a +2 +1 +drop view vt; +select * from (select * from t) as tt; +a +2 +1 +set global versioning_current_timestamp= 'alley'; +ERROR 42000: Variable 'versioning_current_timestamp' can't be set to the value of 'alley' +set global versioning_current_timestamp= null; +ERROR 42000: Variable 'versioning_current_timestamp' can't be set to the value of 'NULL' +set global versioning_current_timestamp= 1; +ERROR 42000: Incorrect argument type to variable 'versioning_current_timestamp' +set global versioning_current_timestamp= 1.1; +ERROR 42000: Incorrect argument type to variable 'versioning_current_timestamp' +set versioning_current_timestamp= 'alley'; +ERROR 42000: Variable 'versioning_current_timestamp' can't be set to the value of 'alley' +set versioning_current_timestamp= null; +ERROR 42000: Variable 'versioning_current_timestamp' can't be set to the value of 'NULL' +set versioning_current_timestamp= 1; +ERROR 42000: Incorrect argument type to variable 'versioning_current_timestamp' +set versioning_current_timestamp= 1.1; +ERROR 42000: Incorrect argument type to variable 'versioning_current_timestamp' +set global versioning_current_timestamp= '1911-11-11 11:11:11.1111119'; +show global variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1911-11-11 11:11:11.111111 +set global versioning_current_timestamp= '1900-01-01 00:00:00'; +show global variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1900-01-01 00:00:00.000000 +set global versioning_current_timestamp= timestamp'1911-11-11 11:11:11.1111119'; +Warnings: +Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' +show global variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1911-11-11 11:11:11.111111 +set @ts= timestamp'1900-01-01 00:00:00'; +set global versioning_current_timestamp= @ts; +show global variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1900-01-01 00:00:00.000000 +set versioning_current_timestamp= '1911-11-11 11:11:11.1111119'; +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1911-11-11 11:11:11.111111 +set versioning_current_timestamp= '1900-01-01 00:00:00'; +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1900-01-01 00:00:00.000000 +set versioning_current_timestamp= timestamp'1911-11-11 11:11:11.1111119'; +Warnings: +Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1911-11-11 11:11:11.111111 +set @ts= timestamp'1900-01-01 00:00:00'; +set versioning_current_timestamp= @ts; +show variables like 'versioning_current_timestamp'; +Variable_name Value +versioning_current_timestamp 1900-01-01 00:00:00.000000 +set global versioning_current_timestamp= 'now'; +set versioning_current_timestamp= 'now'; +show variables where variable_name = "versioning_hide"; +Variable_name Value +versioning_hide IMPLICIT +select * from t for system_time all; +a +2 +1 +set versioning_hide= AUTO; +select * from t; +a +2 +select * from t for system_time as of timestamp current_timestamp(6); +a +2 +select * from t for system_time all; +a sys_trx_start sys_trx_end +2 TIMESTAMP TIMESTAMP +1 TIMESTAMP TIMESTAMP +select * from t for system_time from '0-0-0' to current_timestamp(6); +a sys_trx_start sys_trx_end +2 TIMESTAMP TIMESTAMP +1 TIMESTAMP TIMESTAMP +select * from t for system_time between '0-0-0' and current_timestamp(6); +a sys_trx_start sys_trx_end +2 TIMESTAMP TIMESTAMP +1 TIMESTAMP TIMESTAMP +set versioning_hide= NEVER; +select * from t; +a sys_trx_start sys_trx_end +2 TIMESTAMP TIMESTAMP +set versioning_hide= FULL; +create or replace table t ( +x int, +st timestamp(6) generated always as row start, +en timestamp(6) generated always as row end, +period for system_time (st, en)) +with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `x` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +insert into t values (2); +delete from t; +select * from t; +x +select * from t for system_time all; +x +2 +drop table t; +set versioning_hide= IMPLICIT; diff --git a/mysql-test/suite/versioning/r/truncate.result b/mysql-test/suite/versioning/r/truncate.result new file mode 100644 index 00000000000..47647ade900 --- /dev/null +++ b/mysql-test/suite/versioning/r/truncate.result @@ -0,0 +1,37 @@ +create table t (a int); +truncate t to system_time now(); +ERROR HY000: System Versioning required: t +create or replace table t (a int) with system versioning; +insert into t values (1); +update t set a=2; +set @test = 'correct'; +create trigger trg_before before delete on t for each row set @test = 'incorrect'; +create trigger trg_after after delete on t for each row set @test = 'incorrect'; +truncate t to system_time now(6); +select @test from t; +@test +correct +drop table t; +create table t (a int) with system versioning; +insert into t values (1), (2); +update t set a=11 where a=1; +set @ts1=now(6); +update t set a=22 where a=2; +select * from t for system_time all; +a +11 +22 +1 +2 +truncate t to system_time timestamp @ts1; +select * from t for system_time all; +a +11 +22 +2 +truncate table t to system_time timestamp now(6); +select * from t for system_time all; +a +11 +22 +drop table t; diff --git a/mysql-test/suite/versioning/r/truncate_privilege.result b/mysql-test/suite/versioning/r/truncate_privilege.result new file mode 100644 index 00000000000..69a43ba8830 --- /dev/null +++ b/mysql-test/suite/versioning/r/truncate_privilege.result @@ -0,0 +1,33 @@ +connect root,localhost,root,,test; +connection root; +create database mysqltest; +create user mysqltest_1@localhost; +connect user1,localhost,mysqltest_1,,test; +connection user1; +connection root; +create table mysqltest.t (a int) with system versioning; +connection user1; +show grants; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' +truncate mysqltest.t to system_time now(); +ERROR 42000: DELETE VERSIONING ROWS command denied to user 'mysqltest_1'@'localhost' for table 't' +connection root; +grant delete versioning rows on mysqltest.* to mysqltest_1@localhost; +grant delete versioning rows on mysqltest.t to mysqltest_1@localhost; +connection user1; +show grants; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' +GRANT DELETE VERSIONING ROWS ON `mysqltest`.* TO 'mysqltest_1'@'localhost' +GRANT DELETE VERSIONING ROWS ON `mysqltest`.`t` TO 'mysqltest_1'@'localhost' +truncate mysqltest.t to system_time now(); +connection root; +grant all on *.* to mysqltest_1@localhost; +show grants for mysqltest_1@localhost; +Grants for mysqltest_1@localhost +GRANT ALL PRIVILEGES ON *.* TO 'mysqltest_1'@'localhost' +GRANT DELETE VERSIONING ROWS ON `mysqltest`.* TO 'mysqltest_1'@'localhost' +GRANT DELETE VERSIONING ROWS ON `mysqltest`.`t` TO 'mysqltest_1'@'localhost' +drop user mysqltest_1@localhost; +drop database mysqltest; diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result new file mode 100644 index 00000000000..d54add35def --- /dev/null +++ b/mysql-test/suite/versioning/r/update.result @@ -0,0 +1,594 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure test_01( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(x, y) values +(1, 1000), +(2, 2000), +(3, 3000), +(4, 4000), +(5, 5000), +(6, 6000), +(7, 7000), +(8, 8000), +(9, 9000); +select x, y from t1; +update t1 set y = y + 1 where x > 7; +select x, y from t1; +select x, y from t1 for system_time +between timestamp '0000-0-0 0:0:0' + and timestamp '2038-01-19 04:14:07'; +drop table t1; +end~~ +create procedure test_02( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1 ( + id bigint primary key, + x int, + y int without system versioning) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1 values(1, 1, 1); +set @ins_t= now(6); +select sys_trx_start into @tmp1 from t1; +update t1 set x= 11, y= 11 where id = 1; +select @tmp1 < sys_trx_start as A1, x, y from t1; +select sys_trx_start into @tmp1 from t1; +update t1 set y= 1 where id = 1; +select @tmp1 = sys_trx_start as A2, x from t1; +drop table t1; +end~~ +create procedure test_03( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1 ( + x int, + y int) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1 (x, y) values (1, 1), (2, 1), (3, 1); +start transaction; +update t1 set y= y + 1 where x = 3; +update t1 set y= y + 1 where x = 3; +commit; +select x, y from t1 for system_time +between timestamp '0000-0-0 0:0:0' + and timestamp '2038-01-19 04:14:07'; +drop table t1; +end~~ +create procedure test_04( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1 ( + id int primary key auto_increment, + x int) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @t0= now(6); +insert into t1 (x) values (1); +set @t1= now(6); +update t1 set x= 2 where id = 1; +set @t2= now(6); +update t1 set x= 3 where id = 1; +select x from t1 for system_time as of timestamp @t0; +select x from t1 for system_time as of timestamp @t1; +select x from t1 for system_time as of timestamp @t2; +select x from t1 for system_time as of timestamp now(6); +drop table t1; +end~~ +create procedure test_05( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat(' + create table t1( + x int unsigned, + sys_end ', sys_type, ' generated always as row end, + sys_start ', sys_type, ' generated always as row start, + y int unsigned, + period for system_time (sys_start, sys_end), + primary key(x, y)) + with system versioning + engine ', engine); +prepare stmt from @str; execute stmt; drop prepare stmt; +insert into t1(x, y) values +(1, 1000), +(2, 2000), +(3, 3000), +(4, 4000), +(5, 5000), +(6, 6000), +(7, 7000), +(8, 8000), +(9, 9000); +insert into t1(x, y) values(3, 3000) on duplicate key update y = y+1; +insert into t1(x, y) values(4, 4000) on duplicate key update y = y+1; +insert into t1(x, y) values(4, 4001) on duplicate key update y = y+1; +insert into t1(x, y) values(4, 4444) on duplicate key update y = y+1; +select x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; +select x, y from t1; +drop table t1; +end~~ +create procedure test_06( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat('( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); +set @str2= concat('create table t1', @str); +prepare stmt from @str2; execute stmt; drop prepare stmt; +set @str2= concat('create table t2', @str); +prepare stmt from @str2; execute stmt; drop prepare stmt; +insert into t1(x, y) values +(1, 1000), +(2, 2000), +(3, 3000), +(4, 4000), +(5, 5000), +(6, 6000), +(7, 7000), +(8, 8000), +(9, 9000); +insert into t2(x, y) values +(1, 1010), +(2, 2010), +(3, 3010), +(4, 4010), +(5, 5010), +(6, 6010), +(7, 7010), +(8, 8010), +(9, 9010); +update t1, t2 set t1.y = t1.x + t1.y, t2.y = t2.x + t2.y where t1.x > 7 and t2.x < 7; +select x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; +select x, y from t1; +select x, y from t2 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; +select x, y from t2; +drop table t1; +drop table t2; +end~~ +create procedure test_07( +sys_type varchar(255), +engine varchar(255), +fields varchar(255)) +begin +set @str= concat('( + id bigint primary key, + name varchar(128) with system versioning, + salary bigint) + engine ', engine); +set @str2= concat('create table t1', @str); +prepare stmt from @str2; execute stmt; drop prepare stmt; +set @str2= concat('create table t2', @str); +prepare stmt from @str2; execute stmt; drop prepare stmt; +insert into t1 values (1, "Jeremy", 3000); +insert into t2 values (1, "Jeremy", 4000); +select sys_trx_start into @tmp1 from t1; +select sys_trx_start into @tmp2 from t2; +update t1, t2 set t1.name= "Jerry", t2.name= "Jerry" where t1.id = t2.id and t1.name = "Jeremy"; +select @tmp1 < sys_trx_start as A1, name from t1; +select @tmp2 < sys_trx_start as A2, name from t2; +select sys_trx_start into @tmp1 from t1; +select sys_trx_start into @tmp2 from t2; +update t1, t2 set t1.salary= 2500, t2.salary= 2500 where t1.id = t2.id and t1.name = "Jerry"; +select @tmp1 = sys_trx_start as B1, salary from t1; +select @tmp2 = sys_trx_start as B2, salary from t2; +drop table t1; +drop table t2; +end~~ +call test_01('timestamp(6)', 'myisam', 'sys_end'); +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8001 +9 9001 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8001 +9 9001 +8 8000 +9 9000 +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8001 +9 9001 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8001 +9 9001 +8 8000 +9 9000 +call test_02('timestamp(6)', 'myisam', 'sys_end'); +A1 x y +1 11 11 +A2 x +1 11 +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +A1 x y +1 11 11 +A2 x +1 11 +call test_03('timestamp(6)', 'myisam', 'sys_end'); +x y +1 1 +2 1 +3 3 +3 1 +3 2 +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y +1 1 +2 1 +3 3 +3 1 +call test_04('timestamp(6)', 'myisam', 'sys_end'); +x +x +1 +x +2 +x +3 +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x +x +1 +x +2 +x +3 +call test_05('timestamp(6)', 'myisam', 'sys_end'); +x y +1 1000 +2 2000 +3 3001 +4 4002 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +3 3000 +4 4000 +4 4001 +4 4444 +x y +1 1000 +2 2000 +3 3001 +4 4002 +4 4444 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y +1 1000 +2 2000 +3 3000 +3 3001 +4 4000 +4 4001 +4 4002 +4 4444 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +x y +1 1000 +2 2000 +3 3001 +4 4002 +4 4444 +5 5000 +6 6000 +7 7000 +8 8000 +9 9000 +call test_06('timestamp(6)', 'myisam', 'sys_end'); +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8008 +9 9009 +8 8000 +9 9000 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8008 +9 9009 +x y +1 1011 +2 2012 +3 3013 +4 4014 +5 5015 +6 6016 +7 7010 +8 8010 +9 9010 +1 1010 +2 2010 +3 3010 +4 4010 +5 5010 +6 6010 +x y +1 1011 +2 2012 +3 3013 +4 4014 +5 5015 +6 6016 +7 7010 +8 8010 +9 9010 +call test_06('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8008 +9 9009 +8 8000 +9 9000 +x y +1 1000 +2 2000 +3 3000 +4 4000 +5 5000 +6 6000 +7 7000 +8 8008 +9 9009 +x y +1 1011 +2 2012 +3 3013 +4 4014 +5 5015 +6 6016 +7 7010 +8 8010 +9 9010 +1 1010 +2 2010 +3 3010 +4 4010 +5 5010 +6 6010 +x y +1 1011 +2 2012 +3 3013 +4 4014 +5 5015 +6 6016 +7 7010 +8 8010 +9 9010 +call test_07('timestamp(6)', 'myisam', 'sys_end'); +A1 name +1 Jerry +A2 name +1 Jerry +B1 salary +1 2500 +B2 salary +1 2500 +call test_07('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +A1 name +1 Jerry +A2 name +1 Jerry +B1 salary +1 2500 +B2 salary +1 2500 +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +8 1 1 1 1 +9 1 1 1 1 +10 1 1 1 1 +11 1 1 1 1 +12 1 1 1 1 +13 1 1 1 1 +14 1 1 1 1 +15 1 1 1 1 +16 1 1 1 1 +17 1 1 1 1 +18 1 1 1 1 +19 1 1 1 1 +20 1 1 1 1 +drop procedure test_01; +drop procedure test_02; +drop procedure test_03; +drop procedure test_04; +drop procedure test_05; +drop procedure test_06; +drop procedure test_07; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/view.result b/mysql-test/suite/versioning/r/view.result new file mode 100644 index 00000000000..ff009be57f5 --- /dev/null +++ b/mysql-test/suite/versioning/r/view.result @@ -0,0 +1,217 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(transaction_id), 0) into @start_trx_id from information_schema.innodb_vtq; +set @test_start=now(6); +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +transaction_id > 0 as A, +commit_id > transaction_id as B, +begin_timestamp > @test_start as C, +commit_timestamp >= begin_timestamp as D +from information_schema.innodb_vtq +where transaction_id > @start_trx_id; +select ifnull(max(transaction_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ +create procedure concat_exec2(a varchar(255), b varchar(255)) +begin +prepare stmt from concat(a, b); +execute stmt; +deallocate prepare stmt; +end~~ +create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255)) +begin +prepare stmt from concat(a, b, c); +execute stmt; +deallocate prepare stmt; +end~~ +create table t1 (x int) with system versioning engine innodb; +insert into t1 values (1); +select now(6) into @t1; +update t1 set x= 2; +select now(6) into @t2; +delete from t1; +set @vt1= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'"); +prepare stmt from @vt1; +execute stmt; +drop prepare stmt; +set @vt2= concat("create view vt2 as select *, sys_trx_end from t1 for system_time as of timestamp '", @t2, "'"); +prepare stmt from @vt2; +execute stmt; +drop prepare stmt; +select * from vt1 for system_time all; +x +1 +select * from vt2 for system_time all; +x +2 +select * from t1; +x +create or replace view vt1 as select * from t1; +show create view vt1; +View Create View character_set_client collation_connection +vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from `t1` FOR SYSTEM_TIME ALL where `t1`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci +drop view vt1; +drop view vt2; +create view vt1 as select * from t1 for system_time all; +select * from vt1 for system_time all; +x +2 +1 +prepare stmt from 'select * from vt1 for system_time all'; +execute stmt; +x +2 +1 +drop prepare stmt; +select * from vt1; +x +2 +1 +prepare stmt from 'select * from vt1'; +execute stmt; +x +2 +1 +drop prepare stmt; +select * from t1 for system_time as of timestamp @t1; +x +1 +select * from vt1 for system_time as of timestamp @t1; +x +1 +prepare stmt from 'select * from vt1 for system_time as of timestamp @t1'; +execute stmt; +x +1 +drop prepare stmt; +create or replace view vt1 as select * from t1; +select * from vt1 for system_time all; +x +prepare stmt from 'select * from vt1 for system_time all'; +execute stmt; +x +drop prepare stmt; +insert into vt1 values (3); +select * from t1; +x +3 +select * from vt1; +x +3 +select * from t1 for system_time all; +x +2 +1 +3 +select * from vt1 for system_time all; +x +3 +create or replace table t1 (x int) with system versioning; +insert into t1 values (1), (2); +set @t1=now(6); +delete from t1 where x=2; +set @t2=now(6); +delete from t1 where x=1; +set @t3=now(6); +set @tmp= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'"); +prepare stmt from @tmp; +execute stmt; +drop prepare stmt; +select * from vt1 for system_time all; +x +1 +2 +create or replace table t1 (x int) with system versioning; +create or replace view vt1(c) as select x from t1; +create or replace table t1 (a int) with system versioning engine innodb; +create or replace table t2 (b int) with system versioning engine innodb; +insert into t1 values (1); +insert into t2 values (2); +create or replace view vt12 as select * from t1 cross join t2; +select * from vt12; +a b +1 2 +create or replace view vt12 as select * from t1 for system_time as of timestamp '0-0-0' cross join t2; +select * from vt12; +a b +create or replace view vt1 as select a, t1.sys_trx_start, t2.sys_trx_end from t1, t2; +ERROR HY000: Creating VIEW `vt1` is prohibited: system fields from multiple tables `t1`, `t2` in query! +create or replace view vt1 as select a, t1.sys_trx_end, t2.sys_trx_end from t1, t2; +ERROR HY000: Creating VIEW `vt1` is prohibited: multiple end system fields `t1.sys_trx_end`, `t2.sys_trx_end` in query! +create or replace table t3 (x int); +create or replace view vt1 as select * from t1, t2, t3; +show create view vt1; +View Create View character_set_client collation_connection +vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`b` AS `b`,`t3`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from ((`t1` FOR SYSTEM_TIME ALL join `t2` FOR SYSTEM_TIME ALL) join `t3`) where `t1`.`sys_trx_end` = 18446744073709551615 and `t2`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci +create or replace view vt1 as select * from t3, t2, t1; +show create view vt1; +View Create View character_set_client collation_connection +vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t3`.`x` AS `x`,`t2`.`b` AS `b`,`t1`.`a` AS `a`,`t2`.`sys_trx_start` AS `sys_trx_start`,`t2`.`sys_trx_end` AS `sys_trx_end` from ((`t3` join `t2` FOR SYSTEM_TIME ALL) join `t1` FOR SYSTEM_TIME ALL) where `t2`.`sys_trx_end` = 18446744073709551615 and `t1`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci +create or replace view vt1 as select a, t2.sys_trx_end as endo from t3, t1, t2; +show create view vt1; +View Create View character_set_client collation_connection +vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`sys_trx_end` AS `endo`,`t2`.`sys_trx_start` AS `sys_trx_start` from ((`t3` join `t1` FOR SYSTEM_TIME ALL) join `t2` FOR SYSTEM_TIME ALL) where `t1`.`sys_trx_end` = 18446744073709551615 and `t2`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci +create or replace view vt1 as select * from t1 union select * from t1; +select * from vt1; +a +1 +create or replace view vvt1 as select * from t1, t2, vt1; +ERROR HY000: Creating VIEW `vvt1` is prohibited: versioned VIEW `vt1` in query! +drop view vt1, vt12; +drop table t1, t2, t3; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; +drop procedure concat_exec2; +drop procedure concat_exec3; diff --git a/mysql-test/suite/versioning/r/vtmd.result b/mysql-test/suite/versioning/r/vtmd.result new file mode 100644 index 00000000000..47f0dfd3491 --- /dev/null +++ b/mysql-test/suite/versioning/r/vtmd.result @@ -0,0 +1,364 @@ +create or replace procedure drop_archives (in vtmd_name varchar(64)) +begin +declare archive_name varchar(64); +declare cur_done bool default false; +declare cur cursor for +select cur_tmp.archive_name from cur_tmp; +declare continue handler for not found set cur_done = true; +set @tmp= concat(' + create or replace temporary table + cur_tmp as + select vtmd.archive_name from ', vtmd_name, ' + for system_time all as vtmd + where vtmd.archive_name is not null + group by vtmd.archive_name'); +prepare stmt from @tmp; execute stmt; drop prepare stmt; +open cur; +fetch_loop: loop +fetch cur into archive_name; +if cur_done then +leave fetch_loop; +end if; +set @tmp= concat('drop table ', archive_name); +prepare stmt from @tmp; execute stmt; drop prepare stmt; +end loop; +drop table cur_tmp; +end~~ +create or replace procedure check_vtmd (in vtmd_name varchar(64)) +begin +set @tmp= concat(' + create or replace temporary table + tmp_vtmd with system versioning as + select * from ', vtmd_name, ' + for system_time all as vtmd'); +prepare stmt from @tmp; execute stmt; drop prepare stmt; +set @inf= 0xFFFFFFFFFFFFFFFF + 0; +set @start= null; +select start from tmp_vtmd for system_time all order by start limit 1 into @start; +select @start > 0 and @start < @inf; +select +start >= @start as A_start, +(@start:= end) and end = @inf as B_end, +name, +substr(archive_name, 1, instr(archive_name, '_')) as C_archive_name +from tmp_vtmd for system_time all; +drop table tmp_vtmd; +end~~ +create or replace procedure show_tables() +begin +show tables; +select table_name, table_schema from information_schema.tables +where table_schema not in ('mysql', 'performance_schema', 'information_schema', 'mtr'); +end~~ +set versioning_alter_history= keep; +create table t0 (z int) with system versioning; +show tables; +Tables_in_test +t0 +set versioning_alter_history= survive; +create or replace table t0 (y int) with system versioning; +show tables; +Tables_in_test +t0 +t0_vtmd +show create table t0_vtmd; +Table Create Table +t0_vtmd CREATE TABLE `t0_vtmd` ( + `start` bigint(20) unsigned GENERATED ALWAYS AS ROW START COMMENT 'TRX_ID of table lifetime start', + `end` bigint(20) unsigned GENERATED ALWAYS AS ROW END NOT NULL COMMENT 'TRX_ID of table lifetime end', + `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT 'Table name during period [start, end)', + `archive_name` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT 'Name of archive table', + `col_renames` blob DEFAULT NULL COMMENT 'Column name mappings from previous lifetime', + PRIMARY KEY (`end`), + KEY `archive_name` (`archive_name`), + PERIOD FOR SYSTEM_TIME (`start`, `end`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 WITH SYSTEM VERSIONING +call check_vtmd('t0_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 1 t0 NULL +set versioning_alter_history= keep; +drop table t0; +set versioning_alter_history= survive; +create table t0 (x int) with system versioning; +ERROR HY000: VTMD error: `test.t0_vtmd` exists and not empty! +drop table t0_vtmd; +create table t0 (y int) with system versioning; +create or replace table t0 (x int) with system versioning; +insert into t0 values (1); +set @t0= now(6); +alter table t0 add column (y int); +select * from t0 for system_time as of @t0; +x +1 +select * from t0; +x y +1 NULL +call check_vtmd('t0_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 t0 t0_ +1 0 t0 t0_ +1 1 t0 NULL +call drop_archives('t0_vtmd'); +drop table t0_vtmd; +alter table t0 drop column y; +call check_vtmd('t0_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 1 t0 t0_ +call drop_archives('t0_vtmd'); +set versioning_alter_history= keep; +drop tables t0, t0_vtmd; +set versioning_alter_history= survive; +set versioning_alter_history= keep; +create or replace table x0 (x int) with system versioning; +set versioning_alter_history= survive; +rename table x0 to d0; +show tables; +Tables_in_test +d0 +set versioning_alter_history= keep; +drop table d0; +set versioning_alter_history= survive; +create or replace table x0 (x int) with system versioning; +rename table x0 to d0; +show tables; +Tables_in_test +d0 +d0_vtmd +call check_vtmd('d0_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 x0 NULL +1 1 d0 NULL +set versioning_alter_history= keep; +drop table d0; +set versioning_alter_history= survive; +create or replace table x0 (x int) with system versioning; +rename table x0 to d0; +ERROR HY000: VTMD error: `test.d0_vtmd` table already exists! +show tables; +Tables_in_test +d0_vtmd +x0 +x0_vtmd +drop table x0_vtmd; +rename table x0 to d0; +Warnings: +Warning 4088 `test.d0_vtmd` table already exists! +show tables; +Tables_in_test +d0 +d0_vtmd +rename table d0 to duck; +rename table duck to bay; +rename table bay to sheer; +rename table sheer to t0; +call check_vtmd('t0_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 x0 NULL +1 0 d0 NULL +1 0 duck NULL +1 0 bay NULL +1 0 sheer NULL +1 1 t0 NULL +alter table t0 add column (y int); +call check_vtmd('t0_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 x0 t0_ +1 0 d0 t0_ +1 0 duck t0_ +1 0 bay t0_ +1 0 sheer t0_ +1 0 t0 t0_ +1 1 t0 NULL +alter table t0 add column (z int); +alter table t0 drop column y; +alter table t0 drop column z; +create database db0; +rename table t0 to db0.t0; +show tables; +Tables_in_test +use db0; +show tables; +Tables_in_db0 +t0 +t0_vtmd +call test.check_vtmd('db0.t0_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 x0 t0_ +1 0 d0 t0_ +1 0 duck t0_ +1 0 bay t0_ +1 0 sheer t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 1 t0 NULL +create database db1; +rename table t0 to db1.other_name; +show tables; +Tables_in_db0 +use db1; +show tables; +Tables_in_db1 +other_name +other_name_vtmd +call test.check_vtmd('db1.other_name_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 x0 t0_ +1 0 d0 t0_ +1 0 duck t0_ +1 0 bay t0_ +1 0 sheer t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 NULL +1 1 other_name NULL +alter table other_name rename to t1; +call test.check_vtmd('db1.t1_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 x0 t0_ +1 0 d0 t0_ +1 0 duck t0_ +1 0 bay t0_ +1 0 sheer t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 NULL +1 0 other_name NULL +1 1 t1 NULL +alter table t1 rename to test.t2, add column (y int); +use test; +show tables; +Tables_in_test +t2 +t2_vtmd +call check_vtmd('t2_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 x0 t0_ +1 0 d0 t0_ +1 0 duck t0_ +1 0 bay t0_ +1 0 sheer t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t0_ +1 0 t0 t1_ +1 0 other_name t1_ +1 0 t1 t1_ +1 1 t2 NULL +create or replace table t3 (x int) with system versioning; +alter table t3 change x x bigint; +alter table t3 change x x bigint after sys_trx_start; +call check_vtmd('t3_vtmd'); +@start > 0 and @start < @inf +1 +A_start B_end name C_archive_name +1 0 t3 t3_ +1 0 t3 t3_ +1 1 t3 NULL +set versioning_hide= auto; +call show_tables(); +Tables_in_test +t2 +t2_vtmd +t3 +t3_vtmd +table_name table_schema +t2 test +t2_vtmd test +t3 test +t3_vtmd test +set versioning_hide= implicit; +call show_tables(); +Tables_in_test +t2 +t2_vtmd +t3 +t3_vtmd +table_name table_schema +t2 test +t2_vtmd test +t3 test +t3_vtmd test +set versioning_hide= full; +call show_tables(); +Tables_in_test +t2 +t2_vtmd +t3 +t3_vtmd +table_name table_schema +t2 test +t2_vtmd test +t3 test +t3_vtmd test +set versioning_hide= never; +call show_tables(); +Tables_in_test +t0_TIMESTAMP_SUFFIX +t0_TIMESTAMP_SUFFIX +t0_TIMESTAMP_SUFFIX +t0_TIMESTAMP_SUFFIX +t2 +t2_vtmd +t3 +t3_TIMESTAMP_SUFFIX +t3_TIMESTAMP_SUFFIX +t3_vtmd +table_name table_schema +t1_TIMESTAMP_SUFFIX db1 +t0_TIMESTAMP_SUFFIX test +t0_TIMESTAMP_SUFFIX test +t0_TIMESTAMP_SUFFIX test +t0_TIMESTAMP_SUFFIX test +t2 test +t2_vtmd test +t3 test +t3_TIMESTAMP_SUFFIX test +t3_TIMESTAMP_SUFFIX test +t3_vtmd test +set versioning_hide= auto; +create or replace table u0_vtmd (x int) with system versioning; +show tables; +Tables_in_test +t2 +t2_vtmd +t3 +t3_vtmd +u0_vtmd +u0_vtmd_vtmd +Warnings: +Warning 4088 Table `test.u0_vtmd` is not a VTMD table +set versioning_alter_history= survive; +create or replace table t (x int) with system versioning; +select * from t for system_time all; +x sys_trx_start sys_trx_end +drop database db0; +drop database db1; +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/r/vtmd_show.result b/mysql-test/suite/versioning/r/vtmd_show.result new file mode 100644 index 00000000000..4c77182c5de --- /dev/null +++ b/mysql-test/suite/versioning/r/vtmd_show.result @@ -0,0 +1,229 @@ +create or replace procedure drop_archives (in vtmd_name varchar(64)) +begin +declare archive_name varchar(64); +declare cur_done bool default false; +declare cur cursor for +select cur_tmp.archive_name from cur_tmp; +declare continue handler for not found set cur_done = true; +set @tmp= concat(' + create or replace temporary table + cur_tmp as + select vtmd.archive_name from ', vtmd_name, ' + for system_time all as vtmd + where vtmd.archive_name is not null + group by vtmd.archive_name'); +prepare stmt from @tmp; execute stmt; drop prepare stmt; +open cur; +fetch_loop: loop +fetch cur into archive_name; +if cur_done then +leave fetch_loop; +end if; +set @tmp= concat('drop table ', archive_name); +prepare stmt from @tmp; execute stmt; drop prepare stmt; +end loop; +drop table cur_tmp; +end~~ +create procedure test_01(in engine varchar(64)) +begin +set @tmp = concat('create table t (a int) with system versioning engine ', engine); +prepare stmt from @tmp; execute stmt; drop prepare stmt; +set @tm1 = now(6); +alter table t add column b int; +set @tm2 = now(6); +alter table t add column c int; +show create table t for system_time as of timestamp @tm1; +show create table t for system_time as of timestamp @tm2; +show create table t for system_time as of now; +show create table t for system_time as of timestamp now(6); +show create table t; +set @tm3 = now(6); +rename table t to tt; +show create table tt for system_time as of timestamp @tm3; +set @tm4 = now(6); +alter table tt add column d int; +show create table tt for system_time as of timestamp @tm3; +show create table tt for system_time as of timestamp @tm4; +show create table tt; +drop table tt; +call drop_archives('tt_vtmd'); +drop table tt_vtmd; +end~~ +create table t (a int) with system versioning; +show create table t for system_time as of now; +ERROR HY000: VTMD error: Table 'test.t_vtmd' doesn't exist +set versioning_alter_history=survive; +create or replace table t (a int) with system versioning; +show create table t for system_time between timestamp @tm1 and timestamp @tm1; +ERROR HY000: SYSTEM_TIME range selector is prohibited +show create table t for system_time from timestamp @tm1 to timestamp @tm1; +ERROR HY000: SYSTEM_TIME range selector is prohibited +show create table t for system_time as of timestamp '01-01-1990'; +ERROR HY000: VTMD error: Table 'test.t' doesn't exist +show create table t for system_time as of timestamp '01-01-2020'; +ERROR HY000: VTMD error: Table 'test.t' doesn't exist +drop table t; +call drop_archives('t_vtmd'); +drop table t_vtmd; +call test_01('myisam'); +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `d` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +call test_01('innodb'); +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +Table Create Table +tt CREATE TABLE `tt` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `d` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +drop procedure test_01; +drop procedure drop_archives; diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test new file mode 100644 index 00000000000..7020439d86e --- /dev/null +++ b/mysql-test/suite/versioning/t/alter.test @@ -0,0 +1,279 @@ +create table t( + a int +); +show create table t; +--error ER_VERS_WRONG_PARAMS +alter table t without system versioning; + +alter table t with system versioning; +show create table t; + +alter table t without system versioning; +show create table t; + +--error ER_VERS_FIELD_WRONG_TYPE +alter table t + add column trx_start bigint(20) unsigned generated always as row start, + add column trx_end bigint(20) unsigned generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +--error ER_VERS_FIELD_WRONG_TYPE +alter table t + add column trx_start timestamp generated always as row start, + add column trx_end timestamp generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +--error ER_PARSE_ERROR +alter table t + add column trx_start timestamp(6) not null generated always as row start, + add column trx_end timestamp(6) not null generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +alter table t + add column trx_start timestamp(6) generated always as row start, + add column trx_end timestamp(6) generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; +show create table t; + +alter table t drop column trx_start, drop column trx_end; +alter table t without system versioning; +show create table t; + +alter table t with system versioning; +show create table t; + +alter table t add column b int; +show create table t; + +alter table t add column c int; +show create table t; + +alter table t add column d int first; +show create table t; + +alter table t add column e int after d; +show create table t; + +alter table t drop column a; +show create table t; + +create or replace table t ( + a int, + sys_trx_start timestamp(6) generated always as row start, + sys_trx_end timestamp(6) generated always as row end, + period for system_time(sys_trx_start, sys_trx_end)) +with system versioning; + +select * from t for system_time all; +alter table t drop column sys_trx_start; +alter table t drop column sys_trx_end; +select * from t for system_time all; + +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t drop column sys_trx_start; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t drop column sys_trx_end; + +create or replace table t ( + a int, + sys_trx_start timestamp(6) generated always as row start, + sys_trx_end timestamp(6) generated always as row end, + period for system_time(sys_trx_start, sys_trx_end)) +with system versioning; + +select * from t for system_time all; +alter table t drop column sys_trx_start, drop column sys_trx_end; +select * from t for system_time all; + +create or replace table t( + a int +); +insert into t values(1); +alter table t with system versioning; +show create table t; +insert into t values(2); +select * from t for system_time all; +select * from t; + +update t set a=3 where a=1; +select * from t; +select * from t for system_time all; +select sys_trx_start from t where a=3 into @tm; +alter table t add column b int; +select @tm=sys_trx_start from t where a=3; +show create table t; +select * from t; +select * from t for system_time all; + +alter table t without system versioning; +select * from t; +show create table t; + +--error ER_VERS_WRONG_PARAMS +alter table t modify a int with system versioning; +--error ER_VERS_WRONG_PARAMS +alter table t modify a int without system versioning; + +alter table t with system versioning; + +alter table t modify a int without system versioning; +show create table t; + +alter table t modify a int with system versioning; +show create table t; + +-- source suite/versioning/common.inc +create or replace table t( + a int +) engine=innodb; + +insert into t values(1); +select * from t; + +--error ER_VERS_FIELD_WRONG_TYPE +alter table t + add column trx_start timestamp(6) generated always as row start, + add column trx_end timestamp(6) generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +alter table t + add column trx_start bigint(20) unsigned generated always as row start, + add column trx_end bigint(20) unsigned generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; +show create table t; +alter table t drop column trx_start, drop column trx_end; +alter table t without system versioning; + +alter table t with system versioning, algorithm=copy; +show create table t; + +update t set a=2; +select * from t for system_time all; + +alter table t add column b int, algorithm=copy; +show create table t; +select * from t; + +alter table t drop column b, algorithm=copy; +show create table t; +select * from t for system_time all; + +alter table t add column b int, algorithm=inplace; +show create table t; +select * from t; + +alter table t drop column b, algorithm=inplace; +show create table t; +select * from t for system_time all; + +alter table t without system versioning, algorithm=copy; +show create table t; + +create or replace table t (a int) with system versioning engine=innodb; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b int auto_increment unique; +select * from t for system_time all; +insert into t values (4, NULL); +select * from t for system_time all; + +create or replace table t (a int) with system versioning; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b int auto_increment unique; +select * from t for system_time all; +insert into t values (4, NULL); +select * from t for system_time all; + +create or replace table t (a int) with system versioning engine=innodb; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b tinyint auto_increment unique; +select * from t for system_time all; +insert into t values (4, NULL); +select * from t for system_time all; + +create or replace table t (a int) with system versioning; +insert into t values (1), (2), (3); +delete from t where a<3; +alter table t add b tinyint auto_increment unique; +select * from t for system_time all; +insert into t values (4, NULL); +select * from t for system_time all; + +create or replace table t (a int) engine innodb; +insert into t values (1); +alter table t with system versioning, algorithm=inplace; +select * from t for system_time all; +update t set a=2; +select * from t for system_time all; +alter table t add column b int, algorithm=inplace; +select * from t for system_time all; +alter table t without system versioning, algorithm=inplace; +select * from t; + +create or replace table t ( + a int, + sys_trx_start bigint(20) unsigned generated always as row start, + sys_trx_end bigint(20) unsigned generated always as row end, + period for system_time(sys_trx_start, sys_trx_end) +) with system versioning engine innodb; +--error ER_VERS_ALTER_SYSTEM_FIELD +alter table t change column sys_trx_start asdf bigint unsigned; + +create or replace table t ( + a int, + sys_trx_start timestamp(6) generated always as row start, + sys_trx_end timestamp(6) generated always as row end, + period for system_time(sys_trx_start, sys_trx_end) +) with system versioning engine myisam; +--error ER_VERS_ALTER_SYSTEM_FIELD +alter table t change column sys_trx_start asdf timestamp(6); + +create or replace table t ( + a int, + sys_trx_start timestamp(6) generated always as row start, + sys_trx_end timestamp(6) generated always as row end, + period for system_time(sys_trx_start, sys_trx_end) +) with system versioning; +select * from t; + +--error ER_VERS_SYS_FIELD_NOT_HIDDEN +alter table t without system versioning; +alter table t drop column sys_trx_start; +select * from t; + +--error ER_VERS_SYS_FIELD_NOT_HIDDEN +alter table t without system versioning; +alter table t drop column sys_trx_end; +select * from t; + +alter table t without system versioning; +show create table t; + +set versioning_alter_history = DROP; + +create or replace table t (a int) with system versioning engine innodb; +insert into t values (1); +update t set a = 2; +select * from t for system_time all; +alter table t add column b int; +select * from t for system_time all; + +create or replace table t (a int) with system versioning engine myisam; +insert into t values (1); +update t set a = 2; +select * from t for system_time all; +alter table t add column b int; +select * from t for system_time all; + +call verify_vtq; +drop table t; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/auto_increment.test b/mysql-test/suite/versioning/t/auto_increment.test new file mode 100644 index 00000000000..7b79be575d1 --- /dev/null +++ b/mysql-test/suite/versioning/t/auto_increment.test @@ -0,0 +1,68 @@ +-- source suite/versioning/common.inc + +delimiter ~~; +create procedure test_01( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1( + id int unsigned auto_increment primary key, + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + + set @str= concat(' + create table t2( + id int unsigned auto_increment primary key, + x int unsigned, + y int unsigned) + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + + insert into t1(x, y) values(1, 11); + insert into t2(x, y) values(1, 11); + insert into t1(x, y) values(2, 12); + insert into t2(x, y) values(2, 12); + insert into t1(x, y) values(3, 13); + insert into t2(x, y) values(3, 13); + insert into t1(x, y) values(4, 14); + insert into t2(x, y) values(4, 14); + insert into t1(x, y) values(5, 15); + insert into t2(x, y) values(5, 15); + insert into t1(x, y) values(6, 16); + insert into t2(x, y) values(6, 16); + insert into t1(x, y) values(7, 17); + insert into t2(x, y) values(7, 17); + insert into t1(x, y) values(8, 18); + insert into t2(x, y) values(8, 18); + insert into t1(x, y) values(9, 19); + insert into t2(x, y) values(9, 19); + + select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id; + delete from t1 where x = 2; + delete from t2 where x = 2; + + select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id; + delete from t1 where x > 7; + delete from t2 where x > 7; + + select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id; + drop table t1; + drop table t2; +end~~ +delimiter ;~~ + +call test_01('timestamp(6)', 'myisam', 'sys_end'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +call verify_vtq; + +drop procedure test_01; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/commit_id.test b/mysql-test/suite/versioning/t/commit_id.test new file mode 100644 index 00000000000..fa44958470c --- /dev/null +++ b/mysql-test/suite/versioning/t/commit_id.test @@ -0,0 +1,86 @@ +-- source suite/versioning/common.inc + +create table t1( + id int auto_increment primary key) +with system versioning +engine innodb; + + +# VTQ_TRX_ID, VTQ_COMMIT_ID, VTQ_TRX_SEES # + +insert into t1 values (); + +set @ts0= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx0; +select transaction_id = @tx0 from information_schema.innodb_vtq limit 1; + +set @ts1= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx1; +select transaction_id = @tx1 from information_schema.innodb_vtq limit 1; + +set @ts2= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx2; +select transaction_id = @tx2 from information_schema.innodb_vtq limit 1; + +set @ts3= now(6); + +select + vtq_trx_id(@ts0) < @tx0 as A, + vtq_trx_id(@ts0, true) = @tx0 as B, + vtq_trx_id(@ts1) = @tx0 as C, + vtq_trx_id(@ts1, true) = @tx1 as D, + vtq_trx_id(@ts2) = @tx1 as E, + vtq_trx_id(@ts2, true) = @tx2 as F, + vtq_trx_id(@ts3) = @tx2 as G, + vtq_trx_id(@ts3, true) is null as H; + +select + vtq_commit_id(@ts0) < @tx0 as A, + vtq_commit_id(@ts0, true) = vtq_commit_id(null, @tx0) as B, + vtq_commit_id(@ts1) = vtq_commit_id(null, @tx0) as C, + vtq_commit_id(@ts1, true) = vtq_commit_id(null, @tx1) as D, + vtq_commit_id(@ts2) = vtq_commit_id(null, @tx1) as E, + vtq_commit_id(@ts2, true) = vtq_commit_id(null, @tx2) as F, + vtq_commit_id(@ts3) = vtq_commit_id(null, @tx2) as G, + vtq_commit_id(@ts3, true) is null as H; + +select + vtq_trx_sees(@tx1, @tx0) as A, + not vtq_trx_sees(@tx0, @tx1) as B, + vtq_trx_sees_eq(@tx1, @tx1) as C, + not vtq_trx_sees(@tx1, @tx1) as D, + vtq_trx_sees(@tx2, 0) as E, + vtq_trx_sees(0, @tx2) is null as F, + vtq_trx_sees(-1, @tx2) as H; + + +# VTQ_ISO_LEVEL # + +set transaction isolation level read uncommitted; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx3; +select isolation_level = 'READ-UNCOMMITTED' from information_schema.innodb_vtq where transaction_id = @tx3; + +set transaction isolation level read committed; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx4; +select isolation_level = 'READ-COMMITTED' from information_schema.innodb_vtq where transaction_id = @tx4; + +set transaction isolation level serializable; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx5; +select isolation_level = 'SERIALIZABLE' from information_schema.innodb_vtq where transaction_id = @tx5; + +set transaction isolation level repeatable read; +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx6; +select isolation_level = 'REPEATABLE-READ' from information_schema.innodb_vtq where transaction_id = @tx6; + + +drop table t1; +call verify_vtq; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/create.combinations b/mysql-test/suite/versioning/t/create.combinations new file mode 100644 index 00000000000..75fb20d9f5e --- /dev/null +++ b/mysql-test/suite/versioning/t/create.combinations @@ -0,0 +1,5 @@ +[innodb] +default-storage-engine=innodb + +[myisam] +default-storage-engine=myisam diff --git a/mysql-test/suite/versioning/t/create.test b/mysql-test/suite/versioning/t/create.test new file mode 100644 index 00000000000..815030255df --- /dev/null +++ b/mysql-test/suite/versioning/t/create.test @@ -0,0 +1,295 @@ +-- source suite/versioning/common.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +delimiter ~~; +create function if not exists non_default_engine() +returns varchar(255) +deterministic +begin + if default_engine() = 'innodb' then + return 'myisam'; + end if; + return 'innodb'; +end~~ +delimiter ;~~ + +--let $sys_datatype= `select sys_datatype()` +--let $default_engine= `select default_engine()` +--let $non_default_engine= `select non_default_engine()` + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +eval create table t1 ( + x1 int unsigned, + Sys_start $sys_datatype generated always as row start comment 'start', + Sys_end $sys_datatype generated always as row end comment 'end', + period for system_time (Sys_start, Sys_end) +) with system versioning; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t1; + +--echo # Implicit fields test +create or replace table t1 ( + x2 int unsigned +) with system versioning; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t1; + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +--error ER_VERS_WRONG_PARAMS +eval create or replace table t1 ( + x3 int unsigned, + Sys_start $sys_datatype generated always as row start, + Sys_start2 $sys_datatype generated always as row start, + Sys_end $sys_datatype generated always as row end, + period for system_time (Sys_start, Sys_end) +) with system versioning; + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +--error ER_VERS_WRONG_PARAMS +eval create or replace table t1 ( + x4 int unsigned, + Sys_start $sys_datatype generated always as row start, + Sys_end2 $sys_datatype generated always as row end, + period for system_time (Sys_start, Sys_end) +) with system versioning; + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +--error ER_VERS_WRONG_PARAMS +eval create or replace table t1 ( + x5 int unsigned, + Sys_start $sys_datatype generated always as row start, + Sys_end $sys_datatype generated always as row end, + Sys_end2 $sys_datatype generated always as row end, + period for system_time (Sys_start, Sys_end) +) with system versioning; + +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + x6 int unsigned, + period for system_time (Sys_start, Sys_end) +) with system versioning; + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +--error ER_VERS_WRONG_PARAMS +eval create or replace table t1 ( + x7 int unsigned, + Sys_start $sys_datatype generated always as row start, + Sys_end $sys_datatype generated always as row end, + Sys_end2 $sys_datatype generated always as row end, + period for system_time (Sys_start, Sys_end) +); + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +--error ER_VERS_WRONG_PARAMS +eval create or replace table t1 ( + x8 int unsigned, + Sys_start $sys_datatype generated always as row start, + Sys_end $sys_datatype generated always as row end, + period for system_time (sys_insert, sys_remove) +) with system versioning; + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +--error ER_VERS_WRONG_PARAMS +eval create or replace table t1 ( + x9 int unsigned, + Sys_start $sys_datatype generated always as row start, + Sys_end $sys_datatype generated always as row end, + period for system_time (Sys_start, Sys_end) +); + +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +--error ER_VERS_WRONG_PARAMS +eval create or replace table t1 ( + x10 int unsigned, + Sys_start $sys_datatype generated always as row start, + Sys_end $sys_datatype generated always as row end, + period for system_time (Sys_start, Sys_start) +); + +--error ER_VERS_FIELD_WRONG_TYPE, ER_VERS_FIELD_WRONG_TYPE +create or replace table t1 ( + x11 int unsigned, + Sys_start bigint unsigned generated always as row start, + Sys_end timestamp(6) generated always as row end, + period for system_time (Sys_start, Sys_end) +) with system versioning; + +--error ER_VERS_FIELD_WRONG_TYPE, ER_VERS_FIELD_WRONG_TYPE +create or replace table t1 ( + x12 int unsigned, + Sys_start timestamp(6) generated always as row start, + Sys_end bigint unsigned generated always as row end, + period for system_time (Sys_start, Sys_end) +) with system versioning; + +--error ER_VERS_FIELD_WRONG_TYPE +create or replace table t1 ( + x13 int unsigned, + Sys_start bigint generated always as row start, + Sys_end bigint unsigned generated always as row end, + period for system_time (Sys_start, Sys_end) +) with system versioning engine innodb; + +--error ER_VERS_FIELD_WRONG_TYPE +create or replace table t1 ( + x14 int unsigned, + Sys_start bigint unsigned generated always as row start, + Sys_end bigint generated always as row end, + period for system_time (Sys_start, Sys_end) +) with system versioning engine innodb; + +# columns with/without system versioning + +create or replace table t1 ( + A1 int with system versioning, + B int +); +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t1; + +create or replace table t1 ( + A2 int with system versioning, + B int +) with system versioning; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t1; + +create or replace table t1 ( + A3 int, + B int without system versioning +); + +create or replace table t1 ( + A4 int, + B int without system versioning +) with system versioning; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t1; + +create or replace table t1 ( + A5 int with system versioning, + B int without system versioning +); +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t1; + +create or replace table t1 ( + A6 int with system versioning, + B int without system versioning +) with system versioning; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t1; + +create or replace table t1 ( + A7 int without system versioning +); + +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + A8 int without system versioning +) with system versioning; + +# table with/without system versioning + +--error ER_VERS_WRONG_PARAMS +create table t( + a11 int +) without system versioning; + +create or replace table t1 (a int) with system versioning; +create temporary table tmp with system versioning select * from t1; + +# CREATE TABLE ... LIKE +create or replace table t1 (a int) with system versioning; +create table tt1 like t1; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table tt1; +drop table tt1; + +# CREATE TABLE ... SELECT +create or replace table t1 (x int) with system versioning; +--replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +eval create or replace table t0( + y int, + st $sys_datatype generated always as row start, + en $sys_datatype generated always as row end, + period for system_time (st, en) +) with system versioning; + +## For non-versioned table: +### 1. system fields are not inherited (hidden and not hidden) +create or replace table t2 as select * from t1; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM +show create table t2; + +create or replace table t3 as select * from t0; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM +show create table t3; + +### 2. hidden fields are inherited as hidden +### TODO: non-system hidden fields + +## For versioned table system fields are inherited as is. +insert into t1 values (1); +insert into t0 values (2); + +create or replace table t2 with system versioning as select * from t1; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t2; +# implicit system fields are hidden +select * from t2; + +create or replace table t3 with system versioning as select * from t0; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t3; +# explicit system fields are not hidden +select * from t3 where y > 2; + +delete from t0; + +## Combinations of versioned + non-versioned +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int); +create or replace table t3 with system versioning select * from t1 for system_time all, t2; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t3; + +create or replace table t2 with system versioning as select * from t0; +--error ER_VERS_WRONG_PARAMS +create or replace table t3 with system versioning select x, y, t1.sys_trx_start, t2.en from t1, t2; + +insert into t2 values (1), (2); +delete from t2 where y = 2; + +create or replace table t3 select * from t2 for system_time all; +select st, en from t2 where y = 1 into @st, @en; +select y from t2 for system_time all where st = @st and en = @en; +select st, en from t2 for system_time all where y = 2 into @st, @en; +select y from t2 for system_time all where st = @st and en = @en; + +--replace_result innodb INNODB_OR_MYISAM myisam INNODB_OR_MYISAM +eval create or replace table t1 (a int) with system versioning engine $non_default_engine; +create or replace table t2 as select a, sys_trx_start, sys_trx_end from t1 for system_time all; +--replace_result innodb INNODB_OR_MYISAM myisam INNODB_OR_MYISAM "BIGINT(20) UNSIGNED" SYS_TRX_TYPE "TIMESTAMP(6)" SYS_TRX_TYPE +--error ER_VERS_FIELD_WRONG_TYPE +eval create or replace table t2 with system versioning engine $default_engine as select a, sys_trx_start, sys_trx_end from t1 for system_time all; + +--replace_result innodb INNODB_OR_MYISAM myisam INNODB_OR_MYISAM +eval create or replace table t1 (a int, id int) with system versioning engine $non_default_engine; +create or replace table t2 (b int, id int); +create or replace table t3 as + select t2.b, t1.a, t1.sys_trx_start, t1.sys_trx_end from t2 inner join t1 on t2.id=t1.id; + +create or replace table t (sys_trx_start int); +--error ER_DUP_FIELDNAME +alter table t with system versioning; + +create or replace table t (sys_trx_end int); +--error ER_DUP_FIELDNAME +alter table t with system versioning; + +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/t/cte.opt b/mysql-test/suite/versioning/t/cte.opt new file mode 100644 index 00000000000..36f683f4f5b --- /dev/null +++ b/mysql-test/suite/versioning/t/cte.opt @@ -0,0 +1,3 @@ +--innodb --default-storage-engine=innodb +--plugin-load=versioning +--versioning-hide=implicit diff --git a/mysql-test/suite/versioning/t/cte.test b/mysql-test/suite/versioning/t/cte.test new file mode 100644 index 00000000000..7a35352f7c8 --- /dev/null +++ b/mysql-test/suite/versioning/t/cte.test @@ -0,0 +1,84 @@ +create or replace table dept ( + dept_id int(10) primary key, + name varchar(100) +) +with system versioning; + +create or replace table emp ( + emp_id int(10) primary key, + dept_id int(10) not null, + name varchar(100) not null, + mgr int(10), + salary int(10) not null, + constraint `dept-emp-fk` + foreign key (dept_id) references dept (dept_id) + on delete cascade + on update restrict, + constraint `mgr-fk` + foreign key (mgr) references emp (emp_id) + on delete restrict + on update restrict +) +with system versioning; + +insert into dept (dept_id, name) values (10, "accounting"); + +insert into emp (emp_id, name, salary, dept_id, mgr) values +(1, "bill", 1000, 10, null), +(20, "john", 500, 10, 1), +(30, "jane", 750, 10,1 ); + +select vtq_commit_ts(max(sys_trx_start)) into @ts_1 from emp; + +update emp set mgr=30 where name ="john"; +select vtq_commit_ts(sys_trx_start) into @ts_2 from emp where name="john"; + +/* All report to 'Bill' */ +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr, e.salary + from emp for system_time as of timestamp @ts_1 as e + where name = 'bill' + union + select e.emp_id, e.name, e.mgr, e.salary + from emp for system_time as of timestamp @ts_1 as e, + ancestors as a + where e.mgr = a.emp_id +) +select * from ancestors for system_time as of now; + +/* Expected 3 rows */ +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr, e.salary + from emp for system_time as of timestamp @ts_2 as e + where name = 'bill' + union + select e.emp_id, e.name, e.mgr, e.salary + from emp for system_time as of timestamp @ts_2 as e, + ancestors as a + where e.mgr = a.emp_id +) +select * from ancestors; + +create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning; +create or replace table addr ( emp_id int, address varchar(100)) with system versioning; +insert emp values (1, 'bill', 0), (2, 'bill', 1), (3, 'kate', 1); +insert addr values (1, 'Moscow'), (2, 'New York'), (3, 'London'); +set @ts=now(6); +delete from emp; +delete from addr; +insert emp values (4, 'john', 1); +insert addr values (4, 'Paris'); +with ancestors as (select * from emp natural join addr) select * from ancestors; +with ancestors as (select * from emp natural join addr) select * from ancestors for system_time all; +with ancestors as (select * from emp natural join addr system_time all) select * from ancestors; +select * from emp natural join addr system_time all; + +drop table emp; +drop table dept; +drop table addr; diff --git a/mysql-test/suite/versioning/t/ddl.test b/mysql-test/suite/versioning/t/ddl.test new file mode 100644 index 00000000000..5be62281a6d --- /dev/null +++ b/mysql-test/suite/versioning/t/ddl.test @@ -0,0 +1,105 @@ +-- source suite/versioning/common.inc + +delimiter ~~; +create function get_archive_table_name() +returns varchar(255) +begin + return (select archive_name from t_vtmd for system_time all where archive_name is not NULL + order by start desc limit 1); +end~~ + +create procedure drop_last_archive() +begin + call concat_exec2('drop table ', get_archive_table_name()); +end~~ +delimiter ;~~ + +set versioning_alter_history= survive; + +create or replace table t (a int) with system versioning; +insert into t values (1); +update t set a=2 where a=1; +select sys_trx_start from t where a=2 into @tm; +alter table t add column b int; + +select * from t; +call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all'); + +call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2'); +select @tm<sys_trx_start from t where a=2; +select sys_trx_start from t where a=2 into @tm; +call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2'); + +call drop_last_archive(); + + +set versioning_alter_history= keep; +drop table t_vtmd; +drop table t; +set versioning_alter_history= survive; + +# same for INNODB ALGORITHM=COPY +create or replace table t (a int) with system versioning; +insert into t values (1); +update t set a=2 where a=1; +select sys_trx_start from t where a=2 into @tm; +alter table t add column b int; + +select * from t; +call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all'); + +call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2'); +select @tm<sys_trx_start from t where a=2; +select sys_trx_start from t where a=2 into @tm; +call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2'); + +call drop_last_archive(); + + +set versioning_alter_history= keep; +drop table t_vtmd; +drop table t; +set versioning_alter_history= survive; + +# same for INNODB default ALGORITHM +create or replace table t (a int) with system versioning engine innodb; +insert into t values (1); +update t set a=2 where a=1; +select sys_trx_start from t where a=2 into @tm; +alter table t add column b int; + +select * from t; +call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all'); + +call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2'); +select @tm<sys_trx_start from t where a=2; +select sys_trx_start from t where a=2 into @tm; +call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2'); + +call drop_last_archive(); + + +set versioning_alter_history= keep; +drop table t_vtmd; +drop table t; +set versioning_alter_history= survive; + +# no DDL for INNODB explicit ALGORITHM=INPLACE +create or replace table t (a int) with system versioning engine innodb; +insert into t values (1); +update t set a=2 where a=1; +alter table t add column b int, algorithm=inplace; + +set versioning_alter_history = keep; + +drop function get_archive_table_name; +drop procedure drop_last_archive; + +select * from mysql.vtmd_template; +show create table mysql.vtmd_template; + +call verify_vtq; +drop table t; +drop table t_vtmd; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/delete.test b/mysql-test/suite/versioning/t/delete.test new file mode 100644 index 00000000000..1830f512b88 --- /dev/null +++ b/mysql-test/suite/versioning/t/delete.test @@ -0,0 +1,121 @@ +-- source suite/versioning/common.inc + +delimiter ~~; +create or replace procedure test_01( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create or replace table t1( + XNo int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1(XNo) values(0); + insert into t1(XNo) values(1); + insert into t1(XNo) values(2); + insert into t1(XNo) values(3); + insert into t1(XNo) values(4); + insert into t1(XNo) values(5); + insert into t1(XNo) values(6); + insert into t1(XNo) values(7); + insert into t1(XNo) values(8); + insert into t1(XNo) values(9); + set @str= concat('select XNo, ', + fields, " < '2038-01-19 03:14:07' + from t1 for system_time + between timestamp '0000-0-0 0:0:0' + and timestamp '2038-01-19 04:14:07'"); + prepare stmt from @str; execute stmt; + delete from t1 where XNo = 0; + execute stmt; + delete from t1 where XNo = 1; + execute stmt; + delete from t1 where XNo > 5; + create view vt1 as select XNo from t1; + select XNo from vt1; + delete from vt1 where XNo = 3; + select XNo from vt1; + execute stmt; drop prepare stmt; + drop view vt1; + drop table t1; +end~~ + +create or replace procedure test_02( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat('create or replace table t1 ( + x int, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1(x) values (1); + select sys_start into @sys_start from t1; + delete from t1; + select * from t1; + select x = 1 as A, sys_start = @sys_start as B, sys_end > sys_start as C + from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07'; + drop table t1; +end~~ + +create or replace procedure test_03( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str0= concat('( + x int, + y int, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + set @str= concat('create or replace table t1', @str0); + prepare stmt from @str; execute stmt; drop prepare stmt; + set @str= concat('create or replace table t2', @str0); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1(x, y) values (1, 1), (2, 2), (3, 3), (14, 4); + insert into t2(x, y) values (11, 1), (12, 2), (13, 32), (14, 4); + delete t1, t2 from t1 join t2 where t1.y = 3 and t2.y = 32; + select x as t1_x from t1; + select x as t2_x from t2; + delete t1, t2 from t1 join t2 where t1.x = t2.x; + select x as t1_x from t1; + select x as t2_x from t2; + select x as t1_x_all from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07'; + select x as t2_x_all from t2 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07'; + drop table t1; + drop table t2; +end~~ +delimiter ;~~ + +--echo # Basic + delete from view +call test_01('timestamp(6)', 'myisam', 'sys_end'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +call verify_vtq; + +--echo # Check sys_start, sys_end +call test_02('timestamp(6)', 'myisam', 'sys_end'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +call verify_vtq; + +--echo # Multi-delete +call test_03('timestamp(6)', 'myisam', 'sys_end'); +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +call verify_vtq; + +drop procedure test_01; +drop procedure test_02; +drop procedure test_03; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/derived.test b/mysql-test/suite/versioning/t/derived.test new file mode 100644 index 00000000000..63683e251c9 --- /dev/null +++ b/mysql-test/suite/versioning/t/derived.test @@ -0,0 +1,133 @@ +create table emp +( + emp_id int, + name varchar(127), + mgr int +) with system versioning; + +insert into emp values (1, 'bill', 0), + (2, 'bill', 1), + (3, 'kate', 1); +set @ts=now(6); +delete from emp; +insert into emp values (4, 'john', 1); + +with ancestors as (select * from emp) select * from ancestors; +set @tmp= "with ancestors as (select * from emp) select * from ancestors"; +prepare stmt from @tmp; execute stmt; drop prepare stmt; + +with ancestors as (select * from emp for system_time all) select * from ancestors; +set @tmp= "with ancestors as (select * from emp for system_time all) select * from ancestors"; +prepare stmt from @tmp; execute stmt; drop prepare stmt; + +with recursive ancestors as (select * from emp) select * from ancestors; +set @tmp= "with recursive ancestors as (select * from emp) select * from ancestors"; +prepare stmt from @tmp; execute stmt; drop prepare stmt; + +select emp_id from (select emp_id from emp where sys_trx_end>'2031-1-1') as tmp; +set @tmp= "select emp_id from (select emp_id from emp where sys_trx_end>'2031-1-1') as tmp"; +prepare stmt from @tmp; execute stmt; drop prepare stmt; + +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr + from emp as e + where name = 'john' + union + select ee.emp_id, ee.name, ee.mgr + from emp as ee, ancestors as a + where ee.mgr = a.emp_id +) +select * from ancestors; +set @tmp= " +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr + from emp as e + where name = 'john' + union + select ee.emp_id, ee.name, ee.mgr + from emp as ee, ancestors as a + where ee.mgr = a.emp_id +) +select * from ancestors"; +prepare stmt from @tmp; execute stmt; drop prepare stmt; + +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr + from emp as e + where name = 'bill' + system_time as of timestamp @ts + union + select ee.emp_id, ee.name, ee.mgr + from emp as ee, ancestors as a + where ee.mgr = a.emp_id + system_time as of timestamp @ts +) +select * from ancestors; +set @tmp= " +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr + from emp as e + where name = 'bill' + system_time as of timestamp @ts + union + select ee.emp_id, ee.name, ee.mgr + from emp as ee, ancestors as a + where ee.mgr = a.emp_id + system_time as of timestamp @ts +) +select * from ancestors"; +prepare stmt from @tmp; execute stmt; drop prepare stmt; + +drop table emp; + +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int) with system versioning; +insert into t1 values (1); +set @t0= now(6); +insert into t1 values (2); +delete from t1 where x = 1; +insert into t2 values (10); + +--error ER_VERS_DERIVED_PROHIBITED +select * from (select *, t1.sys_trx_end, t1.sys_trx_end as endo from t1) as s0; +--error ER_VERS_DERIVED_PROHIBITED +select * from (select *, t1.sys_trx_end, t2.sys_trx_start from t1, t2) as s0; + +# system_time propagation from inner to outer +select * from (select * from t1 for system_time as of timestamp @t0, t2) as s0; +with s1 as (select * from t1 for system_time as of timestamp @t0, t2) select * from s1; +# leading table selection +select * from (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) as s2; +with s3 as (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) select * from s3; +# system_time propagation from outer to inner +select * from (select *, t1.sys_trx_start from t2 for system_time as of now, t1) as s4 system_time as of timestamp @t0; +with s5 as (select *, t1.sys_trx_start from t2 for system_time as of now, t1) select * from s5 for system_time as of timestamp @t0; +with s6 as (select *, t1.sys_trx_start from t2 for system_time as of now, t1) select * from s6 system_time as of timestamp @t0; + +# VIEW instead of t1 +set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'"); +prepare q from @q; execute q; drop prepare q; + +# system_time propagation from view +select * from vt1; +# system_time propagation from inner to outer +select * from (select * from vt1, t2) as s0; +# leading table selection +select * from (select *, vt1.sys_trx_end from t2, vt1) as s0; +# system_time propagation from outer to inner +select * from (select *, vt1.sys_trx_start from t2 for system_time as of now, vt1) as s0 system_time as of timestamp @t0; + +drop table t1, t2; +drop view vt1; diff --git a/mysql-test/suite/versioning/t/foreign.opt b/mysql-test/suite/versioning/t/foreign.opt new file mode 100644 index 00000000000..c1a585b67eb --- /dev/null +++ b/mysql-test/suite/versioning/t/foreign.opt @@ -0,0 +1 @@ +--versioning-hide=implicit diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test new file mode 100644 index 00000000000..ec23abac460 --- /dev/null +++ b/mysql-test/suite/versioning/t/foreign.test @@ -0,0 +1,205 @@ +-- source include/have_innodb.inc + +################# +# Test RESTRICT # +################# + +create table parent( + id int unique key +) engine innodb; + +create table child( + parent_id int, + foreign key(parent_id) references parent(id) + on delete restrict + on update restrict +) engine innodb with system versioning; + +insert into parent values(1); +insert into child values(1); + +-- error ER_ROW_IS_REFERENCED_2 +delete from parent where id = 1; +delete from child where parent_id = 1; +delete from parent where id = 1; + +insert into parent values(1); +insert into child values(1); +-- error ER_ROW_IS_REFERENCED_2 +update parent set id=id+1; +delete from child; +update parent set id=id+1; +select * from child for system_time from timestamp '1-1-1' to timestamp now(6); + +drop table child; +drop table parent; + +############################################## +# Test when clustered index is a foreign key # +############################################## + +create table parent( + id int(10) unsigned unique key +) engine innodb; + +create table child( + parent_id int(10) unsigned primary key, + foreign key(parent_id) references parent(id) +) engine innodb with system versioning; + +insert into parent values(1); +insert into child values(1); + +-- error ER_ROW_IS_REFERENCED_2 +delete from parent where id = 1; + +drop table child; +drop table parent; + +################ +# Test CASCADE # +################ + +create table parent( + id int unique key +) engine innodb; + +create table child( + parent_id int, + foreign key(parent_id) references parent(id) + on delete cascade + on update cascade +) engine innodb with system versioning; + +insert into parent values(1); +insert into child values(1); + +delete from parent where id = 1; +select * from child; +select * from child for system_time all; + +insert into parent values(1); +insert into child values(1); +update parent set id = id + 1; +select * from child; +select * from child for system_time all; + +drop table child; +drop table parent; + +create or replace table parent ( + id int primary key +) with system versioning +engine innodb; + +create or replace table child ( + x int, + parent_id int not null, + constraint `parent-fk` + foreign key (parent_id) references parent (id) + on delete cascade + on update restrict +) +engine innodb; + +insert into parent (id) values (2); +insert into child (x, parent_id) values (2, 2); +delete from parent; +select * from child; + +drop table child; +drop table parent; + +create or replace table parent ( + id int primary key +) +engine innodb; + +create or replace table child ( + id int primary key, + parent_id int not null, + constraint `parent-fk` + foreign key (parent_id) references parent (id) + on delete cascade + on update restrict +) with system versioning +engine innodb; + +insert into parent (id) values (3); +insert into child (id, parent_id) values (3, 3); +delete from parent; +select * from child; +select * from child for system_time all; + +drop table child; +drop table parent; + +################# +# Test SET NULL # +################# + +create table parent( + id int unique key +) engine innodb; + +create table child( + parent_id int, + foreign key(parent_id) references parent(id) + on delete set null + on update set null +) engine innodb with system versioning; + +insert into parent values(1); +insert into child values(1); +delete from child; +insert into child values(1); + +delete from parent where id = 1; +select * from child; +select * from child for system_time from timestamp '1-1-1' to timestamp now(6); +delete from child; + +insert into parent values(1); +insert into child values(1); +update parent set id=id+1; +select * from child; +select * from child for system_time from timestamp '1-1-1' to timestamp now(6); + +drop table child; +drop table parent; + +########################### +# Parent table is foreign # +########################### + +create or replace table parent( + id int unique key +) engine innodb with system versioning; + +create or replace table child( + parent_id int, + foreign key(parent_id) references parent(id) +) engine innodb; + +insert into parent values(1); +insert into child values(1); +-- error ER_ROW_IS_REFERENCED_2 +delete from parent; +-- error ER_ROW_IS_REFERENCED_2 +update parent set id=2; + +delete from child; +delete from parent; + +-- error ER_NO_REFERENCED_ROW_2 +insert into child values(1); + +insert into parent values(1); +insert into child values(1); +-- error ER_ROW_IS_REFERENCED_2 +delete from parent; +-- error ER_ROW_IS_REFERENCED_2 +update parent set id=2; + +drop table child; +drop table parent; diff --git a/mysql-test/suite/versioning/t/insert.test b/mysql-test/suite/versioning/t/insert.test new file mode 100644 index 00000000000..730c5478841 --- /dev/null +++ b/mysql-test/suite/versioning/t/insert.test @@ -0,0 +1,197 @@ +-- source suite/versioning/common.inc + +delimiter ~~; +create procedure test_01( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1(x, y) values(3, 4); + insert into t1(x, y) values(2, 3); + insert into t1 values(40, 33); + set @str= concat('select x, y, ', fields, ' from t1'); + prepare stmt from @str; execute stmt; drop prepare stmt; + drop table t1; +end~~ + +create procedure test_02( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1( + id int unsigned auto_increment primary key, + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1(x, y) values(33, 44); + insert into t1(id, x, y) values(20, 33, 44); + insert into t1 values(40, 33, 44); + set @str= concat('select id, x, y, ', fields, ' from t1'); + prepare stmt from @str; execute stmt; drop prepare stmt; + drop table t1; +end~~ + +create procedure test_03( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + create view vt1_1 as select x, y from t1; + insert into t1(x, y) values(8001, 9001); + insert into vt1_1(x, y) values(1001, 2001); + insert into vt1_1 values(1002, 2002); + set @str= concat('select x, y, ', fields, ' from t1'); + prepare stmt from @str; execute stmt; drop prepare stmt; + select x, y from vt1_1; +end~~ + +create procedure test_04( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1( + id bigint primary key, + a int, + b int) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1 values(1, 1, 1); + select sys_trx_start, sys_trx_end from t1 into @sys_start, @sys_end; + select id, a, b from t1; + insert into t1 values(2, 2, 2); + select id, a, b, sys_trx_start > @sys_start as C, sys_trx_end = @sys_end as D from t1 where id = 2; + drop table t1; +end~~ + +create procedure test_05( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat('( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + set @str2= concat('create table t1', @str); + prepare stmt from @str2; execute stmt; drop prepare stmt; + set @str2= concat('create table t2', @str); + prepare stmt from @str2; execute stmt; drop prepare stmt; + insert into t1(x, y) values + (1, 1000), + (2, 2000), + (3, 3000), + (4, 4000), + (5, 5000), + (6, 6000), + (7, 7000), + (8, 8000), + (9, 9000); + delete from t1 where x >= 1; + insert into t1(x, y) values + (1, 1001), + (2, 2001), + (3, 3001), + (4, 4001), + (5, 5001), + (6, 6001), + (7, 7001), + (8, 8001), + (9, 9001); + insert into t2 select x, y from t1 for system_time between timestamp '0000-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; + select x, y from t1; + select x, y from t2; + drop table t1; + drop table t2; +end~~ +delimiter ;~~ + +call test_01('timestamp(6)', 'myisam', 'sys_end'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_02('timestamp(6)', 'myisam', 'sys_end'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_03('timestamp(6)', 'myisam', 'sys_end'); +drop table t1; +drop view vt1_1; + +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +drop table t1; +drop view vt1_1; + +call test_04('timestamp(6)', 'myisam', 'sys_end'); +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_05('timestamp(6)', 'myisam', 'sys_end'); +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +# VTQ test + +call verify_vtq; + +create table t1( + x int unsigned, + sys_start bigint unsigned generated always as row start, + sys_end bigint unsigned generated always as row end, + period for system_time (sys_start, sys_end)) +with system versioning engine=innodb; + +create table t2(x int unsigned) engine=innodb; + +start transaction; +insert into t1(x) values(1); +commit; +call verify_vtq; + +start transaction; +insert into t2(x) values(1); +savepoint a; +insert into t1(x) values(1); +rollback to a; +commit; +call verify_vtq; + +drop table t1; +drop table t2; + +drop procedure test_01; +drop procedure test_02; +drop procedure test_03; +drop procedure test_04; +drop procedure test_05; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/optimized.test b/mysql-test/suite/versioning/t/optimized.test new file mode 100644 index 00000000000..6c508d04508 --- /dev/null +++ b/mysql-test/suite/versioning/t/optimized.test @@ -0,0 +1,40 @@ +create table t ( + a int, + b int without system versioning +) with system versioning; + +insert into t values(1, 2); +insert into t values(3, 4); +select * from t; +select a from t for system_time as of timestamp now(6); +select a, b, b+0 from t for system_time as of timestamp now(6); +select * from t for system_time as of timestamp now(6); +select count(*) from t group by b system_time as of timestamp now(6); +select * from t for system_time as of timestamp now(6) order by b asc; +select * from t for system_time as of timestamp now(6) order by b desc; +select * from t group by a having a=2 system_time as of timestamp now(6); +select * from t group by b having b=2 system_time as of timestamp now(6); +select a from t where b=2 system_time as of timestamp now(6); +select a from t where b=NULL system_time as of timestamp now(6); +select a from t where b is NULL system_time as of timestamp now(6); +select count(*), b from t group by b having b=NULL system_time as of timestamp now(6); +select a, b from t; + +select count(*) from t for system_time as of timestamp now(6) group by b; +select * from t for system_time as of timestamp now(6) group by b having b=2; +select a from t for system_time as of timestamp now(6) where b=2; +select a from t for system_time as of timestamp now(6) where b=NULL; +select a from t for system_time as of timestamp now(6) where b is NULL; +select count(*), b from t for system_time as of timestamp now(6) group by b having b=NULL; + +create or replace table t ( + a int, + b int not null without system versioning +) with system versioning; + +insert into t values (1, 2), (3, 4); + +select * from t for system_time as of timestamp now(6); +select * from t for system_time as of timestamp now(6) where b is NULL; + +drop table t; diff --git a/mysql-test/suite/versioning/t/partition.combinations b/mysql-test/suite/versioning/t/partition.combinations new file mode 100644 index 00000000000..d79429f34f7 --- /dev/null +++ b/mysql-test/suite/versioning/t/partition.combinations @@ -0,0 +1,7 @@ +[innodb] +partition +default-storage-engine=innodb + +[myisam] +partition +default-storage-engine=myisam diff --git a/mysql-test/suite/versioning/t/partition.opt b/mysql-test/suite/versioning/t/partition.opt new file mode 100644 index 00000000000..c1a585b67eb --- /dev/null +++ b/mysql-test/suite/versioning/t/partition.opt @@ -0,0 +1 @@ +--versioning-hide=implicit diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test new file mode 100644 index 00000000000..479b63399bf --- /dev/null +++ b/mysql-test/suite/versioning/t/partition.test @@ -0,0 +1,242 @@ +-- source suite/versioning/common.inc + +### check System Versioning and conventional partitioning + +create table t1 (x int) +with system versioning +partition by range columns (x) ( + partition p0 values less than (100), + partition p1 values less than (1000)); + +insert into t1 values (3), (300); +select * from t1; +select * from t1 partition (p0); +select * from t1 partition (p1); + +delete from t1; +select * from t1; +select * from t1 for system_time all; +select * from t1 partition (p0) for system_time all; +select * from t1 partition (p1) for system_time all; + +### check server-level partitioning + +# create errors +--error ER_VERSIONING_REQUIRED +create or replace table t1 (x int) +partition by system_time ( + partition p0 versioning, + partition pn as of now); + +create or replace table t1 (x int); +--error ER_VERSIONING_REQUIRED,ER_VERSIONING_REQUIRED +alter table t1 +partition by system_time ( + partition p0 versioning, + partition pn as of now); + +--error ER_VERS_WRONG_PARTS +create or replace table t1 (x int) +with system versioning +partition by system_time ( + partition p0 as of now); + +--error ER_VERS_WRONG_PARTS +create or replace table t1 (x int) +with system versioning +partition by system_time ( + partition p0 as of now, + partition p1 as of now); + +--error ER_VERS_WRONG_PARTS +create or replace table t1 (x int) +with system versioning +partition by system_time ( + partition p0 versioning, + partition p1 versioning); + +--error ER_VERS_WRONG_PARTS +create or replace table t1 (x int) +with system versioning +partition by system_time ( + partition pn as of now, + partition p0 versioning); + +create or replace table t1 (x int) +with system versioning +partition by system_time ( + partition p0 versioning, + partition pn as of now); + +# alter table +--error ER_VERS_WRONG_PARTS +alter table t1 add partition ( + partition p1 as of now); + +alter table t1 add partition ( + partition p1 versioning); + +--replace_result InnoDB ${INNODB_OR_MYISAM} MyISAM ${INNODB_OR_MYISAM} "bigint(20) unsigned" ${SYS_TRX_TYPE} timestamp(6) ${SYS_TRX_TYPE} +show create table t1; + +insert into t1 values (1), (2); + +--error ER_VERS_WRONG_PARTS +alter table t1 drop partition pn; +alter table t1 drop partition p1; +--error ER_VERS_WRONG_PARTS +alter table t1 drop partition p0; + +select x from t1; + +# Bug #260: incorrect IB partitioning warning +create or replace table t1 (x int) +with system versioning +partition by system_time limit 1 ( + partition p0 versioning, + partition pn as of now); +alter table t1 change x big int; + +# insert, delete, update +create or replace table t1 (x int) +with system versioning +partition by system_time ( + partition p0 versioning, + partition pn as of now); + +set @now= now(6); +insert into t1 values (1); +set @ts_start= sys_commit_ts('sys_trx_start'); +set @ts_end= sys_commit_ts('sys_trx_end'); +set @str= concat('select x, ', @ts_start, ' < @now as A, ', @ts_end, ' > @now as B from t1 partition (p0) for system_time all'); +prepare select_p0 from @str; +set @str= concat('select x, ', @ts_start, ' > @now as C, ', @ts_end, ' = timestamp\'2038-01-19 03:14:07.999999\' as D from t1 partition (pn) for system_time all'); +prepare select_pn from @str; + +execute select_p0; +execute select_pn; + +# pruning check +--replace_result ALL system "Using where" "" +explain partitions select * from t1; + +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +set @now= now(6); +delete from t1; +execute select_p0; +execute select_pn; + +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all into @ts1'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +select @ts0 = @ts1; + +set @now= now(6); +insert into t1 values (2); +execute select_p0; +execute select_pn; + +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +set @now= now(6); +update t1 set x = x + 1; +execute select_p0; +execute select_pn; + +drop prepare select_p0; +drop prepare select_pn; + +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all where x = 2 into @ts1'); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @str= concat('select ', @ts_end, ' from t1 partition (p0) for system_time all where x = 2 into @ts2'); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts3'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +select @ts0 = @ts1; +select @ts2 = @ts3; + +# rotation by LIMIT +--error ER_VERS_WRONG_PARAMS +create or replace table t1 (x int) +with system versioning +partition by system_time limit 0 ( + partition p0 versioning, + partition p1 versioning, + partition pn as of now); + +create or replace table t1 (x int) +with system versioning +partition by system_time limit 1 ( + partition p0 versioning, + partition p1 versioning, + partition pn as of now); + +--replace_result InnoDB ${INNODB_OR_MYISAM} MyISAM ${INNODB_OR_MYISAM} "bigint(20) unsigned" ${SYS_TRX_TYPE} timestamp(6) ${SYS_TRX_TYPE} +show create table t1; + +--error ER_DROP_PARTITION_NON_EXISTENT +alter table t1 drop partition non_existent; + +insert into t1 values (1), (2); +select * from t1 partition (pn); +delete from t1; +select * from t1 partition (p0) for system_time all; +select * from t1 partition (p1) for system_time all; + +insert into t1 values (3); +delete from t1; +select * from t1 partition (p1) for system_time all; + +# rotation by INTERVAL +--error ER_VERS_WRONG_PARAMS +create or replace table t1 (x int) +with system versioning +partition by system_time interval 0 second ( + partition p0 versioning, + partition p1 versioning, + partition pn as of now); + +create or replace table t1 (x int) +with system versioning +partition by system_time interval 1 second ( + partition p0 versioning, + partition p1 versioning, + partition pn as of now); + +insert into t1 values (1), (2), (3); +select * from t1 partition (pn); +delete from t1; +select * from t1 partition (p0) for system_time all; + +--sleep 2 +insert into t1 values (4); +delete from t1; +select * from t1 partition (p1) for system_time all; + +# Subpartitions +create or replace table t1 (x int) +with system versioning +partition by system_time limit 1 +subpartition by key (x) +subpartitions 2 ( + partition p0 versioning, + partition p1 versioning, + partition pn as of now); + +insert into t1 (x) values (1), (2), (3); +select * from t1 partition (pnsp0); +select * from t1 partition (pnsp1); + +delete from t1; +select * from t1 partition (p0sp0) for system_time all; +select * from t1 partition (p0sp1) for system_time all; +select * from t1 partition (p1sp0) for system_time all; +select * from t1 partition (p1sp1) for system_time all; + +drop table t1; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/rpl_mixed.combinations b/mysql-test/suite/versioning/t/rpl_mixed.combinations new file mode 100644 index 00000000000..9a1c771672c --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_mixed.combinations @@ -0,0 +1,5 @@ +[myisam] +default-storage-engine=myisam + +[innodb] +default-storage-engine=innodb diff --git a/mysql-test/suite/versioning/t/rpl_mixed.test b/mysql-test/suite/versioning/t/rpl_mixed.test new file mode 100644 index 00000000000..09612e664dc --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_mixed.test @@ -0,0 +1,7 @@ +-- source include/have_binlog_format_mixed.inc +-- source include/master-slave.inc +-- source include/have_innodb.inc + +-- source rpl_test.inc + +-- source include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl_row.combinations b/mysql-test/suite/versioning/t/rpl_row.combinations new file mode 100644 index 00000000000..9a1c771672c --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_row.combinations @@ -0,0 +1,5 @@ +[myisam] +default-storage-engine=myisam + +[innodb] +default-storage-engine=innodb diff --git a/mysql-test/suite/versioning/t/rpl_row.test b/mysql-test/suite/versioning/t/rpl_row.test new file mode 100644 index 00000000000..cf04c52dd16 --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_row.test @@ -0,0 +1,7 @@ +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +-- source include/have_innodb.inc + +-- source rpl_test.inc + +-- source include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl_stmt.combinations b/mysql-test/suite/versioning/t/rpl_stmt.combinations new file mode 100644 index 00000000000..75fb20d9f5e --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_stmt.combinations @@ -0,0 +1,5 @@ +[innodb] +default-storage-engine=innodb + +[myisam] +default-storage-engine=myisam diff --git a/mysql-test/suite/versioning/t/rpl_stmt.test b/mysql-test/suite/versioning/t/rpl_stmt.test new file mode 100644 index 00000000000..bc4e76cdf5d --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_stmt.test @@ -0,0 +1,7 @@ +-- source include/have_binlog_format_statement.inc +-- source include/master-slave.inc +-- source include/have_innodb.inc + +-- source rpl_test.inc + +-- source include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl_test.inc b/mysql-test/suite/versioning/t/rpl_test.inc new file mode 100644 index 00000000000..5beee9f9dc6 --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_test.inc @@ -0,0 +1,90 @@ +#BUG#12662190 - COM_COMMIT IS NOT INCREMENTED FROM THE BINARY LOGS ON SLAVE, COM_BEGIN IS +#Testing command counters -BEFORE. +#Storing the before counts of Slave +connection slave; +let $slave_com_commit_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_commit', Value, 1); +let $slave_com_insert_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_insert', Value, 1); +let $slave_com_delete_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_delete', Value, 1); +let $slave_com_update_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_update', Value, 1); + +connection master; +CREATE TABLE t1 (x int) with system versioning; +insert into t1 values (1); +SELECT * FROM t1; +delete from t1; +select * from t1; +select * from t1 for system_time all; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +connection master; +insert into t1 values (2); +sync_slave_with_master; +select * from t1; + +connection master; +update t1 set x = 3; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +# check unversioned -> versioned replication +connection master; +create or replace table t1 (x int primary key); +sync_slave_with_master; +alter table t1 with system versioning; + +connection master; +insert into t1 values (1); +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +connection master; +update t1 set x= 2 where x = 1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +connection master; +delete from t1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +# same thing (UPDATE, DELETE), but without PK +connection master; +create or replace table t1 (x int); +sync_slave_with_master; +alter table t1 with system versioning; + +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +connection master; +delete from t1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +# multi-update +connection master; +create or replace table t1 (x int) with system versioning; +create or replace table t2 (x int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +update t1, t2 set t1.x=11, t2.x=22; +sync_slave_with_master; +select * from t1; +select * from t2; +select * from t1 for system_time all; +select * from t2 for system_time all; + + +connection master; +drop table t1, t2; diff --git a/mysql-test/suite/versioning/t/rpl_test.opt b/mysql-test/suite/versioning/t/rpl_test.opt new file mode 100644 index 00000000000..c1a585b67eb --- /dev/null +++ b/mysql-test/suite/versioning/t/rpl_test.opt @@ -0,0 +1 @@ +--versioning-hide=implicit diff --git a/mysql-test/suite/versioning/t/select.combinations b/mysql-test/suite/versioning/t/select.combinations new file mode 100644 index 00000000000..75fb20d9f5e --- /dev/null +++ b/mysql-test/suite/versioning/t/select.combinations @@ -0,0 +1,5 @@ +[innodb] +default-storage-engine=innodb + +[myisam] +default-storage-engine=myisam diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test new file mode 100644 index 00000000000..6ec45db6c08 --- /dev/null +++ b/mysql-test/suite/versioning/t/select.test @@ -0,0 +1,189 @@ +-- source suite/versioning/common.inc + +# test_01 + +create or replace table t1 ( + x int unsigned, + y int unsigned +) with system versioning; + +insert into t1 (x, y) values + (0, 100), + (1, 101), + (2, 102), + (3, 103), + (4, 104), + (5, 105), + (6, 106), + (7, 107), + (8, 108), + (9, 109); + +set @t0= now(6); +if ($default_engine == 'innodb') +{ +--disable_query_log + select sys_trx_start from t1 limit 1 into @x0; +--enable_query_log +} + +delete from t1 where x = 3; +delete from t1 where x > 7; + +insert into t1(x, y) values(3, 33); +select sys_trx_start from t1 where x = 3 and y = 33 into @t1; +if ($default_engine == 'innodb') +{ +--disable_query_log + set @x1= @t1; + select vtq_commit_ts(@x1) into @t1; +--enable_query_log +} + +select x, y from t1; +select x as ASOF_x, y from t1 for system_time as of timestamp @t0; +select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as ALL_x, y from t1 for system_time all; + +--disable_query_log +if ($default_engine == 'innodb') +{ + select x as ASOF2_x, y from t1 for system_time as of @x0; + select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1; + select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1; +} +if ($default_engine != 'innodb') +{ + select x as ASOF2_x, y from t1 for system_time as of @t0; + select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; + select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +} +--enable_query_log + +# test_02 + +create or replace table t1 ( + x int unsigned, + y int unsigned +) with system versioning; +create or replace table t2 ( + x int unsigned, + y int unsigned +) with system versioning; + +insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5); +insert into t2 values (1, 2), (2, 1), (3, 1); +set @t0= now(6); + +select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x; +select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x; +select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x; + +delete from t1; +delete from t2; + +select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x +system_time as of timestamp @t0; +select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x +system_time as of timestamp @t0; +select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x +system_time as of timestamp @t0; + +drop table t1; +drop table t2; + +# Wildcard expansion on hidden fields + +create table t1( + A int +) with system versioning; +insert into t1 values(1); +select * from t1; + +create or replace table t1 (x int); +insert into t1 values (1); +--error ER_VERSIONING_REQUIRED +select * from t1 for system_time all; + +create or replace table t1 (x int) with system versioning; +insert into t1 values (1); +--error ER_VERS_HISTORY_LOCK +select * from t1 for system_time all for update; + +create or replace table t1 (a int not null auto_increment primary key) with system versioning; +select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; + +create or replace table t1 (a int) with system versioning; +create or replace table t2 (a int) with system versioning; +insert into t1 values(1); +insert into t2 values(1); +create view v1 as select * from t2 inner join t1 using (a); +select * from v1; +drop view v1; + +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create view vt1 as select a from t1; +select * from t1 natural join vt1; +drop view vt1; + +create or replace table t1(x int) with system versioning; +select * from (t1 as r left join t1 as u using (x)), t1; + +# @end should be max +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create trigger read_end after update on t1 + for each row set @end = old.sys_trx_end; +update t1 set a=2; +--replace_result 18446744073709551615 MAX_RESULT "2038-01-19 03:14:07.999999" MAX_RESULT +select @end; + +create or replace table t1 (a int) with system versioning; +create or replace table t2 (b int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +select * from (select * from t1 cross join t2) as tmp; +select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; +select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp; + +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +select * from t1 for system_time all natural left join t2 for system_time all; + +# natural join of a view and table +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +create or replace view v1 as select a1 from t1; + +select * from v1 natural join t2; +select * from v1 natural left join t2; +select * from v1 natural right join t2; + +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1; + +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int) with system versioning; +insert into t1 values (1), (2), (3); +delete from t1 where x = 3; +insert into t2 values (1); +select * from t1, t2 system_time all; + +--error ER_VERS_UNUSED_CLAUSE +select * from t1 for system_time all, t2 for system_time all system_time all; + +drop view v1; +drop table t1, t2; + +call innodb_verify_vtq(27); + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/select_sp.combinations b/mysql-test/suite/versioning/t/select_sp.combinations new file mode 100644 index 00000000000..75fb20d9f5e --- /dev/null +++ b/mysql-test/suite/versioning/t/select_sp.combinations @@ -0,0 +1,5 @@ +[innodb] +default-storage-engine=innodb + +[myisam] +default-storage-engine=myisam diff --git a/mysql-test/suite/versioning/t/select_sp.test b/mysql-test/suite/versioning/t/select_sp.test new file mode 100644 index 00000000000..bd165c3bd16 --- /dev/null +++ b/mysql-test/suite/versioning/t/select_sp.test @@ -0,0 +1,205 @@ +-- source suite/versioning/common.inc + +delimiter ~~; +create procedure test_01() +begin + declare engine varchar(255) default default_engine(); + declare sys_type varchar(255) default sys_datatype(); + declare fields varchar(255) default sys_commit_ts('sys_start'); + + set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1 (x, y) values + (0, 100), + (1, 101), + (2, 102), + (3, 103), + (4, 104), + (5, 105), + (6, 106), + (7, 107), + (8, 108), + (9, 109); + set @t0= now(6); + if engine = 'innodb' then + select sys_start from t1 limit 1 into @x0; + end if; + + delete from t1 where x = 3; + delete from t1 where x > 7; + + insert into t1(x, y) values(3, 33); + select sys_start from t1 where x = 3 and y = 33 into @t1; + if engine = 'innodb' then + set @x1= @t1; + select vtq_commit_ts(@x1) into @t1; + end if; + + select x, y from t1; + select x as ASOF_x, y from t1 for system_time as of timestamp @t0; + select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; + select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; + select x as ALL_x, y from t1 for system_time all; + + if engine = 'innodb' then + select x as ASOF2_x, y from t1 for system_time as of @x0; + select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1; + select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1; + else + select x as ASOF2_x, y from t1 for system_time as of @t0; + select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; + select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; + end if; + + drop table t1; +end~~ + +create or replace procedure test_02() +begin + declare engine varchar(255) default default_engine(); + declare sys_type varchar(255) default sys_datatype(); + declare fields varchar(255) default sys_commit_ts('sys_start'); + + set @str0= concat('( + x int, + y int, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + set @str= concat('create or replace table t1', @str0); + prepare stmt from @str; execute stmt; drop prepare stmt; + set @str= concat('create or replace table t2', @str0); + prepare stmt from @str; execute stmt; drop prepare stmt; + + insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5); + insert into t2 values (1, 2), (2, 1), (3, 1); + set @t0= now(6); + + select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x; + select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x; + select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x; + + delete from t1; + delete from t2; + + select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x + system_time as of timestamp @t0; + select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x + system_time as of timestamp @t0; + select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x + system_time as of timestamp @t0; + + drop table t1; + drop table t2; +end~~ +delimiter ;~~ + +call test_01(); +call test_02(); + +# wildcard expansion on hidden fields. +create table t1( + A int +) with system versioning; +insert into t1 values(1); +select * from t1; + +create or replace table t1 (x int); +insert into t1 values (1); +--error ER_VERSIONING_REQUIRED +select * from t1 for system_time all; + +create or replace table t1 (x int) with system versioning; +insert into t1 values (1); +--error ER_VERS_HISTORY_LOCK +select * from t1 for system_time all for update; + +create or replace table t1 (a int not null auto_increment primary key) with system versioning; +select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; + +create or replace table t1 (a int) with system versioning; +create or replace table t2 (a int) with system versioning; +insert into t1 values(1); +insert into t2 values(1); +create view v1 as select * from t2 inner join t1 using (a); +select * from v1; +drop view v1; + +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create view vt1 as select a from t1; +select * from t1 natural join vt1; +drop view vt1; + +create or replace table t1(x int) with system versioning; +select * from (t1 as r left join t1 as u using (x)), t1; + +# @end should be max +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +create trigger read_end after update on t1 + for each row set @end = old.sys_trx_end; +update t1 set a=2; +--replace_result 18446744073709551615 MAX_RESULT "2038-01-19 03:14:07.999999" MAX_RESULT +select @end; + +create or replace table t1 (a int) with system versioning; +create or replace table t2 (b int) with system versioning; +insert into t1 values (1); +insert into t2 values (2); +select * from (select * from t1 cross join t2) as tmp; +select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; +select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp; + +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +select * from t1 for system_time all natural left join t2 for system_time all; + +# natural join of a view and table +create or replace table t1(a1 int) with system versioning; +create or replace table t2(a2 int) with system versioning; +insert into t1 values(1),(2); +insert into t2 values(1),(2); +create or replace view v1 as select a1 from t1; + +select * from v1 natural join t2; +select * from v1 natural left join t2; +select * from v1 natural right join t2; + +create or replace table t1 (a int) with system versioning; +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1; + +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int) with system versioning; +insert into t1 values (1), (2), (3); +delete from t1 where x = 3; +insert into t2 values (1); +select * from t1, t2 system_time all; + +--error ER_VERS_UNUSED_CLAUSE +select * from t1 for system_time all, t2 for system_time all system_time all; + +drop view v1; +drop table t1, t2; + +call innodb_verify_vtq(27); + +drop procedure test_01; +drop procedure test_02; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/simple.opt b/mysql-test/suite/versioning/t/simple.opt new file mode 100644 index 00000000000..993df05011e --- /dev/null +++ b/mysql-test/suite/versioning/t/simple.opt @@ -0,0 +1,2 @@ +--innodb --default-storage-engine=innodb +--plugin-load=versioning diff --git a/mysql-test/suite/versioning/t/simple.test b/mysql-test/suite/versioning/t/simple.test new file mode 100644 index 00000000000..d32ea939279 --- /dev/null +++ b/mysql-test/suite/versioning/t/simple.test @@ -0,0 +1,70 @@ +create or replace table dept ( + dept_id int(10) primary key, + name varchar(100) +) +with system versioning; + +create or replace table emp ( + emp_id int(10) primary key, + dept_id int(10), + name varchar(100), + salary int(10), + constraint `dept-emp-fk` + foreign key (dept_id) references dept (dept_id) + on delete cascade + on update restrict +) +with system versioning; + +select now() into @ts_0; + +insert into dept (dept_id, name) values (10, "accounting"); +commit; + +select vtq_commit_ts(sys_trx_start) into @ts_1 from dept where dept_id=10; + +insert into emp (emp_id, name, salary, dept_id) values (1, "bill", 1000, 10); +commit; + +select vtq_commit_ts(sys_trx_start) into @ts_2 from emp where name="bill"; + +select * from emp; + +update emp set salary=2000 where name="bill"; +commit; + +select vtq_commit_ts(sys_trx_start) into @ts_3 from emp where name="bill"; + +select * from emp; +select * from emp for system_time as of timestamp @ts_2; +select * from emp for system_time as of timestamp @ts_3; +select * from emp e, dept d +where d.dept_id = 10 + and d.dept_id = e.dept_id; + +select * from emp e, dept d +where d.dept_id = 10 + and d.dept_id = e.dept_id +system_time from timestamp @ts_1 to timestamp @ts_2; + +select * from emp e, dept d +where d.dept_id = 10 + and d.dept_id = e.dept_id +system_time as of timestamp @ts_0; + +select * from emp e, dept d +where d.dept_id = 10 + and d.dept_id = e.dept_id +system_time as of timestamp @ts_1; + +select * from emp e, dept d +where d.dept_id = 10 + and d.dept_id = e.dept_id +system_time as of timestamp @ts_2; + +select * from emp e, dept d +where d.dept_id = 10 + and d.dept_id = e.dept_id +system_time as of timestamp @ts_3; + +drop table emp, dept; diff --git a/mysql-test/suite/versioning/t/sysvars.opt b/mysql-test/suite/versioning/t/sysvars.opt new file mode 100644 index 00000000000..c1a585b67eb --- /dev/null +++ b/mysql-test/suite/versioning/t/sysvars.opt @@ -0,0 +1 @@ +--versioning-hide=implicit diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test new file mode 100644 index 00000000000..6b713c29239 --- /dev/null +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -0,0 +1,111 @@ +create table t (a int) with system versioning; +insert into t values (1); +update t set a= 2; + +show global variables like 'versioning_current_timestamp'; +show variables like 'versioning_current_timestamp'; +select * from t; + +set versioning_current_timestamp = '2031-1-1 0:0:0'; +show variables like 'versioning_current_timestamp'; +select * from t; + +set versioning_current_timestamp = '2011-1-1 0:0:0'; +show variables like 'versioning_current_timestamp'; +select * from t; + +set versioning_current_timestamp = 'all'; +show variables like 'versioning_current_timestamp'; +select * from t; + +create view vt as select * from t; +select * from t; +drop view vt; + +select * from (select * from t) as tt; + +# global +--error ER_WRONG_VALUE_FOR_VAR +set global versioning_current_timestamp= 'alley'; +--error ER_WRONG_VALUE_FOR_VAR +set global versioning_current_timestamp= null; +--error ER_WRONG_TYPE_FOR_VAR +set global versioning_current_timestamp= 1; +--error ER_WRONG_TYPE_FOR_VAR +set global versioning_current_timestamp= 1.1; + +# session +--error ER_WRONG_VALUE_FOR_VAR +set versioning_current_timestamp= 'alley'; +--error ER_WRONG_VALUE_FOR_VAR +set versioning_current_timestamp= null; +--error ER_WRONG_TYPE_FOR_VAR +set versioning_current_timestamp= 1; +--error ER_WRONG_TYPE_FOR_VAR +set versioning_current_timestamp= 1.1; + +# global +set global versioning_current_timestamp= '1911-11-11 11:11:11.1111119'; +show global variables like 'versioning_current_timestamp'; + +set global versioning_current_timestamp= '1900-01-01 00:00:00'; +show global variables like 'versioning_current_timestamp'; + +set global versioning_current_timestamp= timestamp'1911-11-11 11:11:11.1111119'; +show global variables like 'versioning_current_timestamp'; + +set @ts= timestamp'1900-01-01 00:00:00'; +set global versioning_current_timestamp= @ts; +show global variables like 'versioning_current_timestamp'; + +# session +set versioning_current_timestamp= '1911-11-11 11:11:11.1111119'; +show variables like 'versioning_current_timestamp'; + +set versioning_current_timestamp= '1900-01-01 00:00:00'; +show variables like 'versioning_current_timestamp'; + +set versioning_current_timestamp= timestamp'1911-11-11 11:11:11.1111119'; +show variables like 'versioning_current_timestamp'; + +set @ts= timestamp'1900-01-01 00:00:00'; +set versioning_current_timestamp= @ts; +show variables like 'versioning_current_timestamp'; + +set global versioning_current_timestamp= 'now'; +set versioning_current_timestamp= 'now'; + +show variables where variable_name = "versioning_hide"; +select * from t for system_time all; + +set versioning_hide= AUTO; +select * from t; +select * from t for system_time as of timestamp current_timestamp(6); +--replace_regex /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}/TIMESTAMP/ +select * from t for system_time all; +--replace_regex /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}/TIMESTAMP/ +select * from t for system_time from '0-0-0' to current_timestamp(6); +--replace_regex /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}/TIMESTAMP/ +select * from t for system_time between '0-0-0' and current_timestamp(6); + +set versioning_hide= NEVER; +--replace_regex /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}/TIMESTAMP/ +select * from t; + +set versioning_hide= FULL; +create or replace table t ( + x int, + st timestamp(6) generated always as row start, + en timestamp(6) generated always as row end, + period for system_time (st, en)) +with system versioning; + +show create table t; +insert into t values (2); +delete from t; + +select * from t; +select * from t for system_time all; + +drop table t; +set versioning_hide= IMPLICIT; diff --git a/mysql-test/suite/versioning/t/truncate.combinations b/mysql-test/suite/versioning/t/truncate.combinations new file mode 100644 index 00000000000..75fb20d9f5e --- /dev/null +++ b/mysql-test/suite/versioning/t/truncate.combinations @@ -0,0 +1,5 @@ +[innodb] +default-storage-engine=innodb + +[myisam] +default-storage-engine=myisam diff --git a/mysql-test/suite/versioning/t/truncate.opt b/mysql-test/suite/versioning/t/truncate.opt new file mode 100644 index 00000000000..c1a585b67eb --- /dev/null +++ b/mysql-test/suite/versioning/t/truncate.opt @@ -0,0 +1 @@ +--versioning-hide=implicit diff --git a/mysql-test/suite/versioning/t/truncate.test b/mysql-test/suite/versioning/t/truncate.test new file mode 100644 index 00000000000..1de94487570 --- /dev/null +++ b/mysql-test/suite/versioning/t/truncate.test @@ -0,0 +1,29 @@ +-- source include/have_innodb.inc + +create table t (a int); +--error ER_VERSIONING_REQUIRED +truncate t to system_time now(); + +# TRUNCATE is not DELETE and trigger must not be called. +create or replace table t (a int) with system versioning; +insert into t values (1); +update t set a=2; +set @test = 'correct'; +create trigger trg_before before delete on t for each row set @test = 'incorrect'; +create trigger trg_after after delete on t for each row set @test = 'incorrect'; +truncate t to system_time now(6); +select @test from t; +drop table t; + +create table t (a int) with system versioning; +insert into t values (1), (2); +update t set a=11 where a=1; +set @ts1=now(6); +update t set a=22 where a=2; +select * from t for system_time all; +truncate t to system_time timestamp @ts1; +select * from t for system_time all; +truncate table t to system_time timestamp now(6); +select * from t for system_time all; + +drop table t; diff --git a/mysql-test/suite/versioning/t/truncate_privilege.test b/mysql-test/suite/versioning/t/truncate_privilege.test new file mode 100644 index 00000000000..7042f359e13 --- /dev/null +++ b/mysql-test/suite/versioning/t/truncate_privilege.test @@ -0,0 +1,41 @@ +# Can't test with embedded server +-- source include/not_embedded.inc + +--source include/have_innodb.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +connect (root,localhost,root,,test); +connection root; + +--disable_warnings +create database mysqltest; +--enable_warnings + +create user mysqltest_1@localhost; +connect (user1,localhost,mysqltest_1,,test); +connection user1; + +connection root; +create table mysqltest.t (a int) with system versioning; + +connection user1; +show grants; +--error ER_TABLEACCESS_DENIED_ERROR +truncate mysqltest.t to system_time now(); + +connection root; +grant delete versioning rows on mysqltest.* to mysqltest_1@localhost; +grant delete versioning rows on mysqltest.t to mysqltest_1@localhost; + +connection user1; +show grants; +truncate mysqltest.t to system_time now(); + +connection root; +grant all on *.* to mysqltest_1@localhost; +show grants for mysqltest_1@localhost; + +drop user mysqltest_1@localhost; +drop database mysqltest; diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test new file mode 100644 index 00000000000..b7e0c1fc85f --- /dev/null +++ b/mysql-test/suite/versioning/t/update.test @@ -0,0 +1,267 @@ +-- source suite/versioning/common.inc + +delimiter ~~; +create procedure test_01( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1(x, y) values + (1, 1000), + (2, 2000), + (3, 3000), + (4, 4000), + (5, 5000), + (6, 6000), + (7, 7000), + (8, 8000), + (9, 9000); + select x, y from t1; + update t1 set y = y + 1 where x > 7; + select x, y from t1; + select x, y from t1 for system_time + between timestamp '0000-0-0 0:0:0' + and timestamp '2038-01-19 04:14:07'; + drop table t1; +end~~ + +create procedure test_02( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1 ( + id bigint primary key, + x int, + y int without system versioning) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1 values(1, 1, 1); + set @ins_t= now(6); + select sys_trx_start into @tmp1 from t1; + update t1 set x= 11, y= 11 where id = 1; + select @tmp1 < sys_trx_start as A1, x, y from t1; + + select sys_trx_start into @tmp1 from t1; + update t1 set y= 1 where id = 1; + select @tmp1 = sys_trx_start as A2, x from t1; + + drop table t1; +end~~ + +create procedure test_03( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1 ( + x int, + y int) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + + insert into t1 (x, y) values (1, 1), (2, 1), (3, 1); + + start transaction; + update t1 set y= y + 1 where x = 3; + update t1 set y= y + 1 where x = 3; + commit; + + select x, y from t1 for system_time + between timestamp '0000-0-0 0:0:0' + and timestamp '2038-01-19 04:14:07'; + + drop table t1; +end~~ + +create procedure test_04( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1 ( + id int primary key auto_increment, + x int) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + + set @t0= now(6); + insert into t1 (x) values (1); + set @t1= now(6); + update t1 set x= 2 where id = 1; + set @t2= now(6); + update t1 set x= 3 where id = 1; + + select x from t1 for system_time as of timestamp @t0; + select x from t1 for system_time as of timestamp @t1; + select x from t1 for system_time as of timestamp @t2; + select x from t1 for system_time as of timestamp now(6); + + drop table t1; +end~~ + +create procedure test_05( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat(' + create table t1( + x int unsigned, + sys_end ', sys_type, ' generated always as row end, + sys_start ', sys_type, ' generated always as row start, + y int unsigned, + period for system_time (sys_start, sys_end), + primary key(x, y)) + with system versioning + engine ', engine); + prepare stmt from @str; execute stmt; drop prepare stmt; + insert into t1(x, y) values + (1, 1000), + (2, 2000), + (3, 3000), + (4, 4000), + (5, 5000), + (6, 6000), + (7, 7000), + (8, 8000), + (9, 9000); + insert into t1(x, y) values(3, 3000) on duplicate key update y = y+1; + insert into t1(x, y) values(4, 4000) on duplicate key update y = y+1; + insert into t1(x, y) values(4, 4001) on duplicate key update y = y+1; + insert into t1(x, y) values(4, 4444) on duplicate key update y = y+1; + select x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; + select x, y from t1; + drop table t1; +end~~ + +create procedure test_06( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat('( + x int unsigned, + y int unsigned, + sys_start ', sys_type, ' generated always as row start, + sys_end ', sys_type, ' generated always as row end, + period for system_time (sys_start, sys_end)) + with system versioning + engine ', engine); + set @str2= concat('create table t1', @str); + prepare stmt from @str2; execute stmt; drop prepare stmt; + set @str2= concat('create table t2', @str); + prepare stmt from @str2; execute stmt; drop prepare stmt; + insert into t1(x, y) values + (1, 1000), + (2, 2000), + (3, 3000), + (4, 4000), + (5, 5000), + (6, 6000), + (7, 7000), + (8, 8000), + (9, 9000); + insert into t2(x, y) values + (1, 1010), + (2, 2010), + (3, 3010), + (4, 4010), + (5, 5010), + (6, 6010), + (7, 7010), + (8, 8010), + (9, 9010); + update t1, t2 set t1.y = t1.x + t1.y, t2.y = t2.x + t2.y where t1.x > 7 and t2.x < 7; + select x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; + select x, y from t1; + select x, y from t2 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0'; + select x, y from t2; + drop table t1; + drop table t2; +end~~ + +create procedure test_07( + sys_type varchar(255), + engine varchar(255), + fields varchar(255)) +begin + set @str= concat('( + id bigint primary key, + name varchar(128) with system versioning, + salary bigint) + engine ', engine); + + set @str2= concat('create table t1', @str); + prepare stmt from @str2; execute stmt; drop prepare stmt; + set @str2= concat('create table t2', @str); + prepare stmt from @str2; execute stmt; drop prepare stmt; + + insert into t1 values (1, "Jeremy", 3000); + insert into t2 values (1, "Jeremy", 4000); + + select sys_trx_start into @tmp1 from t1; + select sys_trx_start into @tmp2 from t2; + update t1, t2 set t1.name= "Jerry", t2.name= "Jerry" where t1.id = t2.id and t1.name = "Jeremy"; + select @tmp1 < sys_trx_start as A1, name from t1; + select @tmp2 < sys_trx_start as A2, name from t2; + + select sys_trx_start into @tmp1 from t1; + select sys_trx_start into @tmp2 from t2; + update t1, t2 set t1.salary= 2500, t2.salary= 2500 where t1.id = t2.id and t1.name = "Jerry"; + select @tmp1 = sys_trx_start as B1, salary from t1; + select @tmp2 = sys_trx_start as B2, salary from t2; + + drop table t1; + drop table t2; +end~~ +delimiter ;~~ + +call test_01('timestamp(6)', 'myisam', 'sys_end'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_02('timestamp(6)', 'myisam', 'sys_end'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_03('timestamp(6)', 'myisam', 'sys_end'); +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_04('timestamp(6)', 'myisam', 'sys_end'); +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_05('timestamp(6)', 'myisam', 'sys_end'); +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_06('timestamp(6)', 'myisam', 'sys_end'); +call test_06('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call test_07('timestamp(6)', 'myisam', 'sys_end'); +call test_07('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); + +call verify_vtq; + +drop procedure test_01; +drop procedure test_02; +drop procedure test_03; +drop procedure test_04; +drop procedure test_05; +drop procedure test_06; +drop procedure test_07; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/view.opt b/mysql-test/suite/versioning/t/view.opt new file mode 100644 index 00000000000..9baff80804d --- /dev/null +++ b/mysql-test/suite/versioning/t/view.opt @@ -0,0 +1,2 @@ +--versioning-hide=implicit +--plugin-load=versioning diff --git a/mysql-test/suite/versioning/t/view.test b/mysql-test/suite/versioning/t/view.test new file mode 100644 index 00000000000..bd95d0fdfd3 --- /dev/null +++ b/mysql-test/suite/versioning/t/view.test @@ -0,0 +1,97 @@ +-- source include/have_innodb.inc +-- source suite/versioning/common.inc + +create table t1 (x int) with system versioning engine innodb; +insert into t1 values (1); + +select now(6) into @t1; +update t1 set x= 2; + +select now(6) into @t2; +delete from t1; + +set @vt1= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'"); +prepare stmt from @vt1; execute stmt; drop prepare stmt; + +set @vt2= concat("create view vt2 as select *, sys_trx_end from t1 for system_time as of timestamp '", @t2, "'"); +prepare stmt from @vt2; execute stmt; drop prepare stmt; + +select * from vt1 for system_time all; +select * from vt2 for system_time all; +select * from t1; + +create or replace view vt1 as select * from t1; +show create view vt1; + +drop view vt1; +drop view vt2; + +create view vt1 as select * from t1 for system_time all; +select * from vt1 for system_time all; +prepare stmt from 'select * from vt1 for system_time all'; execute stmt; drop prepare stmt; + +select * from vt1; +prepare stmt from 'select * from vt1'; execute stmt; drop prepare stmt; + +select * from t1 for system_time as of timestamp @t1; +select * from vt1 for system_time as of timestamp @t1; +prepare stmt from 'select * from vt1 for system_time as of timestamp @t1'; execute stmt; drop prepare stmt; + +create or replace view vt1 as select * from t1; +select * from vt1 for system_time all; +prepare stmt from 'select * from vt1 for system_time all'; execute stmt; drop prepare stmt; + +insert into vt1 values (3); +select * from t1; +select * from vt1; +select * from t1 for system_time all; +select * from vt1 for system_time all; + +create or replace table t1 (x int) with system versioning; +insert into t1 values (1), (2); +set @t1=now(6); +delete from t1 where x=2; +set @t2=now(6); +delete from t1 where x=1; +set @t3=now(6); + +set @tmp= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'"); +prepare stmt from @tmp; execute stmt; drop prepare stmt; + +select * from vt1 for system_time all; + +create or replace table t1 (x int) with system versioning; +create or replace view vt1(c) as select x from t1; + +create or replace table t1 (a int) with system versioning engine innodb; +create or replace table t2 (b int) with system versioning engine innodb; +insert into t1 values (1); +insert into t2 values (2); +create or replace view vt12 as select * from t1 cross join t2; +select * from vt12; +create or replace view vt12 as select * from t1 for system_time as of timestamp '0-0-0' cross join t2; +select * from vt12; + +--error ER_VERS_VIEW_PROHIBITED +create or replace view vt1 as select a, t1.sys_trx_start, t2.sys_trx_end from t1, t2; +--error ER_VERS_VIEW_PROHIBITED +create or replace view vt1 as select a, t1.sys_trx_end, t2.sys_trx_end from t1, t2; + +create or replace table t3 (x int); +create or replace view vt1 as select * from t1, t2, t3; +show create view vt1; +create or replace view vt1 as select * from t3, t2, t1; +show create view vt1; +create or replace view vt1 as select a, t2.sys_trx_end as endo from t3, t1, t2; +show create view vt1; + +create or replace view vt1 as select * from t1 union select * from t1; +select * from vt1; + +--error ER_VERS_VIEW_PROHIBITED +create or replace view vvt1 as select * from t1, t2, vt1; + +drop view vt1, vt12; +drop table t1, t2, t3; + +-- source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/vtmd.opt b/mysql-test/suite/versioning/t/vtmd.opt new file mode 100644 index 00000000000..3596fc4d3bd --- /dev/null +++ b/mysql-test/suite/versioning/t/vtmd.opt @@ -0,0 +1 @@ +--innodb --default-storage-engine=innodb diff --git a/mysql-test/suite/versioning/t/vtmd.test b/mysql-test/suite/versioning/t/vtmd.test new file mode 100644 index 00000000000..c5483c182cc --- /dev/null +++ b/mysql-test/suite/versioning/t/vtmd.test @@ -0,0 +1,203 @@ +-- source include/have_innodb.inc +delimiter ~~; +create or replace procedure drop_archives (in vtmd_name varchar(64)) +begin + declare archive_name varchar(64); + declare cur_done bool default false; + declare cur cursor for + select cur_tmp.archive_name from cur_tmp; + declare continue handler for not found set cur_done = true; + + set @tmp= concat(' + create or replace temporary table + cur_tmp as + select vtmd.archive_name from ', vtmd_name, ' + for system_time all as vtmd + where vtmd.archive_name is not null + group by vtmd.archive_name'); + prepare stmt from @tmp; execute stmt; drop prepare stmt; + + open cur; + fetch_loop: loop + fetch cur into archive_name; + if cur_done then + leave fetch_loop; + end if; + set @tmp= concat('drop table ', archive_name); + prepare stmt from @tmp; execute stmt; drop prepare stmt; + end loop; + + drop table cur_tmp; +end~~ +delimiter ;~~ + +delimiter ~~; +create or replace procedure check_vtmd (in vtmd_name varchar(64)) +begin + set @tmp= concat(' + create or replace temporary table + tmp_vtmd with system versioning as + select * from ', vtmd_name, ' + for system_time all as vtmd'); + prepare stmt from @tmp; execute stmt; drop prepare stmt; + + set @inf= 0xFFFFFFFFFFFFFFFF + 0; + set @start= null; + select start from tmp_vtmd for system_time all order by start limit 1 into @start; + select @start > 0 and @start < @inf; + select + start >= @start as A_start, + (@start:= end) and end = @inf as B_end, + name, + substr(archive_name, 1, instr(archive_name, '_')) as C_archive_name + from tmp_vtmd for system_time all; + + drop table tmp_vtmd; +end~~ +delimiter ;~~ + +delimiter ~~; +create or replace procedure show_tables() +begin + show tables; + select table_name, table_schema from information_schema.tables + where table_schema not in ('mysql', 'performance_schema', 'information_schema', 'mtr'); +end~~ +delimiter ;~~ + +# create +set versioning_alter_history= keep; +create table t0 (z int) with system versioning; +show tables; +set versioning_alter_history= survive; +create or replace table t0 (y int) with system versioning; +show tables; +show create table t0_vtmd; +call check_vtmd('t0_vtmd'); + +set versioning_alter_history= keep; +drop table t0; +set versioning_alter_history= survive; +--error ER_VERS_VTMD_ERROR +create table t0 (x int) with system versioning; + +drop table t0_vtmd; +create table t0 (y int) with system versioning; +create or replace table t0 (x int) with system versioning; + +# alter +insert into t0 values (1); +set @t0= now(6); +alter table t0 add column (y int); +select * from t0 for system_time as of @t0; +select * from t0; +call check_vtmd('t0_vtmd'); + +call drop_archives('t0_vtmd'); +drop table t0_vtmd; +alter table t0 drop column y; +call check_vtmd('t0_vtmd'); + +call drop_archives('t0_vtmd'); +set versioning_alter_history= keep; +drop tables t0, t0_vtmd; +set versioning_alter_history= survive; + +# rename +set versioning_alter_history= keep; +create or replace table x0 (x int) with system versioning; +set versioning_alter_history= survive; +rename table x0 to d0; +show tables; + +set versioning_alter_history= keep; +drop table d0; +set versioning_alter_history= survive; +create or replace table x0 (x int) with system versioning; +rename table x0 to d0; +show tables; +call check_vtmd('d0_vtmd'); + +set versioning_alter_history= keep; +drop table d0; +set versioning_alter_history= survive; +create or replace table x0 (x int) with system versioning; + +--error ER_VERS_VTMD_ERROR +rename table x0 to d0; +show tables; + +drop table x0_vtmd; +rename table x0 to d0; +show tables; + +rename table d0 to duck; +rename table duck to bay; +rename table bay to sheer; +rename table sheer to t0; +call check_vtmd('t0_vtmd'); + +alter table t0 add column (y int); +call check_vtmd('t0_vtmd'); + +# rename to different schema +alter table t0 add column (z int); +alter table t0 drop column y; +alter table t0 drop column z; + +create database db0; +rename table t0 to db0.t0; +show tables; +use db0; +show tables; +call test.check_vtmd('db0.t0_vtmd'); + +create database db1; +rename table t0 to db1.other_name; +show tables; +use db1; +show tables; +call test.check_vtmd('db1.other_name_vtmd'); + +# alter rename +alter table other_name rename to t1; +call test.check_vtmd('db1.t1_vtmd'); + +# alter rename and modify to different schema +alter table t1 rename to test.t2, add column (y int); +use test; +show tables; +call check_vtmd('t2_vtmd'); + +create or replace table t3 (x int) with system versioning; +alter table t3 change x x bigint; +alter table t3 change x x bigint after sys_trx_start; +call check_vtmd('t3_vtmd'); + +# hide archive tables +set versioning_hide= auto; +call show_tables(); + +set versioning_hide= implicit; +call show_tables(); + +set versioning_hide= full; +call show_tables(); + +set versioning_hide= never; +--replace_regex /\d{8}_\d{6}_\d{6}/TIMESTAMP_SUFFIX/ +call show_tables(); + +# wrong VTMD handling +set versioning_hide= auto; +create or replace table u0_vtmd (x int) with system versioning; +show tables; + +set versioning_alter_history= survive; +create or replace table t (x int) with system versioning; +select * from t for system_time all; + +drop database db0; +drop database db1; +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/t/vtmd_show.opt b/mysql-test/suite/versioning/t/vtmd_show.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/suite/versioning/t/vtmd_show.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/suite/versioning/t/vtmd_show.test b/mysql-test/suite/versioning/t/vtmd_show.test new file mode 100644 index 00000000000..4397198c839 --- /dev/null +++ b/mysql-test/suite/versioning/t/vtmd_show.test @@ -0,0 +1,90 @@ +delimiter ~~; +create or replace procedure drop_archives (in vtmd_name varchar(64)) +begin + declare archive_name varchar(64); + declare cur_done bool default false; + declare cur cursor for + select cur_tmp.archive_name from cur_tmp; + declare continue handler for not found set cur_done = true; + + set @tmp= concat(' + create or replace temporary table + cur_tmp as + select vtmd.archive_name from ', vtmd_name, ' + for system_time all as vtmd + where vtmd.archive_name is not null + group by vtmd.archive_name'); + prepare stmt from @tmp; execute stmt; drop prepare stmt; + + open cur; + fetch_loop: loop + fetch cur into archive_name; + if cur_done then + leave fetch_loop; + end if; + set @tmp= concat('drop table ', archive_name); + prepare stmt from @tmp; execute stmt; drop prepare stmt; + end loop; + + drop table cur_tmp; +end~~ +delimiter ;~~ + +delimiter ~~; +create procedure test_01(in engine varchar(64)) +begin + set @tmp = concat('create table t (a int) with system versioning engine ', engine); + prepare stmt from @tmp; execute stmt; drop prepare stmt; + + set @tm1 = now(6); + alter table t add column b int; + + set @tm2 = now(6); + alter table t add column c int; + + show create table t for system_time as of timestamp @tm1; + show create table t for system_time as of timestamp @tm2; + show create table t for system_time as of now; + show create table t for system_time as of timestamp now(6); + show create table t; + + set @tm3 = now(6); + rename table t to tt; + show create table tt for system_time as of timestamp @tm3; + + set @tm4 = now(6); + alter table tt add column d int; + show create table tt for system_time as of timestamp @tm3; + show create table tt for system_time as of timestamp @tm4; + show create table tt; + + drop table tt; + call drop_archives('tt_vtmd'); + drop table tt_vtmd; +end~~ +delimiter ;~~ + +create table t (a int) with system versioning; +--error ER_VERS_VTMD_ERROR +show create table t for system_time as of now; + +set versioning_alter_history=survive; + +create or replace table t (a int) with system versioning; +--error ER_VERS_RANGE_PROHIBITED +show create table t for system_time between timestamp @tm1 and timestamp @tm1; +--error ER_VERS_RANGE_PROHIBITED +show create table t for system_time from timestamp @tm1 to timestamp @tm1; +--error ER_VERS_VTMD_ERROR +show create table t for system_time as of timestamp '01-01-1990'; +--error ER_VERS_VTMD_ERROR +show create table t for system_time as of timestamp '01-01-2020'; +drop table t; +call drop_archives('t_vtmd'); +drop table t_vtmd; + +call test_01('myisam'); +call test_01('innodb'); + +drop procedure test_01; +drop procedure drop_archives; diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 1613f8e7a4f..f186e2f4559 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -5,6 +5,7 @@ --source include/have_perfschema.inc --source include/have_profiling.inc --source include/platform.inc +--source include/have_xtradb.inc # # force lower-case-table-names=1 (linux/macosx have different defaults) diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 98eaa7a7774..3be42eb0595 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -104,9 +104,7 @@ create table MIN (a int); drop table MIN; --error ER_PARSE_ERROR -create table NOW(a int); create table NOW (a int); -drop table NOW; --error ER_PARSE_ERROR create table POSITION(a int); diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index e8d5f9fa445..d216b003c78 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -25,13 +25,13 @@ if (`select @join_cache_level_for_select_test is not null`) } CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, + Period_ smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL ); INSERT INTO t1 VALUES (9410,9412); -select period from t1; +select period_ from t1; select * from t1; select t1.* from t1; @@ -1361,7 +1361,7 @@ select fld1,fld3 from t2 where fld1 like "25050_"; select distinct companynr from t2; select distinct companynr from t2 order by companynr; select distinct companynr from t2 order by companynr desc; -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; +select distinct t2.fld3,period_ from t2,t1 where companynr=37 and fld3 like "O%"; select distinct fld3 from t2 where companynr = 34 order by fld3; select distinct fld3 from t2 limit 10; @@ -1374,26 +1374,26 @@ select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10; # make a big table. create table t3 ( - period int not null, + period_ int not null, name char(32) not null, companynr int not null, price double(11,0), price2 double(11,0), - key (period), + key (period_), key (name) ); --disable_query_log -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1001,"Iranizes",37,5987435,234724); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1002,"violinist",37,28357832,8723648); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1003,"extramarital",37,39654943,235872); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1004,"spates",78,726498,72987523); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1005,"cloakroom",78,98439034,823742); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1006,"gazer",101,834598,27348324); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1007,"hand",154,983543950,29837423); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1008,"tucked",311,234298,3275892); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1009,"gems",447,2374834,9872392); -INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1010,"clinker",512,786542,76234234); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1001,"Iranizes",37,5987435,234724); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1002,"violinist",37,28357832,8723648); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1003,"extramarital",37,39654943,235872); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1004,"spates",78,726498,72987523); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1005,"cloakroom",78,98439034,823742); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1006,"gazer",101,834598,27348324); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1007,"hand",154,983543950,29837423); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1008,"tucked",311,234298,3275892); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1009,"gems",447,2374834,9872392); +INSERT INTO t3 (period_,name,companynr,price,price2) VALUES (1010,"clinker",512,786542,76234234); --enable_query_log create temporary table tmp engine = myisam select * from t3; @@ -1462,39 +1462,39 @@ explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2 # Some test with ORDER BY and limit # -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t3.period_ limit 10; +explain select * from t3 as t1,t3 where t1.period_=t3.period_ order by t1.period_ limit 10; # # Search with a constant table. # -select period from t1; -select period from t1 where period=1900; -select fld3,period from t1,t2 where fld1 = 011401 order by period; +select period_ from t1; +select period_ from t1 where period_=1900; +select fld3,period_ from t1,t2 where fld1 = 011401 order by period_; # # Search with a constant table and several keyparts. (Rows are read only once # in the beginning of the search) # -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; +select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period_=1001; -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +explain select fld3,period_ from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period_; # # Search with a constant table and several rows from another table # -select fld3,period from t2,t1 where companynr*10 = 37*10; +select fld3,period_ from t2,t1 where companynr*10 = 37*10; # # Search with a table reference and without a key. # t3 will be the main table. # -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; +select fld3,period_,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period_ >= 1001 and period_ <= 1002 and t2.companynr = 37 order by fld3,period_, price; # # Search with an interval on a table with full key on reference table. @@ -1502,7 +1502,7 @@ select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1 # t2nr will be checked. # -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; +select t2.fld1,fld3,period_,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period_ = 1001 and t2.companynr = 37; # # We need another table for join stuff.. @@ -1594,18 +1594,18 @@ explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr= # each record # -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period_ = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period_ = 1008; -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +select t2.fld1,t2.companynr,fld3,period_ from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period_>=1008 and period_<=1009; # # Test of many parenthesis levels # -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); +select period_ from t1 where (((period_ > 0) or period_ < 10000 or (period_ = 1900)) and (period_=1900 and period_ <= 1901) or (period_=1903 and (period_=1903)) and period_>=1902) or ((period_=1904 or period_=1905) or (period_=1906 or period_>1907)) or (period_=1908 and period_ = 1909); +select period_ from t1 where ((period_ > 0 and period_ < 1) or (((period_ > 0 and period_ < 100) and (period_ > 10)) or (period_ > 10)) or (period_ > 0 and (period_ > 5 or period_ > 6))); select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; @@ -1663,7 +1663,7 @@ select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 grou # Calculation with group functions # -select sum(Period)/count(*) from t1; +select sum(Period_)/count(*) from t1; select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg; @@ -1753,13 +1753,13 @@ select max(t2nr) from t3 where price=983543950; # Test of alias # -select t1.period from t3 = t1 limit 1; -select t1.period from t1 as t1 limit 1; -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -select period as ok_period from t1 limit 1; -select period as ok_period from t1 group by ok_period limit 1; +select t1.period_ from t3 = t1 limit 1; +select t1.period_ from t1 as t1 limit 1; +select t1.period_ as "Nuvarande period_" from t1 as t1 limit 1; +select period_ as ok_period from t1 limit 1; +select period_ as ok_period from t1 group by ok_period limit 1; select 1+1 as summa from t1 group by summa limit 1; -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; +select period_ as "Nuvarande period_" from t1 group by "Nuvarande period_" limit 1; # # Some simple show commands diff --git a/mysql-test/t/system_mysql_db_fix40123.test b/mysql-test/t/system_mysql_db_fix40123.test index fd1212d4ce6..e21f52c7726 100644 --- a/mysql-test/t/system_mysql_db_fix40123.test +++ b/mysql-test/t/system_mysql_db_fix40123.test @@ -72,7 +72,7 @@ CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, vtmd_template, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; -- enable_query_log diff --git a/mysql-test/t/system_mysql_db_fix50030.test b/mysql-test/t/system_mysql_db_fix50030.test index c3e7dd7b9b1..9c7d4f9f10e 100644 --- a/mysql-test/t/system_mysql_db_fix50030.test +++ b/mysql-test/t/system_mysql_db_fix50030.test @@ -79,7 +79,7 @@ INSERT INTO servers VALUES ('test','localhost','test','root','', 0,'','mysql','r -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, vtmd_template, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; -- enable_query_log diff --git a/mysql-test/t/system_mysql_db_fix50117.test b/mysql-test/t/system_mysql_db_fix50117.test index dcc765ae132..561a2040160 100644 --- a/mysql-test/t/system_mysql_db_fix50117.test +++ b/mysql-test/t/system_mysql_db_fix50117.test @@ -96,7 +96,7 @@ CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_b -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, vtmd_template, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; -- enable_query_log diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 1ba20f0ac9e..1f65956f8ad 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -1295,166 +1295,6 @@ DROP TABLE t1; --echo End of 5.1 tests -########################################################################### - ---echo ---echo # ---echo # Bug#34828: OF is taken as OFF and a value of 0 is set for variable SQL_notes. ---echo # ---echo - ---echo # Checking sql_notes... -SET @sql_notes_saved = @@sql_notes; - ---echo -SET @@sql_notes = ON; -SELECT @@sql_notes; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET @@sql_notes = OF; -SELECT @@sql_notes; - ---echo -SET @@sql_notes = OFF; -SELECT @@sql_notes; - ---echo -SET @@sql_notes = @sql_notes_saved; - ---echo ---echo # Checking delay_key_write... -SET @delay_key_write_saved = @@delay_key_write; - ---echo -SET GLOBAL delay_key_write = ON; -SELECT @@delay_key_write; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET GLOBAL delay_key_write = OF; -SELECT @@delay_key_write; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET GLOBAL delay_key_write = AL; -SELECT @@delay_key_write; - ---echo -SET GLOBAL delay_key_write = OFF; -SELECT @@delay_key_write; - ---echo -SET GLOBAL delay_key_write = ALL; -SELECT @@delay_key_write; - ---echo -SET GLOBAL delay_key_write = @delay_key_write_saved; - ---echo ---echo # Checking sql_safe_updates... -SET @sql_safe_updates_saved = @@sql_safe_updates; - ---echo -SET @@sql_safe_updates = ON; -SELECT @@sql_safe_updates; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET @@sql_safe_updates = OF; -SELECT @@sql_safe_updates; - ---echo -SET @@sql_safe_updates = OFF; -SELECT @@sql_safe_updates; - ---echo -SET @@sql_safe_updates = @sql_safe_updates_saved; - ---echo ---echo # Checking foreign_key_checks... -SET @foreign_key_checks_saved = @@foreign_key_checks; - ---echo -SET @@foreign_key_checks = ON; -SELECT @@foreign_key_checks; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET @@foreign_key_checks = OF; -SELECT @@foreign_key_checks; - ---echo -SET @@foreign_key_checks = OFF; -SELECT @@foreign_key_checks; - ---echo -SET @@foreign_key_checks = @foreign_key_checks_saved; - ---echo ---echo # Checking unique_checks... -SET @unique_checks_saved = @@unique_checks; - ---echo -SET @@unique_checks = ON; -SELECT @@unique_checks; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET @@unique_checks = OF; -SELECT @@unique_checks; - ---echo -SET @@unique_checks = OFF; -SELECT @@unique_checks; - ---echo -SET @@unique_checks = @unique_checks_saved; - ---echo ---echo # Checking sql_buffer_result... -SET @sql_buffer_result_saved = @@sql_buffer_result; - ---echo -SET @@sql_buffer_result = ON; -SELECT @@sql_buffer_result; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET @@sql_buffer_result = OF; -SELECT @@sql_buffer_result; - ---echo -SET @@sql_buffer_result = OFF; -SELECT @@sql_buffer_result; - ---echo -SET @@sql_buffer_result = @sql_buffer_result_saved; - ---echo ---echo # Checking sql_quote_show_create... -SET @sql_quote_show_create_saved = @@sql_quote_show_create; - ---echo -SET @@sql_quote_show_create = ON; -SELECT @@sql_quote_show_create; - ---echo ---error ER_WRONG_VALUE_FOR_VAR -SET @@sql_quote_show_create = OF; -SELECT @@sql_quote_show_create; - ---echo -SET @@sql_quote_show_create = OFF; -SELECT @@sql_quote_show_create; - ---echo -SET @@sql_quote_show_create = @sql_quote_show_create_saved; - ---echo ---echo # End of Bug#34828. ---echo - --echo # Make sure we can manipulate with autocommit in the --echo # along with other variables. diff --git a/mysys/my_error.c b/mysys/my_error.c index f9614e07c6a..d57c186b2f3 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -327,3 +327,39 @@ void my_error_unregister_all(void) my_errmsgs_list= &my_errmsgs_globerrs; } + + +/** + Format one error and print out as another error code. + + @note + Stacks two error messages and prints as single error message. + Like my_error(), but error argument is another formatted error + + @param nr1 error number of printed message. nr1 must have exactly one %s + parameter which will be formatted message of error nr2. + @param nr2 error number of formatted message + @param MyFlags Flags + @param ... parameters for error nr2 +*/ + +void my_error_as(uint nr1, uint nr2, myf MyFlags, ...) +{ + const char *format; + va_list args; + char ebuff[ERRMSGSIZE]; + DBUG_ENTER("my_suberror"); + DBUG_PRINT("my", ("nr1: %d nr2: %d MyFlags: %lu errno: %d", nr1, nr2, MyFlags, errno)); + + if (!(format = my_get_err_msg(nr2))) + (void) my_snprintf(ebuff, sizeof(ebuff), "Unknown error %d", nr2); + else + { + va_start(args,MyFlags); + (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, + sizeof(ebuff), format, args); + va_end(args); + } + my_error(nr1, MyFlags, ebuff); + DBUG_VOID_RETURN; +} diff --git a/plugin/versioning/CMakeLists.txt b/plugin/versioning/CMakeLists.txt new file mode 100644 index 00000000000..a4dbc4dc835 --- /dev/null +++ b/plugin/versioning/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2016, 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-1301 USA + +MYSQL_ADD_PLUGIN(versioning versioning.cc RECOMPILE_FOR_EMBEDDED + MODULE_ONLY MODULE_OUTPUT_NAME "versioning" COMPONENT Test) diff --git a/plugin/versioning/versioning.cc b/plugin/versioning/versioning.cc new file mode 100644 index 00000000000..05ef5def5b8 --- /dev/null +++ b/plugin/versioning/versioning.cc @@ -0,0 +1,226 @@ +/* Copyright (c) 2016, 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-1301 USA */ + +#define MYSQL_SERVER 1 +#include <my_global.h> +#include <mysql_version.h> +#include <mysqld.h> +#include <mysql/plugin.h> +#include "sql_plugin.h" // st_plugin_int +#include "sql_class.h" +#include "item.h" +#include "vtq.h" +#include "vers_utils.h" + +plugin_ref innodb_plugin= NULL; +static handlerton* innodb_hton= NULL; + +/* System Versioning: VTQ_TRX_ID(), VTQ_COMMIT_ID(), VTQ_BEGIN_TS(), VTQ_COMMIT_TS(), VTQ_ISO_LEVEL() */ +template <vtq_field_t VTQ_FIELD> +class Create_func_vtq : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list); + + static Create_func_vtq<VTQ_FIELD> s_singleton; + +protected: + Create_func_vtq<VTQ_FIELD>() {} + virtual ~Create_func_vtq<VTQ_FIELD>() {} +}; + +template<vtq_field_t VTQ_FIELD> +Create_func_vtq<VTQ_FIELD> Create_func_vtq<VTQ_FIELD>::s_singleton; + +template <vtq_field_t VTQ_FIELD> +Item* +Create_func_vtq<VTQ_FIELD>::create_native(THD *thd, LEX_CSTRING *name, + List<Item> *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + switch (VTQ_FIELD) + { + case VTQ_BEGIN_TS: + case VTQ_COMMIT_TS: + func= new (thd->mem_root) Item_func_vtq_ts(thd, innodb_hton, param_1, VTQ_FIELD); + break; + case VTQ_TRX_ID: + case VTQ_COMMIT_ID: + case VTQ_ISO_LEVEL: + func= new (thd->mem_root) Item_func_vtq_id(thd, innodb_hton, param_1, VTQ_FIELD); + break; + default: + DBUG_ASSERT(0); + } + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + switch (VTQ_FIELD) + { + case VTQ_TRX_ID: + case VTQ_COMMIT_ID: + func= new (thd->mem_root) Item_func_vtq_id(thd, innodb_hton, param_1, param_2, VTQ_FIELD); + break; + default: + goto error; + } + break; + } + error: + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + break; + } + } + + return func; +}; + +template <class Item_func_vtq_trx_seesX> +class Create_func_vtq_trx_sees : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list) + { + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_vtq_trx_seesX(thd, innodb_hton, param_1, param_2); + break; + } + default: + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + break; + } + + return func; + } + + static Create_func_vtq_trx_sees<Item_func_vtq_trx_seesX> s_singleton; + +protected: + Create_func_vtq_trx_sees<Item_func_vtq_trx_seesX>() {} + virtual ~Create_func_vtq_trx_sees<Item_func_vtq_trx_seesX>() {} +}; + +template<class X> +Create_func_vtq_trx_sees<X> Create_func_vtq_trx_sees<X>::s_singleton; + +#define BUILDER(F) & F::s_singleton + +static Native_func_registry func_array[] = +{ + { { C_STRING_WITH_LEN("VTQ_BEGIN_TS") }, BUILDER(Create_func_vtq<VTQ_BEGIN_TS>)}, + { { C_STRING_WITH_LEN("VTQ_COMMIT_ID") }, BUILDER(Create_func_vtq<VTQ_COMMIT_ID>)}, + { { C_STRING_WITH_LEN("VTQ_COMMIT_TS") }, BUILDER(Create_func_vtq<VTQ_COMMIT_TS>)}, + { { C_STRING_WITH_LEN("VTQ_ISO_LEVEL") }, BUILDER(Create_func_vtq<VTQ_ISO_LEVEL>)}, + { { C_STRING_WITH_LEN("VTQ_TRX_ID") }, BUILDER(Create_func_vtq<VTQ_TRX_ID>)}, + { { C_STRING_WITH_LEN("VTQ_TRX_SEES") }, BUILDER(Create_func_vtq_trx_sees<Item_func_vtq_trx_sees>)}, + { { C_STRING_WITH_LEN("VTQ_TRX_SEES_EQ") }, BUILDER(Create_func_vtq_trx_sees<Item_func_vtq_trx_sees_eq>)}, + { {0, 0}, NULL} +}; + + +/* + Disable __attribute__() on non-gcc compilers. +*/ +#if !defined(__attribute__) && !defined(__GNUC__) +#define __attribute__(A) +#endif + +static int versioning_plugin_init(void *p __attribute__ ((unused))) +{ + static LString InnoDB= "InnoDB"; + + DBUG_ENTER("versioning_plugin_init"); + // No need in locking since we so far single-threaded + int res= item_create_append(func_array); + if (res) + { + my_message(ER_PLUGIN_IS_NOT_LOADED, "Can't append function array" , MYF(0)); + DBUG_RETURN(res); + } + + innodb_plugin= ha_resolve_by_name(NULL, &InnoDB.lex_cstring(), false); + if (!innodb_plugin) + { + my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), InnoDB.ptr()); + DBUG_RETURN(1); + } + + innodb_hton= plugin_hton(innodb_plugin); + if (!innodb_hton || (innodb_hton->flags & HTON_NOT_USER_SELECTABLE)) + { + my_message(ER_PLUGIN_IS_NOT_LOADED, "Can't get handlerton" , MYF(0)); + DBUG_RETURN(1); + } + + DBUG_RETURN(0); +} + +static int versioning_plugin_deinit(void *p __attribute__ ((unused))) +{ + DBUG_ENTER("versioning_plugin_deinit"); + if (innodb_plugin) + plugin_unlock(NULL, innodb_plugin); + DBUG_RETURN(0); +} + +struct st_mysql_daemon versioning_plugin= +{ MYSQL_REPLICATION_INTERFACE_VERSION }; + +/* + Plugin library descriptor +*/ + +maria_declare_plugin(versioning) +{ + MYSQL_REPLICATION_PLUGIN, // initialized after MYSQL_STORAGE_ENGINE_PLUGIN + &versioning_plugin, + "versioning", + "MariaDB Corp", + "System Vesioning testing features", + PLUGIN_LICENSE_GPL, + versioning_plugin_init, /* Plugin Init */ + versioning_plugin_deinit, /* Plugin Deinit */ + 0x0100 /* 1.0 */, + NULL, /* status variables */ + NULL, /* system variables */ + "1.0", /* string version */ + MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */ +} +maria_declare_plugin_end; diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 3b0255abdae..3fa85867709 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -23,17 +23,19 @@ set sql_mode=''; set @orig_storage_engine=@@storage_engine; set storage_engine=myisam; +set versioning_alter_history=keep; + set @have_innodb= (select count(engine) from information_schema.engines where engine='INNODB' and support != 'NO'); SET @innodb_or_myisam=IF(@have_innodb <> 0, 'InnoDB', 'MyISAM'); -CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_versioning_rows_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; -- Remember for later if db table already existed set @had_db_table= @@warning_count != 0; CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; -CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, authentication_string TEXT NOT NULL, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, default_role char(80) binary DEFAULT '' NOT NULL, max_statement_time decimal(12,6) DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_versioning_rows_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, authentication_string TEXT NOT NULL, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, default_role char(80) binary DEFAULT '' NOT NULL, max_statement_time decimal(12,6) DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; -- Remember for later if user table already existed set @had_user_table= @@warning_count != 0; @@ -49,7 +51,7 @@ CREATE TABLE IF NOT EXISTS plugin ( name varchar(64) DEFAULT '' NOT NULL, dl var CREATE TABLE IF NOT EXISTS servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) NOT NULL DEFAULT '', Db char(64) NOT NULL DEFAULT '', Username char(80) NOT NULL DEFAULT '', Password char(64) NOT NULL DEFAULT '', Port INT(4) NOT NULL DEFAULT '0', Socket char(64) NOT NULL DEFAULT '', Wrapper char(64) NOT NULL DEFAULT '', Owner char(64) NOT NULL DEFAULT '', PRIMARY KEY (Server_name)) CHARACTER SET utf8 comment='MySQL Foreign Servers table'; -CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; @@ -129,6 +131,17 @@ SET @create_innodb_index_stats="CREATE TABLE IF NOT EXISTS innodb_index_stats ( PRIMARY KEY (database_name, table_name, index_name, stat_name) ) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0"; +SET @create_vtmd_template="CREATE OR REPLACE TABLE vtmd_template ( + start BIGINT UNSIGNED GENERATED ALWAYS AS ROW START COMMENT 'TRX_ID of table lifetime start', + end BIGINT UNSIGNED GENERATED ALWAYS AS ROW END COMMENT 'TRX_ID of table lifetime end', + name VARCHAR(64) NOT NULL COMMENT 'Table name during period [start, end)', + archive_name VARCHAR(64) NULL COMMENT 'Name of archive table', + col_renames BLOB COMMENT 'Column name mappings from previous lifetime', + PERIOD FOR SYSTEM_TIME(start, end), + PRIMARY KEY (end), + INDEX (archive_name) +) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 WITH SYSTEM VERSIONING"; + SET @str=IF(@have_innodb <> 0, @create_innodb_table_stats, "SET @dummy = 0"); PREPARE stmt FROM @str; EXECUTE stmt; @@ -139,6 +152,11 @@ PREPARE stmt FROM @str; EXECUTE stmt; DROP PREPARE stmt; +SET @str=IF(@have_innodb <> 0, @create_vtmd_template, "SET @dummy = 0"); +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + SET @cmd="CREATE TABLE IF NOT EXISTS slave_relay_log_info ( Number_of_lines INTEGER UNSIGNED NOT NULL COMMENT 'Number of lines in the file or rows in the table. Used to version table definitions.', Relay_log_name TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the current relay log file.', diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index 9556e7ba160..4821b18bcbf 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -30,8 +30,8 @@ SELECT LOWER( REPLACE((SELECT REPLACE(@@hostname,'_','\_')),'%','\%') )INTO @cur -- Fill "db" table with default grants for anyone to -- access database 'test' and 'test_%' if "db" table didn't exist CREATE TEMPORARY TABLE tmp_db LIKE db; -INSERT INTO tmp_db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'); -INSERT INTO tmp_db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'); +INSERT INTO tmp_db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y','Y'); +INSERT INTO tmp_db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y','Y'); INSERT INTO db SELECT * FROM tmp_db WHERE @had_db_table=0; DROP TABLE tmp_db; @@ -42,12 +42,12 @@ CREATE TEMPORARY TABLE tmp_user_nopasswd LIKE user; CREATE TEMPORARY TABLE tmp_user_socket LIKE user; CREATE TEMPORARY TABLE tmp_user_anonymous LIKE user; -- Classic passwordless root account. -INSERT INTO tmp_user_nopasswd VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N', 'N','', 0); -REPLACE INTO tmp_user_nopasswd SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0 FROM dual WHERE @current_hostname != 'localhost'; -REPLACE INTO tmp_user_nopasswd VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0); -REPLACE INTO tmp_user_nopasswd VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', '', 0); +INSERT INTO tmp_user_nopasswd VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N', 'N','', 0); +REPLACE INTO tmp_user_nopasswd SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0 FROM dual WHERE @current_hostname != 'localhost'; +REPLACE INTO tmp_user_nopasswd VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0); +REPLACE INTO tmp_user_nopasswd VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', '', 0); -- More secure root account using unix sucket auth. -INSERT INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),'','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'unix_socket','','N', 'N','', 0); +INSERT INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),'','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'unix_socket','','N', 'N','', 0); -- Anonymous user with no privileges. INSERT INTO tmp_user_anonymous (host,user) VALUES ('localhost',''); INSERT INTO tmp_user_anonymous (host,user) SELECT @current_hostname,'' FROM dual WHERE @current_hostname != 'localhost'; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 10e2dcf21fb..e0cf16be6ce 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -74,7 +74,7 @@ ALTER TABLE tables_priv COLLATE utf8_general_ci DEFAULT '' NOT NULL, MODIFY Table_priv set('Select','Insert','Update','Delete','Create', 'Drop','Grant','References','Index','Alter', - 'Create View','Show view','Trigger') + 'Create View','Show view','Trigger','Delete versioning rows') COLLATE utf8_general_ci DEFAULT '' NOT NULL, COMMENT='Table privileges'; @@ -740,3 +740,9 @@ ALTER TABLE help_topic MODIFY url TEXT NOT NULL; # MDEV-7383 - varbinary on mix/max of column_stats alter table column_stats modify min_value varbinary(255) DEFAULT NULL, modify max_value varbinary(255) DEFAULT NULL; + +# System versioning +ALTER TABLE user add Delete_versioning_rows_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL DEFAULT 'N' after Trigger_priv; +ALTER TABLE user modify Delete_versioning_rows_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL DEFAULT 'N'; +ALTER TABLE db add Delete_versioning_rows_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL DEFAULT 'N' after Trigger_priv; +ALTER TABLE db modify Delete_versioning_rows_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL DEFAULT 'N'; diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 8a03692598d..270c0d82993 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -141,6 +141,7 @@ SET (SQL_SOURCE sql_type.cc item_windowfunc.cc sql_window.cc sql_cte.cc + item_vers.cc sql_sequence.cc sql_sequence.h ha_sequence.h ${WSREP_SOURCES} table_cache.cc encryption.cc temporary_tables.cc @@ -148,6 +149,7 @@ SET (SQL_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} + vtmd.cc ) IF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR diff --git a/sql/field.cc b/sql/field.cc index 51562dd4198..6f7958f02b8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1987,6 +1987,41 @@ bool Field_num::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) } +bool Field_vers_trx_id::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id) +{ + ASSERT_COLUMN_MARKED_FOR_READ; + DBUG_ASSERT(ltime); + if (!table || !table->s) + return true; + DBUG_ASSERT(table->versioned_by_engine() || + (table->versioned() && table->s->table_category == TABLE_CATEGORY_TEMPORARY)); + if (!trx_id) + return true; + if (trx_id == ULONGLONG_MAX) + { + get_thd()->variables.time_zone->gmt_sec_to_TIME(ltime, TIMESTAMP_MAX_VALUE); + ltime->second_part= TIME_MAX_SECOND_PART; + return false; + } + if (cached == trx_id) + { + *ltime= cache; + return false; + } + handlerton *hton= table->file->partition_ht(); + DBUG_ASSERT(hton); + DBUG_ASSERT(hton->vers_query_trx_id); + bool found= hton->vers_query_trx_id(get_thd(), &cache, trx_id, VTQ_COMMIT_TS); + if (found) + { + *ltime= cache; + cached= trx_id; + return false; + } + return true; +} + + Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, @@ -4295,6 +4330,26 @@ void Field_longlong::sql_type(String &res) const add_zerofill_and_unsigned(res); } +void Field_longlong::set_max() +{ + ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; + set_notnull(); + int8store(ptr, unsigned_flag ? ULONGLONG_MAX : LONGLONG_MAX); +} + +bool Field_longlong::is_max() +{ + ASSERT_COLUMN_MARKED_FOR_READ; + if (unsigned_flag) + { + ulonglong j; + j= uint8korr(ptr); + return j == ULONGLONG_MAX; + } + longlong j; + j= sint8korr(ptr); + return j == LONGLONG_MAX; +} /* Floating-point numbers @@ -5307,13 +5362,41 @@ void Field_timestampf::store_TIME(my_time_t timestamp, ulong sec_part) my_timestamp_to_binary(&tm, ptr, dec); } +void Field_timestampf::set_max() +{ + DBUG_ENTER("Field_timestampf::set_max"); + ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; + DBUG_ASSERT(dec == TIME_SECOND_PART_DIGITS); + + set_notnull(); + mi_int4store(ptr, TIMESTAMP_MAX_VALUE); + mi_int3store(ptr + 4, TIME_MAX_SECOND_PART); + + DBUG_VOID_RETURN; +} + +bool Field_timestampf::is_max() +{ + DBUG_ENTER("Field_timestampf::is_max"); + ASSERT_COLUMN_MARKED_FOR_READ; + + DBUG_RETURN(mi_sint4korr(ptr) == TIMESTAMP_MAX_VALUE && + mi_sint3korr(ptr + 4) == TIME_MAX_SECOND_PART); +} my_time_t Field_timestampf::get_timestamp(const uchar *pos, ulong *sec_part) const { struct timeval tm; - my_timestamp_from_binary(&tm, pos, dec); - *sec_part= tm.tv_usec; + if (sec_part) + { + my_timestamp_from_binary(&tm, pos ? pos : ptr, dec); + *sec_part= tm.tv_usec; + } + else + { + my_timestamp_from_binary(&tm, pos ? pos : ptr, 0); + } return tm.tv_sec; } @@ -10307,7 +10390,8 @@ Field *make_field(TABLE_SHARE *share, Field::geometry_type geom_type, uint srid, Field::utype unireg_check, TYPELIB *interval, - const LEX_CSTRING *field_name) + const LEX_CSTRING *field_name, + uint32 flags) { uchar *UNINIT_VAR(bit_ptr); uchar UNINIT_VAR(bit_offset); @@ -10492,11 +10576,22 @@ Field *make_field(TABLE_SHARE *share, f_is_zerofill(pack_flag) != 0, f_is_dec(pack_flag) == 0); case MYSQL_TYPE_LONGLONG: - return new (mem_root) - Field_longlong(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); + if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG)) + { + return new (mem_root) + Field_vers_trx_id(ptr, field_length, null_pos, null_bit, + unireg_check, field_name, + f_is_zerofill(pack_flag) != 0, + f_is_dec(pack_flag) == 0); + } + else + { + return new (mem_root) + Field_longlong(ptr,field_length,null_pos,null_bit, + unireg_check, field_name, + f_is_zerofill(pack_flag) != 0, + f_is_dec(pack_flag) == 0); + } case MYSQL_TYPE_TIMESTAMP: { uint dec= field_length > MAX_DATETIME_WIDTH ? @@ -10573,6 +10668,11 @@ Field *make_field(TABLE_SHARE *share, return 0; } +bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) const +{ + return item->type() == Item::DATE_ITEM; +} + /** Create a field suitable for create of table. */ @@ -10594,6 +10694,8 @@ Column_definition::Column_definition(THD *thd, Field *old_field, option_list= old_field->option_list; pack_flag= 0; compression_method_ptr= 0; + versioning= VERSIONING_NOT_SET; + implicit_not_null= false; if (orig_field) { diff --git a/sql/field.h b/sql/field.h index eb6510bc9a4..b9b9e052ec6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -673,6 +673,14 @@ public: static void operator delete(void *ptr, MEM_ROOT *mem_root) { DBUG_ASSERT(0); } + /** + Used by System Versioning. + */ + virtual void set_max() + { DBUG_ASSERT(0); } + virtual bool is_max() + { DBUG_ASSERT(0); return false; } + uchar *ptr; // Position to field in record /** Byte where the @c NULL bit is stored inside a record. If this Field is a @@ -1000,6 +1008,9 @@ public: } bool set_explicit_default(Item *value); + virtual my_time_t get_timestamp(const uchar *pos= NULL, ulong *sec_part= NULL) const + { DBUG_ASSERT(0); return 0; } + /** Evaluates the @c UPDATE default function, if one exists, and stores the result in the record buffer. If no such function exists for the column, @@ -1439,6 +1450,16 @@ public: FIELD_FLAGS_COLUMN_FORMAT; } + bool vers_sys_field() const + { + return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG); + } + + virtual bool vers_trx_id() const + { + return false; + } + /* Validate a non-null field value stored in the given record according to the current thread settings, e.g. sql_mode. @@ -2146,6 +2167,57 @@ public: { return unpack_int64(to, from, from_end); } + + void set_max(); + bool is_max(); +}; + + +class Field_vers_trx_id :public Field_longlong { + MYSQL_TIME cache; + ulonglong cached; +public: + Field_vers_trx_id(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + uchar null_bit_arg, enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, bool zero_arg, + bool unsigned_arg) + : Field_longlong(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, zero_arg, + unsigned_arg), + cached(0) + {} + enum_field_types real_type() const { return MYSQL_TYPE_LONGLONG; } + enum_field_types type() const { return MYSQL_TYPE_LONGLONG;} + uint size_of() const { return sizeof(*this); } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { + return get_date(ltime, fuzzydate, (ulonglong) val_int()); + } + bool test_if_equality_guarantees_uniqueness(const Item *item) const; + bool can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) const + { + return true; + } + + bool can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) const + { + return true; + } + bool can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const + { + return true; + } + /* cmp_type() cannot be TIME_RESULT, because we want to compare this field against + integers. But in all other cases we treat it as TIME_RESULT! */ + bool vers_trx_id() const + { + return true; + } }; @@ -2561,8 +2633,10 @@ public: { return memcmp(a_ptr, b_ptr, pack_length()); } + void set_max(); + bool is_max(); void store_TIME(my_time_t timestamp, ulong sec_part); - my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; + my_time_t get_timestamp(const uchar *pos= NULL, ulong *sec_part= NULL) const; uint size_of() const { return sizeof(*this); } }; @@ -3982,7 +4056,8 @@ Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, CHARSET_INFO *cs, Field::geometry_type geom_type, uint srid, Field::utype unireg_check, - TYPELIB *interval, const LEX_CSTRING *field_name); + TYPELIB *interval, const LEX_CSTRING *field_name, + uint32 flags); /* Create field class for CREATE TABLE @@ -4036,6 +4111,12 @@ class Column_definition: public Sql_alloc, public: LEX_CSTRING field_name; LEX_CSTRING comment; // Comment for field + enum enum_column_versioning + { + VERSIONING_NOT_SET, + WITH_VERSIONING, + WITHOUT_VERSIONING + }; Item *on_update; // ON UPDATE NOW() /* At various stages in execution this can be length of field in bytes or @@ -4068,6 +4149,9 @@ public: *default_value, // Default value *check_constraint; // Check constraint + enum_column_versioning versioning; + bool implicit_not_null; + Column_definition() :Type_handler_hybrid_field_type(&type_handler_null), compression_method_ptr(0), @@ -4077,10 +4161,13 @@ public: interval(0), charset(&my_charset_bin), srid(0), geom_type(Field::GEOM_GEOMETRY), option_list(NULL), pack_flag(0), - vcol_info(0), default_value(0), check_constraint(0) + vcol_info(0), default_value(0), check_constraint(0), + versioning(VERSIONING_NOT_SET), + implicit_not_null(false) { interval_list.empty(); } + Column_definition(THD *thd, Field *field, Field *orig_field); void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs); void create_length_to_internal_length_null() @@ -4207,7 +4294,7 @@ public: (uint32)length, null_pos, null_bit, pack_flag, type_handler(), charset, geom_type, srid, unireg_check, interval, - field_name_arg); + field_name_arg, flags); } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *field_name_arg) const diff --git a/sql/gen_lex_token.cc b/sql/gen_lex_token.cc index ebd966d9301..e024ee3799e 100644 --- a/sql/gen_lex_token.cc +++ b/sql/gen_lex_token.cc @@ -130,6 +130,8 @@ void compute_tokens() set_token(WITH_CUBE_SYM, "WITH CUBE"); set_token(WITH_ROLLUP_SYM, "WITH ROLLUP"); + set_token(WITH_SYSTEM_SYM, "WITH SYSTEM"); + set_token(FOR_SYSTEM_TIME_SYM, "FOR SYSTEM_TIME"); set_token(NOT2_SYM, "!"); set_token(OR2_SYM, "|"); set_token(PARAM_MARKER, "?"); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 67132e5ee4f..a580f793e9a 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -160,9 +160,6 @@ static int partition_initialize(void *p) bool Partition_share::init(uint num_parts) { DBUG_ENTER("Partition_share::init"); - mysql_mutex_init(key_partition_auto_inc_mutex, - &auto_inc_mutex, - MY_MUTEX_INIT_FAST); auto_inc_initialized= false; partition_name_hash_initialized= false; next_auto_inc_val= 0; @@ -1265,12 +1262,12 @@ int ha_partition::handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt, (modelled after mi_check_print_msg) TODO: move this into the handler, or rewrite mysql_admin_table. */ -static bool print_admin_msg(THD* thd, uint len, +bool print_admin_msg(THD* thd, uint len, const char* msg_type, const char* db_name, String &table_name, const char* op_name, const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 7, 8); -static bool print_admin_msg(THD* thd, uint len, +bool print_admin_msg(THD* thd, uint len, const char* msg_type, const char* db_name, String &table_name, const char* op_name, const char *fmt, ...) @@ -3588,7 +3585,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_part_info->part_expr->get_monotonicity_info(); else if (m_part_info->list_of_part_fields) m_part_func_monotonicity_info= MONOTONIC_STRICT_INCREASING; - info(HA_STATUS_VARIABLE | HA_STATUS_CONST); + info(HA_STATUS_OPEN | HA_STATUS_VARIABLE | HA_STATUS_CONST); DBUG_RETURN(0); err_handler: @@ -4321,6 +4318,15 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data) if (error) goto exit; + if (m_part_info->part_type == VERSIONING_PARTITION) + { + uint sub_factor= m_part_info->num_subparts ? m_part_info->num_subparts : 1; + DBUG_ASSERT(m_tot_parts == m_part_info->num_parts * sub_factor); + uint lpart_id= new_part_id / sub_factor; + // lpart_id is VERSIONING partition because new_part_id != old_part_id + m_part_info->vers_update_stats(thd, lpart_id); + } + tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */ error= m_file[old_part_id]->ha_delete_row(old_data); reenable_binlog(thd); @@ -5754,6 +5760,22 @@ int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen) } +int ha_partition::index_read_last_map(uchar *buf, + const uchar *key, + key_part_map keypart_map) +{ + DBUG_ENTER("ha_partition::index_read_last_map"); + + m_ordered= true; // Safety measure + end_range= NULL; + m_index_scan_type= partition_index_read_last; + m_start_key.key= key; + m_start_key.keypart_map= keypart_map; + m_start_key.flag= HA_READ_PREFIX_LAST; + DBUG_RETURN(common_index_read(buf, true)); +} + + /* Read next record when performing index scan backwards @@ -6563,6 +6585,7 @@ int ha_partition::info(uint flag) { uint no_lock_flag= flag & HA_STATUS_NO_LOCK; uint extra_var_flag= flag & HA_STATUS_VARIABLE_EXTRA; + uint open_flag= flag & HA_STATUS_OPEN; DBUG_ENTER("ha_partition::info"); #ifndef DBUG_OFF @@ -6603,7 +6626,7 @@ int ha_partition::info(uint flag) do { file= *file_array; - file->info(HA_STATUS_AUTO | no_lock_flag); + file->info(HA_STATUS_AUTO | no_lock_flag | open_flag); set_if_bigger(auto_increment_value, file->stats.auto_increment_value); } while (*(++file_array)); @@ -6657,7 +6680,7 @@ int ha_partition::info(uint flag) i= bitmap_get_next_set(&m_part_info->read_partitions, i)) { file= m_file[i]; - file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag); + file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag | open_flag); stats.records+= file->stats.records; stats.deleted+= file->stats.deleted; stats.data_file_length+= file->stats.data_file_length; @@ -6738,7 +6761,7 @@ int ha_partition::info(uint flag) if (!(flag & HA_STATUS_VARIABLE) || !bitmap_is_set(&(m_part_info->read_partitions), (uint)(file_array - m_file))) - file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag); + file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag | open_flag); if (file->stats.records > max_records) { max_records= file->stats.records; @@ -6757,7 +6780,7 @@ int ha_partition::info(uint flag) this); file= m_file[handler_instance]; - file->info(HA_STATUS_CONST | no_lock_flag); + file->info(HA_STATUS_CONST | no_lock_flag | open_flag); stats.block_size= file->stats.block_size; stats.create_time= file->stats.create_time; ref_length= m_ref_length; @@ -6773,7 +6796,7 @@ int ha_partition::info(uint flag) Note: all engines does not support HA_STATUS_ERRKEY, so set errkey. */ file->errkey= errkey; - file->info(HA_STATUS_ERRKEY | no_lock_flag); + file->info(HA_STATUS_ERRKEY | no_lock_flag | open_flag); errkey= file->errkey; } if (flag & HA_STATUS_TIME) @@ -6790,7 +6813,7 @@ int ha_partition::info(uint flag) do { file= *file_array; - file->info(HA_STATUS_TIME | no_lock_flag); + file->info(HA_STATUS_TIME | no_lock_flag | open_flag); if (file->stats.update_time > stats.update_time) stats.update_time= file->stats.update_time; } while (*(++file_array)); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 0402908c640..981eb0aa74e 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -68,6 +68,8 @@ public: }; +extern PSI_mutex_key key_partition_auto_inc_mutex; + /** Partition specific Handler_share. */ @@ -85,24 +87,86 @@ public: HASH partition_name_hash; /** Storage for each partitions Handler_share */ Parts_share_refs partitions_share_refs; - Partition_share() {} + Partition_share() + : auto_inc_initialized(false), + next_auto_inc_val(0), + partition_name_hash_initialized(false), + partition_names(NULL) + { + mysql_mutex_init(key_partition_auto_inc_mutex, + &auto_inc_mutex, + MY_MUTEX_INIT_FAST); + } + ~Partition_share() { - DBUG_ENTER("Partition_share::~Partition_share"); mysql_mutex_destroy(&auto_inc_mutex); + if (partition_names) + { + my_free(partition_names); + } if (partition_name_hash_initialized) + { my_hash_free(&partition_name_hash); - DBUG_VOID_RETURN; + } } + bool init(uint num_parts); - void lock_auto_inc() + + /** + Release reserved auto increment values not used. + @param thd Thread. + @param table_share Table Share + @param next_insert_id Next insert id (first non used auto inc value). + @param max_reserved End of reserved auto inc range. + */ + void release_auto_inc_if_possible(THD *thd, TABLE_SHARE *table_share, + const ulonglong next_insert_id, + const ulonglong max_reserved); + + /** lock mutex protecting auto increment value next_auto_inc_val. */ + inline void lock_auto_inc() { mysql_mutex_lock(&auto_inc_mutex); } - void unlock_auto_inc() + /** unlock mutex protecting auto increment value next_auto_inc_val. */ + inline void unlock_auto_inc() { mysql_mutex_unlock(&auto_inc_mutex); } + /** + Populate partition_name_hash with partition and subpartition names + from part_info. + @param part_info Partition info containing all partitions metadata. + + @return Operation status. + @retval false Success. + @retval true Failure. + */ + bool populate_partition_name_hash(partition_info *part_info); + /** Get partition name. + + @param part_id Partition id (for subpartitioned table only subpartition + names will be returned.) + + @return partition name or NULL if error. + */ + const char *get_partition_name(size_t part_id) const; +private: + const uchar **partition_names; + /** + Insert [sub]partition name into partition_name_hash + @param name Partition name. + @param part_id Partition id. + @param is_subpart True if subpartition else partition. + + @return Operation status. + @retval false Success. + @retval true Failure. + */ + bool insert_partition_name_in_hash(const char *name, + uint part_id, + bool is_subpart); }; @@ -599,6 +663,10 @@ public: virtual int index_last(uchar * buf); virtual int index_next_same(uchar * buf, const uchar * key, uint keylen); + int index_read_last_map(uchar *buf, + const uchar *key, + key_part_map keypart_map); + /* read_first_row is virtual method but is only implemented by handler.cc, no storage engine has implemented it so neither @@ -1080,7 +1148,6 @@ private: ulonglong nr= (((Field_num*) field)->unsigned_flag || field->val_int() > 0) ? field->val_int() : 0; lock_auto_increment(); - DBUG_ASSERT(part_share->auto_inc_initialized); /* must check when the mutex is taken */ if (nr >= part_share->next_auto_inc_val) part_share->next_auto_inc_val= nr + 1; @@ -1271,7 +1338,37 @@ public: return h; } + virtual ha_rows part_records(void *_part_elem) + { + partition_element *part_elem= reinterpret_cast<partition_element *>(_part_elem); + DBUG_ASSERT(m_part_info); + uint32 sub_factor= m_part_info->num_subparts ? m_part_info->num_subparts : 1; + uint32 part_id= part_elem->id * sub_factor; + uint32 part_id_end= part_id + sub_factor; + DBUG_ASSERT(part_id_end <= m_tot_parts); + ha_rows part_recs= 0; + for (; part_id < part_id_end; ++part_id) + { + handler *file= m_file[part_id]; + DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), part_id)); + file->info(HA_STATUS_OPEN | HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); + part_recs+= file->stats.records; + } + return part_recs; + } + + virtual handler* part_handler(uint32 part_id) + { + DBUG_ASSERT(part_id < m_tot_parts); + return m_file[part_id]; + } + friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2); }; +bool print_admin_msg(THD* thd, uint len, + const char* msg_type, + const char* db_name, String &table_name, + const char* op_name, const char *fmt, ...); + #endif /* HA_PARTITION_INCLUDED */ diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 93f6f32d473..4afa2168b8d 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -259,7 +259,8 @@ int ha_sequence::write_row(uchar *buf) sequence->copy(&tmp_seq); rows_changed++; /* We have to do the logging while we hold the sequence mutex */ - error= binlog_log_row(table, 0, buf, log_func); + if (table->file->check_table_binlog_row_based(1)) + error= binlog_log_row(table, 0, buf, log_func); row_already_logged= 1; } diff --git a/sql/handler.cc b/sql/handler.cc index ca4f8634091..68e43119caa 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2435,6 +2435,12 @@ LEX_CSTRING *handler::engine_name() } +void handler::ha_statistic_increment(ulong SSV::*offset) const +{ + (table->in_use->status_var.*offset)++; +} + + double handler::keyread_time(uint index, uint ranges, ha_rows rows) { /* @@ -3023,6 +3029,36 @@ int handler::update_auto_increment() enum enum_check_fields save_count_cuted_fields; DBUG_ENTER("handler::update_auto_increment"); + // System Versioning: handle ALTER ADD COLUMN AUTO_INCREMENT + if (thd->lex->sql_command == SQLCOM_ALTER_TABLE && table->versioned_by_sql()) + { + Field *end= table->vers_end_field(); + DBUG_ASSERT(end); + bitmap_set_bit(table->read_set, end->field_index); + if (!end->is_max()) + { + uchar *ptr= table->next_number_field->ptr; + switch (table->next_number_field->pack_length()) + { + case 8: + int8store(ptr, vers_auto_decrement--); + break; + case 4: + int4store(ptr, vers_auto_decrement--); + break; + case 2: + int2store(ptr, vers_auto_decrement--); + break; + case 1: + *ptr= vers_auto_decrement--; + break; + default: + DBUG_ASSERT(false); + } + DBUG_RETURN(0); + } + } + /* next_insert_id is a "cursor" into the reserved interval, it may go greater than the interval, but not smaller. @@ -3145,7 +3181,7 @@ int handler::update_auto_increment() /* Store field without warning (Warning will be printed by insert) */ save_count_cuted_fields= thd->count_cuted_fields; thd->count_cuted_fields= CHECK_FIELD_IGNORE; - tmp= table->next_number_field->store((longlong) nr, TRUE); + tmp= table->next_number_field->store((longlong)nr, TRUE); thd->count_cuted_fields= save_count_cuted_fields; if (unlikely(tmp)) // Out of range value in store @@ -5681,8 +5717,10 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) 1 Row needs to be logged */ -inline bool handler::check_table_binlog_row_based(bool binlog_row) +bool handler::check_table_binlog_row_based(bool binlog_row) { + if (table->versioned_by_engine()) + return false; if (unlikely((table->in_use->variables.sql_log_bin_off))) return 0; /* Called by partitioning engine */ if (unlikely((!check_table_binlog_row_based_done))) @@ -5831,10 +5869,10 @@ static int write_locked_table_maps(THD *thd) static int check_wsrep_max_ws_rows(); -static int binlog_log_row_internal(TABLE* table, - const uchar *before_record, - const uchar *after_record, - Log_func *log_func) +int binlog_log_row(TABLE* table, + const uchar *before_record, + const uchar *after_record, + Log_func *log_func) { bool error= 0; THD *const thd= table->in_use; @@ -5869,16 +5907,6 @@ static int binlog_log_row_internal(TABLE* table, return error ? HA_ERR_RBR_LOGGING_FAILED : 0; } -int binlog_log_row(TABLE* table, - const uchar *before_record, - const uchar *after_record, - Log_func *log_func) -{ - if (!table->file->check_table_binlog_row_based(1)) - return 0; - return binlog_log_row_internal(table, before_record, after_record, log_func); -} - int handler::ha_external_lock(THD *thd, int lock_type) { @@ -6027,7 +6055,8 @@ int handler::ha_write_row(uchar *buf) if (likely(!error) && !row_already_logged) { rows_changed++; - error= binlog_log_row(table, 0, buf, log_func); + if (table->file->check_table_binlog_row_based(1)) + error= binlog_log_row(table, 0, buf, log_func); } DEBUG_SYNC_C("ha_write_row_end"); DBUG_RETURN(error); @@ -6059,7 +6088,8 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data) if (likely(!error) && !row_already_logged) { rows_changed++; - error= binlog_log_row(table, old_data, new_data, log_func); + if (table->file->check_table_binlog_row_based(1)) + error= binlog_log_row(table, old_data, new_data, log_func); } return error; } @@ -6114,7 +6144,8 @@ int handler::ha_delete_row(const uchar *buf) if (likely(!error)) { rows_changed++; - error= binlog_log_row(table, buf, 0, log_func); + if (table->file->check_table_binlog_row_based(1)) + error= binlog_log_row(table, buf, 0, log_func); } return error; } @@ -6594,3 +6625,498 @@ int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info) mysql_mutex_unlock(&LOCK_global_index_stats); DBUG_RETURN(res); } + +bool Vers_parse_info::is_trx_start(const char *name) const +{ + DBUG_ASSERT(name); + return as_row.start && as_row.start == LString_i(name); +} +bool Vers_parse_info::is_trx_end(const char *name) const +{ + DBUG_ASSERT(name); + return as_row.end && as_row.end == LString_i(name); +} +bool Vers_parse_info::is_trx_start(const Create_field &f) const +{ + return f.flags & VERS_SYS_START_FLAG; +} +bool Vers_parse_info::is_trx_end(const Create_field &f) const +{ + return f.flags & VERS_SYS_END_FLAG; +} + +static Create_field *vers_init_sys_field(THD *thd, const char *field_name, + int flags, bool integer_fields) +{ + Create_field *f= new (thd->mem_root) Create_field(); + if (!f) + return NULL; + + memset(f, 0, sizeof(*f)); + f->field_name.str= field_name; + f->field_name.length= strlen(field_name); + f->charset= system_charset_info; + f->flags= flags | HIDDEN_FLAG; + if (integer_fields) + { + f->set_handler(&type_handler_longlong); + f->flags|= UNSIGNED_FLAG; + f->length= MY_INT64_NUM_DECIMAL_DIGITS - 1; + } + else + { + f->set_handler(&type_handler_timestamp2); + f->length= MAX_DATETIME_PRECISION; + } + + if (f->check(thd)) + return NULL; + + return f; +} + +static bool vers_create_sys_field(THD *thd, const char *field_name, + Alter_info *alter_info, int flags, + bool integer_fields) +{ + Create_field *f= vers_init_sys_field(thd, field_name, flags, integer_fields); + if (!f) + return true; + + alter_info->flags|= Alter_info::ALTER_ADD_COLUMN; + alter_info->create_list.push_back(f); + + return false; +} + +static bool vers_change_sys_field(THD *thd, const char *field_name, + Alter_info *alter_info, int flags, + bool integer_fields, const char *change) +{ + Create_field *f= vers_init_sys_field(thd, field_name, flags, integer_fields); + if (!f) + return true; + + f->change.str= change; + f->change.length= strlen(change); + + alter_info->flags|= Alter_info::ALTER_CHANGE_COLUMN; + alter_info->create_list.push_back(f); + + return false; +} + +bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info, + bool integer_fields) +{ + // If user specified some of these he must specify the others too. Do nothing. + if (as_row.start || as_row.end || system_time.start || system_time.end) + return false; + + alter_info->flags|= Alter_info::ALTER_ADD_COLUMN; + + static const LString sys_trx_start= "sys_trx_start"; + static const LString sys_trx_end= "sys_trx_end"; + + system_time= start_end_t(sys_trx_start, sys_trx_end); + as_row= system_time; + + return vers_create_sys_field(thd, sys_trx_start, alter_info, + VERS_SYS_START_FLAG, + integer_fields) || + vers_create_sys_field(thd, sys_trx_end, alter_info, + VERS_SYS_END_FLAG, + integer_fields); +} + +bool Vers_parse_info::check_and_fix_implicit( + THD *thd, + Alter_info *alter_info, + HA_CREATE_INFO *create_info, + const char* table_name) +{ + SELECT_LEX &slex= thd->lex->select_lex; + int vers_tables= 0; + bool from_select= slex.item_list.elements ? true : false; + + if (from_select) + { + for (TABLE_LIST *table= slex.table_list.first; table; table= table->next_local) + { + if (table->table && table->table->versioned()) + vers_tables++; + } + } + + // CREATE ... SELECT: if at least one table in SELECT is versioned, + // then created table will be versioned. + if (thd->variables.vers_force) + { + with_system_versioning= true; + create_info->options|= HA_VERSIONED_TABLE; + } + + // Possibly override default storage engine to match one used in source table. + if (from_select && with_system_versioning && + !(create_info->used_fields & HA_CREATE_USED_ENGINE)) + { + List_iterator_fast<Create_field> it(alter_info->create_list); + while (Create_field *f= it++) + { + if (is_trx_start(*f) || is_trx_end(*f)) + { + create_info->db_type= f->field->orig_table->file->ht; + break; + } + } + } + + if (!need_check()) + return false; + + if (!versioned_fields && unversioned_fields && !with_system_versioning) + { + // All is correct but this table is not versioned. + create_info->options&= ~HA_VERSIONED_TABLE; + return false; + } + + if (without_system_versioning) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_NOT_ALLOWED, MYF(0), table_name, + "WITHOUT SYSTEM VERSIONING"); + return true; + } + + if ((system_time.start || system_time.end || as_row.start || as_row.end) && + !with_system_versioning) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_MISSING, MYF(0), table_name, + "WITH SYSTEM VERSIONING"); + return true; + } + + TABLE *orig_table= NULL; + List_iterator<Create_field> it(alter_info->create_list); + while (Create_field *f= it++) + { + if (is_trx_start(*f)) + { + if (!as_row.start) // not inited in CREATE ... SELECT + { + DBUG_ASSERT(vers_tables > 0); + if (orig_table && orig_table != f->field->orig_table) + { + err_different_tables: + my_error_as(ER_VERS_WRONG_PARAMS, ER_VERS_DIFFERENT_TABLES, MYF(0), table_name); + return true; + } + orig_table= f->field->orig_table; + as_row.start= f->field_name; + system_time.start= as_row.start; + } + continue; + } + if (is_trx_end(*f)) + { + if (!as_row.end) + { + DBUG_ASSERT(vers_tables > 0); + if (orig_table && orig_table != f->field->orig_table) + { + goto err_different_tables; + } + orig_table= f->field->orig_table; + as_row.end= f->field_name; + system_time.end= as_row.end; + } + continue; + } + + if ((f->versioning == Column_definition::VERSIONING_NOT_SET && + !with_system_versioning) || + f->versioning == Column_definition::WITHOUT_VERSIONING) + { + f->flags|= VERS_OPTIMIZED_UPDATE_FLAG; + } + } + + bool integer_fields= create_info->db_type->flags & HTON_NATIVE_SYS_VERSIONING; + + if (fix_implicit(thd, alter_info, integer_fields)) + return true; + + int plain_cols= 0; // column doesn't have WITH or WITHOUT SYSTEM VERSIONING + int vers_cols= 0; // column has WITH SYSTEM VERSIONING + it.rewind(); + while (const Create_field *f= it++) + { + if (is_trx_start(*f) || is_trx_end(*f)) + continue; + + if (f->versioning == Column_definition::VERSIONING_NOT_SET) + plain_cols++; + else if (f->versioning == Column_definition::WITH_VERSIONING) + vers_cols++; + } + + bool table_with_system_versioning= + as_row.start || as_row.end || system_time.start || system_time.end; + + if (!thd->lex->tmp_table() && + // CREATE from SELECT (Create_fields are not yet added) + !from_select && + vers_cols == 0 && + (plain_cols == 0 || !table_with_system_versioning)) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_VERS_NO_COLS_DEFINED, MYF(0), + table_name, "WITH SYSTEM VERSIONING"); + return true; + } + + return check_with_conditions(table_name) || + check_generated_type(table_name, alter_info, integer_fields); +} + +static bool add_field_to_drop_list(THD *thd, Alter_info *alter_info, + Field *field) +{ + DBUG_ASSERT(field); + DBUG_ASSERT(field->field_name.str); + alter_info->flags|= Alter_info::ALTER_DROP_COLUMN; + Alter_drop *ad= new (thd->mem_root) + Alter_drop(Alter_drop::COLUMN, field->field_name.str, false); + return !ad || alter_info->drop_list.push_back(ad, thd->mem_root); +} + +bool Vers_parse_info::check_and_fix_alter(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, + TABLE_SHARE *share) +{ + bool integer_fields= + create_info->db_type->flags & HTON_NATIVE_SYS_VERSIONING; + const char *table_name= share->table_name.str; + + if (!need_check() && !share->versioned) + return false; + + if (without_system_versioning) + { + if (!share->versioned) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_VERS_NOT_VERSIONED, MYF(0), table_name); + return true; + } + + if (!(share->vers_start_field()->flags & HIDDEN_FLAG)) + { + my_error(ER_VERS_SYS_FIELD_NOT_HIDDEN, MYF(0), + share->vers_start_field()->field_name); + return true; + } + if (!(share->vers_end_field()->flags & HIDDEN_FLAG)) + { + my_error(ER_VERS_SYS_FIELD_NOT_HIDDEN, MYF(0), + share->vers_end_field()->field_name); + return true; + } + + if (add_field_to_drop_list(thd, alter_info, share->vers_start_field()) || + add_field_to_drop_list(thd, alter_info, share->vers_end_field())) + return true; + + return false; + } + + if ((versioned_fields || unversioned_fields) && !share->versioned) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_VERS_NOT_VERSIONED, MYF(0), table_name); + return true; + } + + if (share->versioned) + { + // copy info from existing table + create_info->options|= HA_VERSIONED_TABLE; + + DBUG_ASSERT(share->vers_start_field() && share->vers_end_field()); + LString start(share->vers_start_field()->field_name); + LString end(share->vers_end_field()->field_name); + DBUG_ASSERT(start.ptr() && end.ptr()); + + as_row= start_end_t(start, end); + system_time= as_row; + + if (alter_info->create_list.elements) + { + List_iterator_fast<Create_field> it(alter_info->create_list); + while (Create_field *f= it++) + { + if (f->versioning == Column_definition::WITHOUT_VERSIONING) + f->flags|= VERS_OPTIMIZED_UPDATE_FLAG; + + if (f->change.str && (start == f->change || end == f->change)) + { + my_error(ER_VERS_ALTER_SYSTEM_FIELD, MYF(0), f->change); + return true; + } + } + } + + if (alter_info->drop_list.elements) + { + bool done_start= false; + bool done_end= false; + List_iterator<Alter_drop> it(alter_info->drop_list); + while (Alter_drop *d= it++) + { + const char *name= d->name; + Field *f= NULL; + if (!done_start && is_trx_start(name)) + { + f= share->vers_start_field(); + done_start= true; + } + else if (!done_end && is_trx_end(name)) + { + f= share->vers_end_field(); + done_end= true; + } + else + continue; + if (f->flags & HIDDEN_FLAG) + { + my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), d->type_name(), name); + return true; + } + + if (vers_change_sys_field(thd, name, alter_info, + f->flags & + (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG), + integer_fields, name)) + { + return true; + } + + it.remove(); + + if (done_start && done_end) + break; + } + } + + return false; + } + + return fix_implicit(thd, alter_info, integer_fields) || + (with_system_versioning && + (check_with_conditions(table_name) || + check_generated_type(table_name, alter_info, integer_fields))); +} + +bool Vers_parse_info::fix_create_like(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, TABLE_LIST *table) +{ + List_iterator<Create_field> it(alter_info->create_list); + Create_field *f, *f_start=NULL, *f_end= NULL; + + DBUG_ASSERT(alter_info->create_list.elements > 2); + while ((f= it++)) + { + if (f->flags & VERS_SYS_START_FLAG) + { + f_start= f; + if (f_end) + break; + } + else if (f->flags & VERS_SYS_END_FLAG) + { + f_end= f; + if (f_start) + break; + } + } + + if (!f_start || !f_end) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_MISSING, MYF(0), table->table_name, + f_start ? "AS ROW END" : "AS ROW START"); + return true; + } + + as_row= start_end_t(f_start->field_name, f_end->field_name); + system_time= as_row; + + create_info->options|= HA_VERSIONED_TABLE; + return false; +} + + +bool Vers_parse_info::check_with_conditions(const char *table_name) const +{ + if (!as_row.start || !as_row.end) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_MISSING, MYF(0), table_name, + as_row.start ? "AS ROW END" : "AS ROW START"); + return true; + } + + if (!system_time.start || !system_time.end) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_MISSING, MYF(0), table_name, + "PERIOD FOR SYSTEM_TIME"); + return true; + } + + if (as_row.start != system_time.start) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_MISMATCH, MYF(0), table_name, + "PERIOD FOR SYSTEM_TIME", "AS ROW START"); + return true; + } + + if (as_row.end != system_time.end) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_MISMATCH, MYF(0), table_name, + "PERIOD FOR SYSTEM_TIME", "AS ROW END"); + return true; + } + + return false; +} + +bool Vers_parse_info::check_generated_type(const char *table_name, + Alter_info *alter_info, + bool integer_fields) const +{ + List_iterator<Create_field> it(alter_info->create_list); + while (Create_field *f= it++) + { + if (is_trx_start(*f) || is_trx_end(*f)) + { + if (integer_fields) + { + if (f->type_handler() != &type_handler_longlong || !(f->flags & UNSIGNED_FLAG) || + f->length != (MY_INT64_NUM_DECIMAL_DIGITS - 1)) + { + my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, + "BIGINT(20) UNSIGNED", table_name); + return true; + } + } + else + { + if (!(f->type_handler() == &type_handler_datetime2 || + f->type_handler() == &type_handler_timestamp2) || + f->length != MAX_DATETIME_FULL_WIDTH) + { + my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, + "TIMESTAMP(6)", table_name); + return true; + } + } + } + } + + return false; +} diff --git a/sql/handler.h b/sql/handler.h index f681040db39..66fa336f675 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -34,6 +34,8 @@ #include "structs.h" /* SHOW_COMP_OPTION */ #include "sql_array.h" /* Dynamic_array<> */ #include "mdl.h" +#include "vtq.h" +#include "vers_string.h" #include "sql_analyze_stmt.h" // for Exec_time_tracker @@ -400,6 +402,8 @@ enum enum_alter_inplace_result { #define HA_LEX_CREATE_TMP_TABLE 1U #define HA_CREATE_TMP_ALTER 8U #define HA_LEX_CREATE_SEQUENCE 16U +#define HA_VERSIONED_TABLE 32U +#define HA_VTMD 64U #define HA_MAX_REC_LENGTH 65535 @@ -1382,6 +1386,40 @@ struct handlerton */ int (*discover_table_structure)(handlerton *hton, THD* thd, TABLE_SHARE *share, HA_CREATE_INFO *info); + + /* + System Versioning + */ + /** + Query VTQ by TRX_ID. + @param[in] thd MySQL thread + @param[out] out field value or whole record returned by query (selected by `field`) + @param[in] in_trx_id query parameter TRX_ID + @param[in] field field to get in `out` or VTQ_ALL for whole record (vtq_record_t) + @return TRUE if record is found, FALSE otherwise */ + bool (*vers_query_trx_id)(THD* thd, void *out, ulonglong trx_id, vtq_field_t field); + + /** Query VTQ by COMMIT_TS. + @param[in] thd MySQL thread + @param[out] out field value or whole record returned by query (selected by `field`) + @param[in] commit_ts query parameter COMMIT_TS + @param[in] field field to get in `out` or VTQ_ALL for whole record (vtq_record_t) + @param[in] backwards direction of VTQ search + @return TRUE if record is found, FALSE otherwise */ + bool (*vers_query_commit_ts)(THD* thd, void *out, const MYSQL_TIME &commit_ts, + vtq_field_t field, bool backwards); + + /** Check if transaction TX1 sees transaction TX0. + @param[in] thd MySQL thread + @param[out] result true if TX1 sees TX0 + @param[in] trx_id1 TX1 TRX_ID + @param[in] trx_id0 TX0 TRX_ID + @param[in] commit_id1 TX1 COMMIT_ID + @param[in] iso_level1 TX1 isolation level + @param[in] commit_id0 TX0 COMMIT_ID + @return FALSE if there is no trx_id1 in VTQ, otherwise TRUE */ + bool (*vers_trx_sees)(THD *thd, bool &result, ulonglong trx_id1, ulonglong trx_id0, + ulonglong commit_id1, uchar iso_level1, ulonglong commit_id0); }; @@ -1429,6 +1467,7 @@ handlerton *ha_default_tmp_handlerton(THD *thd); */ #define HTON_NO_BINLOG_ROW_OPT (1 << 9) #define HTON_SUPPORTS_EXTENDED_KEYS (1 <<10) //supports extended keys +#define HTON_NATIVE_SYS_VERSIONING (1 << 11) //Engine supports System Versioning // MySQL compatibility. Unused. #define HTON_SUPPORTS_FOREIGN_KEYS (1 << 0) //Foreign key constraint supported. @@ -1674,6 +1713,86 @@ struct Schema_specification_st } }; +class Create_field; + +struct Vers_parse_info +{ + Vers_parse_info() : + with_system_versioning(false), + without_system_versioning(false), + versioned_fields(false), + unversioned_fields(false) + {} + + struct start_end_t + { + start_end_t() + {} + start_end_t(LEX_CSTRING _start, LEX_CSTRING _end) : + start(_start), + end(_end) {} + LString_i start; + LString_i end; + }; + + start_end_t system_time; + start_end_t as_row; + + void set_period_for_system_time(LString start, LString end) + { + system_time.start= start; + system_time.end= end; + } + +private: + bool is_trx_start(const char *name) const; + bool is_trx_end(const char *name) const; + bool is_trx_start(const Create_field &f) const; + bool is_trx_end(const Create_field &f) const; + bool fix_implicit(THD *thd, Alter_info *alter_info, bool integer_fields); + bool need_check() const + { + return + versioned_fields || + unversioned_fields || + with_system_versioning || + without_system_versioning || + system_time.start || + system_time.end || + as_row.start || + as_row.end; + } + bool check_with_conditions(const char *table_name) const; + bool check_generated_type(const char *table_name, Alter_info *alter_info, + bool integer_fields) const; + +public: + bool check_and_fix_implicit(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, + const char *table_name); + bool check_and_fix_alter(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, TABLE_SHARE *share); + bool fix_create_like(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, TABLE_LIST *table); + + /** User has added 'WITH SYSTEM VERSIONING' to table definition */ + bool with_system_versioning : 1; + + /** Use has added 'WITHOUT SYSTEM VERSIONING' to ALTER TABLE */ + bool without_system_versioning : 1; + + /** + At least one field was specified 'WITH SYSTEM VERSIONING'. Useful for + error handling. + */ + bool versioned_fields : 1; + + /** + At least one field was specified 'WITHOUT SYSTEM VERSIONING'. Useful for + error handling. + */ + bool unversioned_fields : 1; +}; /** A helper struct for table DDL statements, e.g.: @@ -1749,6 +1868,8 @@ struct Table_scope_and_contents_source_st bool table_was_deleted; sequence_definition *seq_create_info; + Vers_parse_info vers_info; + void init() { bzero(this, sizeof(*this)); @@ -1759,6 +1880,16 @@ struct Table_scope_and_contents_source_st db_type= tmp_table() ? ha_default_tmp_handlerton(thd) : ha_default_handlerton(thd); } + + bool versioned() const + { + return options & HA_VERSIONED_TABLE; + } + + bool vtmd() const + { + return options & HA_VTMD; + } }; @@ -2025,6 +2156,8 @@ public: static const HA_ALTER_FLAGS ALTER_DROP_CHECK_CONSTRAINT= 1ULL << 40; + static const HA_ALTER_FLAGS ALTER_DROP_HISTORICAL = 1ULL << 41; + /** Create options (like MAX_ROWS) for the new version of table. @@ -2757,6 +2890,8 @@ public: */ uint auto_inc_intervals_count; + ulonglong vers_auto_decrement; + /** Instrumented table associated with this handler. This member should be set to NULL when no instrumentation is in place, @@ -3191,6 +3326,18 @@ protected: virtual int index_last(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_next_same(uchar *buf, const uchar *key, uint keylen); + /** + @brief + The following functions works like index_read, but it find the last + row with the current key value or prefix. + @returns @see index_read_map(). + */ + virtual int index_read_last_map(uchar * buf, const uchar * key, + key_part_map keypart_map) + { + uint key_len= calculate_key_len(table, active_index, key, keypart_map); + return index_read_last(buf, key, key_len); + } virtual int close(void)=0; inline void update_rows_read() { @@ -3270,7 +3417,7 @@ public: void ft_end() { ft_handler=NULL; } virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key) { return NULL; } -private: +public: virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(uchar *buf)=0; virtual int rnd_pos(uchar * buf, uchar *pos)=0; @@ -3977,6 +4124,7 @@ public: TABLE_SHARE* get_table_share() { return table_share; } protected: /* Service methods for use by storage engines. */ + void ha_statistic_increment(ulong SSV::*offset) const; void **ha_data(THD *) const; THD *ha_thd(void) const; @@ -4001,8 +4149,8 @@ protected: virtual int delete_table(const char *name); public: - inline bool check_table_binlog_row_based(bool binlog_row); -private: + bool check_table_binlog_row_based(bool binlog_row); + /* Cache result to avoid extra calls */ inline void mark_trx_read_write() { @@ -4012,6 +4160,8 @@ private: mark_trx_read_write_internal(); } } + +private: void mark_trx_read_write_internal(); bool check_table_binlog_row_based_internal(bool binlog_row); @@ -4130,6 +4280,11 @@ protected: virtual int index_read(uchar * buf, const uchar * key, uint key_len, enum ha_rkey_function find_flag) { return HA_ERR_WRONG_COMMAND; } + virtual int index_read_last(uchar * buf, const uchar * key, uint key_len) + { + my_errno= HA_ERR_WRONG_COMMAND; + return HA_ERR_WRONG_COMMAND; + } friend class ha_partition; friend class ha_sequence; public: @@ -4253,6 +4408,15 @@ public: */ virtual int find_unique_row(uchar *record, uint unique_ref) { return -1; /*unsupported */} + + bool native_versioned() const + { DBUG_ASSERT(ht); return partition_ht()->flags & HTON_NATIVE_SYS_VERSIONING; } + virtual ha_rows part_records(void *_part_elem) + { DBUG_ASSERT(0); return false; } + virtual handler* part_handler(uint32 part_id) + { DBUG_ASSERT(0); return NULL; } + virtual void update_partition(uint part_id) + {} protected: Handler_share *get_ha_share_ptr(); void set_ha_share_ptr(Handler_share *arg_ha_share); diff --git a/sql/item.cc b/sql/item.cc index 024fbd87d79..a0a06975ea7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5787,6 +5787,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) expression to 'reference', i.e. it substitute that expression instead of this Item_field */ + DBUG_ASSERT(context); if ((from_field= find_field_in_tables(thd, this, context->first_name_resolution_table, context->last_name_resolution_table, @@ -6641,7 +6642,7 @@ int Item_int::save_in_field(Field *field, bool no_conversions) Item *Item_int::clone_item(THD *thd) { - return new (thd->mem_root) Item_int(thd, name.str, value, max_length); + return new (thd->mem_root) Item_int(thd, name.str, value, max_length, unsigned_flag); } @@ -6971,6 +6972,26 @@ bool Item_temporal_literal::eq(const Item *item, bool binary_cmp) const &((Item_temporal_literal *) item)->cached_time); } +bool Item_temporal_literal::operator<(const MYSQL_TIME <ime) const +{ + if (my_time_compare(&cached_time, <ime) < 0) + return true; + return false; +} + +bool Item_temporal_literal::operator>(const MYSQL_TIME <ime) const +{ + if (my_time_compare(&cached_time, <ime) > 0) + return true; + return false; +} + +bool Item_temporal_literal::operator==(const MYSQL_TIME <ime) const +{ + if (my_time_compare(&cached_time, <ime) == 0) + return true; + return false; +} void Item_date_literal::print(String *str, enum_query_type query_type) { @@ -10329,6 +10350,35 @@ Item_field::excl_dep_on_grouping_fields(st_select_lex *sel) return find_matching_grouping_field(this, sel) != NULL; } +Item *Item_field::vers_optimized_fields_transformer(THD *thd, uchar *) +{ + if (!field) + return this; + + if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG && context && + field->table->pos_in_table_list && + field->table->pos_in_table_list->vers_conditions) + { + push_warning_printf( + current_thd, Sql_condition::WARN_LEVEL_WARN, + ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY, + ER_THD(current_thd, ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY), + field_name); + + Item *null_item= new (thd->mem_root) Item_null(thd); + if (null_item) + return null_item; + } + + return this; +} + +bool Item_field::vers_trx_id() const +{ + DBUG_ASSERT(field); + return field->vers_trx_id(); +} + void Item::register_in(THD *thd) { next= thd->free_list; diff --git a/sql/item.h b/sql/item.h index 1f743913d78..6184417136a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -541,7 +541,6 @@ public: String_copier_for_item(THD *thd): m_thd(thd) { } }; - class Item: public Value_source, public Type_all_attributes { @@ -775,6 +774,10 @@ public: return type_handler()->field_type(); } virtual const Type_handler *type_handler() const= 0; + virtual uint field_flags() const + { + return 0; + } const Type_handler *type_handler_for_comparison() const { return type_handler()->type_handler_for_comparison(); @@ -1743,6 +1746,10 @@ public: virtual Item_field *field_for_view_update() { return 0; } + virtual Item *vers_optimized_fields_transformer(THD *thd, uchar *) + { return this; } + virtual bool vers_trx_id() const + { return false; } virtual Item *neg_transformer(THD *thd) { return NULL; } virtual Item *update_value_transformer(THD *thd, uchar *select_arg) { return this; } @@ -1933,8 +1940,10 @@ public: { marker &= ~EXTRACTION_MASK; } -}; + /* System versioning */ + virtual vtq_record_t *vtq_cached_result() { return NULL; } +}; template <class T> inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item) @@ -2783,6 +2792,10 @@ public: return field->type_handler(); } TYPELIB *get_typelib() const { return field->get_typelib(); } + uint32 field_flags() const + { + return field->flags; + } enum_monotonicity_info get_monotonicity_info() const { return MONOTONIC_STRICT_INCREASING; @@ -2879,6 +2892,8 @@ public: uint32 max_display_length() const { return field->max_display_length(); } Item_field *field_for_view_update() { return this; } int fix_outer_field(THD *thd, Field **field, Item **reference); + virtual Item *vers_optimized_fields_transformer(THD *thd, uchar *); + virtual bool vers_trx_id() const; virtual Item *update_value_transformer(THD *thd, uchar *select_arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg); @@ -3320,6 +3335,14 @@ public: name.str= str_arg; name.length= safe_strlen(name.str); fixed= 1; } + Item_int(THD *thd, const char *str_arg,longlong i,uint length, bool flag): + Item_num(thd), value(i) + { + max_length=length; + name.str= str_arg; name.length= safe_strlen(name.str); + fixed= 1; + unsigned_flag= flag; + } Item_int(THD *thd, const char *str_arg, uint length=64); enum Type type() const { return INT_ITEM; } const Type_handler *type_handler() const @@ -3770,10 +3793,10 @@ class Item_return_date_time :public Item_partition_func_safe_string enum_field_types date_time_field_type; public: Item_return_date_time(THD *thd, const char *name_arg, uint length_arg, - enum_field_types field_type_arg): + enum_field_types field_type_arg, uint dec_arg= 0): Item_partition_func_safe_string(thd, name_arg, length_arg, &my_charset_bin), date_time_field_type(field_type_arg) - { decimals= 0; } + { decimals= dec_arg; } const Type_handler *type_handler() const { return Type_handler::get_handler_by_field_type(date_time_field_type); @@ -4014,6 +4037,13 @@ public: { return val_decimal_from_date(decimal_value); } int save_in_field(Field *field, bool no_conversions) { return save_date_in_field(field, no_conversions); } + void set_time(MYSQL_TIME *ltime) + { + cached_time= *ltime; + } + bool operator>(const MYSQL_TIME <ime) const; + bool operator<(const MYSQL_TIME <ime) const; + bool operator==(const MYSQL_TIME <ime) const; }; @@ -4073,7 +4103,7 @@ public: class Item_datetime_literal: public Item_temporal_literal { public: - Item_datetime_literal(THD *thd, MYSQL_TIME *ltime, uint dec_arg): + Item_datetime_literal(THD *thd, MYSQL_TIME *ltime, uint dec_arg= 0): Item_temporal_literal(thd, ltime, dec_arg) { max_length= MAX_DATETIME_WIDTH + (decimals ? decimals + 1 : 0); @@ -5056,6 +5086,7 @@ public: #include "item_xmlfunc.h" #include "item_jsonfunc.h" #include "item_create.h" +#include "item_vers.h" #endif /** @@ -6003,6 +6034,12 @@ public: { DBUG_ASSERT(item->fixed); maybe_null= item->maybe_null; + if (item->real_type() == Item::FIELD_ITEM) + { + Item_field *item_field= (Item_field *)item->real_item(); + flags|= (item_field->field->flags & + (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG)); + } } Item_type_holder(THD *thd, const LEX_CSTRING *name_arg, @@ -6050,6 +6087,12 @@ public: Type_geometry_attributes::set_geometry_type(type); } Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } + + uint flags; + uint32 field_flags() const + { + return flags; + } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f35017629aa..85bee75fe79 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -127,9 +127,12 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const char *funcname, many cases. */ set_handler(items[0]->type_handler()->type_handler_for_comparison()); + m_vers_trx_id= items[0]->vers_trx_id(); for (uint i= 1 ; i < nitems ; i++) { unsigned_count+= items[i]->unsigned_flag; + if (!m_vers_trx_id) + m_vers_trx_id= items[i]->vers_trx_id(); if (aggregate_for_comparison(items[i]->type_handler()-> type_handler_for_comparison())) { @@ -421,7 +424,7 @@ void Item_func::convert_const_compared_to_int_field(THD *thd) args[field= 1]->real_item()->type() == FIELD_ITEM) { Item_field *field_item= (Item_field*) (args[field]->real_item()); - if ((field_item->field_type() == MYSQL_TYPE_LONGLONG || + if (((field_item->field_type() == MYSQL_TYPE_LONGLONG && !field_item->vers_trx_id()) || field_item->field_type() == MYSQL_TYPE_YEAR)) convert_const_to_int(thd, field_item, &args[!field]); } @@ -5265,7 +5268,6 @@ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str, return FALSE; } - bool Item_func_like::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); diff --git a/sql/item_create.cc b/sql/item_create.cc index 5d6d9742c7a..d73a5327d25 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -43,38 +43,6 @@ */ /** - Adapter for native functions with a variable number of arguments. - The main use of this class is to discard the following calls: - <code>foo(expr1 AS name1, expr2 AS name2, ...)</code> - which are syntactically correct (the syntax can refer to a UDF), - but semantically invalid for native functions. -*/ - -class Create_native_func : public Create_func -{ -public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, - List<Item> *item_list); - - /** - Builder method, with no arguments. - @param thd The current thread - @param name The native function name - @param item_list The function parameters, none of which are named - @return An item representing the function call - */ - virtual Item *create_native(THD *thd, LEX_CSTRING *name, - List<Item> *item_list) = 0; - -protected: - /** Constructor. */ - Create_native_func() {} - /** Destructor. */ - virtual ~Create_native_func() {} -}; - - -/** Adapter for functions that takes exactly zero arguments. */ @@ -6827,12 +6795,6 @@ Create_func_year_week::create_native(THD *thd, LEX_CSTRING *name, } -struct Native_func_registry -{ - LEX_CSTRING name; - Create_func *builder; -}; - #define BUILDER(F) & F::s_singleton #ifdef HAVE_SPATIAL @@ -7218,8 +7180,6 @@ get_native_fct_hash_key(const uchar *buff, size_t *length, int item_create_init() { - Native_func_registry *func; - DBUG_ENTER("item_create_init"); if (my_hash_init(& native_functions_hash, @@ -7232,7 +7192,16 @@ int item_create_init() MYF(0))) DBUG_RETURN(1); - for (func= func_array; func->builder != NULL; func++) + DBUG_RETURN(item_create_append(func_array)); +} + +int item_create_append(Native_func_registry array[]) +{ + Native_func_registry *func; + + DBUG_ENTER("item_create_append"); + + for (func= array; func->builder != NULL; func++) { if (my_hash_insert(& native_functions_hash, (uchar*) func)) DBUG_RETURN(1); diff --git a/sql/item_create.h b/sql/item_create.h index 128a19a1c15..e0beca37082 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -19,6 +19,8 @@ #ifndef ITEM_CREATE_H #define ITEM_CREATE_H +#include "item_func.h" // Cast_target + typedef struct st_udf_func udf_func; /** @@ -67,6 +69,38 @@ protected: /** + Adapter for native functions with a variable number of arguments. + The main use of this class is to discard the following calls: + <code>foo(expr1 AS name1, expr2 AS name2, ...)</code> + which are syntactically correct (the syntax can refer to a UDF), + but semantically invalid for native functions. +*/ + +class Create_native_func : public Create_func +{ +public: + virtual Item *create_func(THD *thd, LEX_CSTRING *name, + List<Item> *item_list); + + /** + Builder method, with no arguments. + @param thd The current thread + @param name The native function name + @param item_list The function parameters, none of which are named + @return An item representing the function call + */ + virtual Item *create_native(THD *thd, LEX_CSTRING *name, + List<Item> *item_list) = 0; + +protected: + /** Constructor. */ + Create_native_func() {} + /** Destructor. */ + virtual ~Create_native_func() {} +}; + + +/** Function builder for qualified functions. This builder is used with functions call using a qualified function name syntax, as in <code>db.func(expr, expr, ...)</code>. @@ -172,7 +206,14 @@ Item *create_temporal_literal(THD *thd, const String *str, type, send_error); } +struct Native_func_registry +{ + LEX_STRING name; + Create_func *builder; +}; + int item_create_init(); +int item_create_append(Native_func_registry array[]); void item_create_cleanup(); Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list); diff --git a/sql/item_func.h b/sql/item_func.h index de213df0fc5..e8c9c0ef484 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -30,6 +30,9 @@ extern "C" /* Bug in BSDI include file */ } #endif +#include "sql_udf.h" // udf_handler +#include "my_decimal.h" // string2my_decimal + class Item_func :public Item_func_or_sum { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 3a7684fe7b4..9399ec9d359 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1687,6 +1687,15 @@ void Item_func_curtime_utc::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) */ } + +Item_func_now::Item_func_now(THD *thd, uint dec) : + Item_datetimefunc(thd, new (thd->mem_root) Item_decimal(thd, dec, TRUE)), + last_query_id(0) +{ + decimals = dec; +} + + bool Item_func_now::fix_fields(THD *thd, Item **items) { if (decimals > TIME_SECOND_PART_DIGITS) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 9c102e8a666..fc6d297d9ce 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -746,8 +746,7 @@ class Item_func_now :public Item_datetimefunc MYSQL_TIME ltime; query_id_t last_query_id; public: - Item_func_now(THD *thd, uint dec): Item_datetimefunc(thd), last_query_id(0) - { decimals= dec; } + Item_func_now(THD *thd, uint dec); bool fix_fields(THD *, Item **); void fix_length_and_dec() { fix_attributes_datetime(decimals); } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); diff --git a/sql/item_vers.cc b/sql/item_vers.cc new file mode 100644 index 00000000000..5866afa4570 --- /dev/null +++ b/sql/item_vers.cc @@ -0,0 +1,259 @@ +/* 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-1301, USA */ + + +/** + @brief + System Versioning items +*/ + +#include "sql_class.h" +#include "tztime.h" +#include "item.h" + +Item_func_vtq_ts::Item_func_vtq_ts( + THD *thd, + handlerton* hton, + Item* a, + vtq_field_t _vtq_field) : + VTQ_common<Item_datetimefunc>(thd, hton, a), + vtq_field(_vtq_field) +{ + decimals= 6; + null_value= true; + DBUG_ASSERT(arg_count == 1 && args[0]); + check_hton(); +} + +template <class Item_func_X> +void +VTQ_common<Item_func_X>::check_hton() +{ + DBUG_ASSERT(hton); + if (!(hton->flags & HTON_NATIVE_SYS_VERSIONING) && hton->db_type != DB_TYPE_HEAP) + { + my_error(ER_VERS_ENGINE_UNSUPPORTED, MYF(0), Item::name.str ? Item::name.str : this->func_name()); + hton= NULL; + } +} + +bool +Item_func_vtq_ts::get_date(MYSQL_TIME *res, ulonglong fuzzy_date) +{ + THD *thd= current_thd; // can it differ from constructor's? + DBUG_ASSERT(thd); + DBUG_ASSERT(args[0]); + if (args[0]->result_type() != INT_RESULT) + { + my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0), + args[0]->type_handler()->name().ptr(), + func_name()); + return true; + } + ulonglong trx_id= args[0]->val_uint(); + if (trx_id == ULONGLONG_MAX) + { + null_value= false; + thd->variables.time_zone->gmt_sec_to_TIME(res, TIMESTAMP_MAX_VALUE); + res->second_part= TIME_MAX_SECOND_PART; + return false; + } + + DBUG_ASSERT(hton && hton->vers_query_trx_id); + null_value= !hton->vers_query_trx_id(thd, res, trx_id, vtq_field); + if (null_value) + { + my_error(ER_VERS_NO_TRX_ID, MYF(0), trx_id); + } + + return null_value; +} + + +Item_func_vtq_id::Item_func_vtq_id( + THD *thd, + handlerton *hton, + Item* a, + vtq_field_t _vtq_field, + bool _backwards) : + VTQ_common<Item_longlong_func>(thd, hton, a), + vtq_field(_vtq_field), + backwards(_backwards) +{ + memset(&cached_result, 0, sizeof(cached_result)); + decimals= 0; + unsigned_flag= 1; + null_value= true; + DBUG_ASSERT(arg_count == 1 && args[0]); + check_hton(); +} + +Item_func_vtq_id::Item_func_vtq_id( + THD *thd, + handlerton *hton, + Item* a, + Item* b, + vtq_field_t _vtq_field) : + VTQ_common<Item_longlong_func>(thd, hton, a, b), + vtq_field(_vtq_field), + backwards(false) +{ + memset(&cached_result, 0, sizeof(cached_result)); + decimals= 0; + unsigned_flag= 1; + null_value= true; + DBUG_ASSERT(arg_count == 2 && args[0] && args[1]); + check_hton(); +} + +longlong +Item_func_vtq_id::get_by_trx_id(ulonglong trx_id) +{ + ulonglong res; + THD *thd= current_thd; // can it differ from constructor's? + DBUG_ASSERT(thd); + + if (trx_id == ULONGLONG_MAX) + { + null_value= true; + return 0; + } + + DBUG_ASSERT(hton->vers_query_trx_id); + null_value= !hton->vers_query_trx_id(thd, &res, trx_id, vtq_field); + return res; +} + +longlong +Item_func_vtq_id::get_by_commit_ts(MYSQL_TIME &commit_ts, bool backwards) +{ + THD *thd= current_thd; // can it differ from constructor's? + DBUG_ASSERT(thd); + + DBUG_ASSERT(hton->vers_query_commit_ts); + null_value= !hton->vers_query_commit_ts(thd, &cached_result, commit_ts, VTQ_ALL, backwards); + if (null_value) + { + return 0; + } + + switch (vtq_field) + { + case VTQ_COMMIT_ID: + return cached_result.commit_id; + case VTQ_ISO_LEVEL: + return cached_result.iso_level; + case VTQ_TRX_ID: + return cached_result.trx_id; + default: + DBUG_ASSERT(0); + null_value= true; + } + + return 0; +} + +longlong +Item_func_vtq_id::val_int() +{ + if (!hton) + { + null_value= true; + return 0; + } + + if (args[0]->is_null()) + { + if (arg_count < 2 || vtq_field == VTQ_TRX_ID) + { + null_value= true; + return 0; + } + return get_by_trx_id(args[1]->val_uint()); + } + else + { + MYSQL_TIME commit_ts; + if (args[0]->get_date(&commit_ts, 0)) + { + null_value= true; + return 0; + } + if (arg_count > 1) + { + backwards= args[1]->val_bool(); + DBUG_ASSERT(arg_count == 2); + } + return get_by_commit_ts(commit_ts, backwards); + } +} + +Item_func_vtq_trx_sees::Item_func_vtq_trx_sees( + THD *thd, + handlerton *hton, + Item* a, + Item* b) : + VTQ_common<Item_bool_func>(thd, hton, a, b), + accept_eq(false) +{ + null_value= true; + DBUG_ASSERT(arg_count == 2 && args[0] && args[1]); +} + +longlong +Item_func_vtq_trx_sees::val_int() +{ + THD *thd= current_thd; + DBUG_ASSERT(thd); + + if (!hton) + { + null_value= true; + return 0; + } + + ulonglong trx_id1, trx_id0; + ulonglong commit_id1= 0; + ulonglong commit_id0= 0; + uchar iso_level1= 0; + + DBUG_ASSERT(arg_count > 1); + trx_id1= args[0]->val_uint(); + trx_id0= args[1]->val_uint(); + + vtq_record_t *cached= args[0]->vtq_cached_result(); + if (cached && cached->commit_id) + { + commit_id1= cached->commit_id; + iso_level1= cached->iso_level; + } + + cached= args[1]->vtq_cached_result(); + if (cached && cached->commit_id) + { + commit_id0= cached->commit_id; + } + + if (accept_eq && trx_id1 && trx_id1 == trx_id0) + { + null_value= false; + return true; + } + + DBUG_ASSERT(hton->vers_trx_sees); + bool result= false; + null_value= !hton->vers_trx_sees(thd, result, trx_id1, trx_id0, commit_id1, iso_level1, commit_id0); + return result; +} diff --git a/sql/item_vers.h b/sql/item_vers.h new file mode 100644 index 00000000000..c2b127af817 --- /dev/null +++ b/sql/item_vers.h @@ -0,0 +1,137 @@ +#ifndef ITEM_VERS_INCLUDED +#define ITEM_VERS_INCLUDED +/* 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-1301, USA */ + + +/* System Versioning items */ + +#include "vtq.h" + +#ifdef USE_PRAGMA_INTERFACE +#pragma interface /* gcc class implementation */ +#endif + +template <class Item_func_X> +class VTQ_common : public Item_func_X +{ +protected: + handlerton *hton; + void check_hton(); +public: + VTQ_common(THD *thd, handlerton* _hton, Item* a, Item* b) : + Item_func_X(thd, a, b), + hton(_hton) {} + VTQ_common(THD *thd, handlerton* _hton, Item* a) : + Item_func_X(thd, a), + hton(_hton) {} +}; + +class Item_func_vtq_ts : + public VTQ_common<Item_datetimefunc> +{ + vtq_field_t vtq_field; +public: + Item_func_vtq_ts(THD *thd, handlerton *hton, Item* a, vtq_field_t _vtq_field); + const char *func_name() const + { + if (vtq_field == VTQ_BEGIN_TS) + { + return "vtq_begin_ts"; + } + return "vtq_commit_ts"; + } + bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_func_vtq_ts>(thd, mem_root, this); } + void fix_length_and_dec() { fix_attributes_datetime(decimals); } +}; + +class Item_func_vtq_id : + public VTQ_common<Item_longlong_func> +{ + vtq_field_t vtq_field; + vtq_record_t cached_result; + bool backwards; + + longlong get_by_trx_id(ulonglong trx_id); + longlong get_by_commit_ts(MYSQL_TIME &commit_ts, bool backwards); + +public: + Item_func_vtq_id(THD *thd, handlerton *hton, Item* a, vtq_field_t _vtq_field, bool _backwards= false); + Item_func_vtq_id(THD *thd, handlerton *hton, Item* a, Item* b, vtq_field_t _vtq_field); + + vtq_record_t *vtq_cached_result() { return &cached_result; } + + const char *func_name() const + { + switch (vtq_field) + { + case VTQ_TRX_ID: + return "vtq_trx_id"; + case VTQ_COMMIT_ID: + return "vtq_commit_id"; + case VTQ_ISO_LEVEL: + return "vtq_iso_level"; + default: + DBUG_ASSERT(0); + } + return NULL; + } + + void fix_length_and_dec() + { + Item_int_func::fix_length_and_dec(); + max_length= 20; + } + + longlong val_int(); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_func_vtq_id>(thd, mem_root, this); } +}; + +class Item_func_vtq_trx_sees : + public VTQ_common<Item_bool_func> +{ +protected: + bool accept_eq; + +public: + Item_func_vtq_trx_sees(THD *thd, handlerton *hton, Item* a, Item* b); + const char *func_name() const + { + return "vtq_trx_sees"; + } + longlong val_int(); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_func_vtq_trx_sees>(thd, mem_root, this); } +}; + +class Item_func_vtq_trx_sees_eq : + public Item_func_vtq_trx_sees +{ +public: + Item_func_vtq_trx_sees_eq(THD *thd, handlerton *hton, Item* a, Item* b) : + Item_func_vtq_trx_sees(thd, hton, a, b) + { + accept_eq= true; + } + const char *func_name() const + { + return "vtq_trx_sees_eq"; + } +}; + +#endif /* ITEM_VERS_INCLUDED */ diff --git a/sql/lex.h b/sql/lex.h index ef03afb7a32..68c98a95a7b 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -428,6 +428,7 @@ static SYMBOL symbols[] = { { "NONE", SYM(NONE_SYM)}, { "NOT", SYM(NOT_SYM)}, { "NOTFOUND", SYM(NOTFOUND_SYM)}, + { "NOW", SYM(NOW_SYM)}, { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)}, { "NULL", SYM(NULL_SYM)}, { "NUMBER", SYM(NUMBER_SYM)}, @@ -458,6 +459,7 @@ static SYMBOL symbols[] = { { "PAGE_CHECKSUM", SYM(PAGE_CHECKSUM_SYM)}, { "PARSER", SYM(PARSER_SYM)}, { "PARSE_VCOL_EXPR", SYM(PARSE_VCOL_EXPR_SYM)}, + { "PERIOD", SYM(PERIOD_SYM)}, { "PARTIAL", SYM(PARTIAL)}, { "PARTITION", SYM(PARTITION_SYM)}, { "PARTITIONING", SYM(PARTITIONING_SYM)}, @@ -627,6 +629,8 @@ static SYMBOL symbols[] = { { "SUSPEND", SYM(SUSPEND_SYM)}, { "SWAPS", SYM(SWAPS_SYM)}, { "SWITCHES", SYM(SWITCHES_SYM)}, + { "SYSTEM", SYM(SYSTEM)}, + { "SYSTEM_TIME", SYM(SYSTEM_TIME_SYM)}, { "TABLE", SYM(TABLE_SYM)}, { "TABLE_NAME", SYM(TABLE_NAME_SYM)}, { "TABLES", SYM(TABLES)}, @@ -692,6 +696,7 @@ static SYMBOL symbols[] = { { "VIA", SYM(VIA_SYM)}, { "VIEW", SYM(VIEW_SYM)}, { "VIRTUAL", SYM(VIRTUAL_SYM)}, + { "VERSIONING", SYM(VERSIONING_SYM)}, { "WAIT", SYM(WAIT_SYM)}, { "WARNINGS", SYM(WARNINGS)}, { "WEEK", SYM(WEEK_SYM)}, @@ -701,6 +706,7 @@ static SYMBOL symbols[] = { { "WHILE", SYM(WHILE_SYM)}, { "WINDOW", SYM(WINDOW_SYM)}, { "WITH", SYM(WITH)}, + { "WITHOUT", SYM(WITHOUT)}, { "WORK", SYM(WORK_SYM)}, { "WRAPPER", SYM(WRAPPER_SYM)}, { "WRITE", SYM(WRITE_SYM)}, @@ -738,7 +744,6 @@ static SYMBOL sql_functions[] = { { "MAX", SYM(MAX_SYM)}, { "MID", SYM(SUBSTRING)}, /* unireg function */ { "MIN", SYM(MIN_SYM)}, - { "NOW", SYM(NOW_SYM)}, { "NTH_VALUE", SYM(NTH_VALUE_SYM)}, { "NTILE", SYM(NTILE_SYM)}, { "POSITION", SYM(POSITION_SYM)}, diff --git a/sql/log_event.cc b/sql/log_event.cc index f1ceaec6456..102fbc251e3 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -44,6 +44,7 @@ #include <strfunc.h> #include "compat56.h" #include "wsrep_mysqld.h" +#include "sql_insert.h" #endif /* MYSQL_CLIENT */ #include <my_bitmap.h> @@ -12504,6 +12505,22 @@ Rows_log_event::write_row(rpl_group_info *rgi, DBUG_RETURN(HA_ERR_GENERIC); // in case if error is not set yet } + // Handle INSERT. + // Set vers fields when replicating from not system-versioned table. + if (m_type == WRITE_ROWS_EVENT_V1 && table->versioned_by_sql()) + { + bitmap_set_bit(table->read_set, table->vers_start_field()->field_index); + // Check whether a row came from unversioned table and fix vers fields. + if (table->vers_start_field()->get_timestamp() == 0) + { + bitmap_set_bit(table->write_set, table->vers_start_field()->field_index); + bitmap_set_bit(table->write_set, table->vers_end_field()->field_index); + thd->set_current_time(); + table->vers_start_field()->set_time(); + table->vers_end_field()->set_max(); + } + } + /* Try to write record. If a corresponding record already exists in the table, we try to change it using ha_update_row() if possible. Otherwise we delete @@ -12824,7 +12841,10 @@ static bool record_compare(TABLE *table) /* Compare fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - + if (table->versioned() && (*ptr)->vers_sys_field()) + { + continue; + } /** We only compare field contents that are not null. NULL fields (i.e., their null bits) were compared @@ -13019,6 +13039,27 @@ int Rows_log_event::find_row(rpl_group_info *rgi) prepare_record(table, m_width, FALSE); error= unpack_current_row(rgi); + m_vers_from_plain= false; + if (table->versioned()) + { + Field *sys_trx_end= table->vers_end_field(); + DBUG_ASSERT(table->read_set); + bitmap_set_bit(table->read_set, sys_trx_end->field_index); + // check whether master table is unversioned + if (sys_trx_end->val_int() == 0) + { + // sys_trx_start initialized with NULL when came from plain table. + // Set it notnull() because record_compare() count NULLs. + table->vers_start_field()->set_notnull(); + bitmap_set_bit(table->write_set, sys_trx_end->field_index); + // Plain source table may have a PRIMARY KEY. And sys_trx_end is always + // a part of PRIMARY KEY. Set it to max value for engine to find it in + // index. Needed for an UPDATE/DELETE cases. + table->vers_end_field()->set_max(); + m_vers_from_plain= true; + } + } + DBUG_PRINT("info",("looking for the following record")); DBUG_DUMP("record[0]", table->record[0], table->s->reclength); @@ -13400,7 +13441,19 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi) if (!error) { m_table->mark_columns_per_binlog_row_image(); - error= m_table->file->ha_delete_row(m_table->record[0]); + if (m_vers_from_plain && m_table->versioned_by_sql()) + { + Field *end= m_table->vers_end_field(); + bitmap_set_bit(m_table->write_set, end->field_index); + store_record(m_table, record[1]); + end->set_time(); + error= m_table->file->ha_update_row(m_table->record[1], + m_table->record[0]); + } + else + { + error= m_table->file->ha_delete_row(m_table->record[0]); + } m_table->default_column_bitmaps(); } if (invoke_triggers && !error && @@ -13657,9 +13710,22 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi) memcpy(m_table->write_set->bitmap, m_cols_ai.bitmap, (m_table->write_set->n_bits + 7) / 8); m_table->mark_columns_per_binlog_row_image(); + if (m_vers_from_plain && m_table->versioned_by_sql()) + { + bitmap_set_bit(m_table->write_set, + m_table->vers_start_field()->field_index); + thd->set_current_time(); + m_table->vers_start_field()->set_time(); + } error= m_table->file->ha_update_row(m_table->record[1], m_table->record[0]); if (error == HA_ERR_RECORD_IS_THE_SAME) error= 0; + if (m_vers_from_plain && m_table->versioned_by_sql()) + { + store_record(m_table, record[2]); + error= vers_insert_history_row(m_table); + restore_record(m_table, record[2]); + } m_table->default_column_bitmaps(); if (invoke_triggers && !error && diff --git a/sql/log_event.h b/sql/log_event.h index c8f3241cb3d..2dedd8bbe9a 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -4594,6 +4594,8 @@ protected: uchar *m_extra_row_data; /* Pointer to extra row data if any */ /* If non null, first byte is length */ + bool m_vers_from_plain; + /* helper functions */ @@ -4744,6 +4746,7 @@ public: __attribute__((unused)), const uchar *after_record) { + DBUG_ASSERT(!table->versioned_by_engine()); return thd->binlog_write_row(table, is_transactional, after_record); } #endif @@ -4825,6 +4828,7 @@ public: const uchar *before_record, const uchar *after_record) { + DBUG_ASSERT(!table->versioned_by_engine()); return thd->binlog_update_row(table, is_transactional, before_record, after_record); } @@ -4914,6 +4918,7 @@ public: const uchar *after_record __attribute__((unused))) { + DBUG_ASSERT(!table->versioned_by_engine()); return thd->binlog_delete_row(table, is_transactional, before_record); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ad27c58f67f..14cfc7e9e5a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -943,6 +943,9 @@ PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered, key_LOCK_slave_background; PSI_mutex_key key_TABLE_SHARE_LOCK_share; +PSI_mutex_key key_TABLE_SHARE_LOCK_rotation; +PSI_cond_key key_TABLE_SHARE_COND_rotation; + static PSI_mutex_info all_server_mutexes[]= { #ifdef HAVE_MMAP @@ -1004,6 +1007,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0}, { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0}, { &key_TABLE_SHARE_LOCK_share, "TABLE_SHARE::LOCK_share", 0}, + { &key_TABLE_SHARE_LOCK_rotation, "TABLE_SHARE::LOCK_rotation", 0}, { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL}, { &key_LOCK_prepare_ordered, "LOCK_prepare_ordered", PSI_FLAG_GLOBAL}, { &key_LOCK_after_binlog_sync, "LOCK_after_binlog_sync", PSI_FLAG_GLOBAL}, @@ -1024,8 +1028,8 @@ static PSI_mutex_info all_server_mutexes[]= PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave, key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock, - key_LOCK_SEQUENCE; - + key_LOCK_SEQUENCE, + key_rwlock_LOCK_vers_stats, key_rwlock_LOCK_stat_serial; static PSI_rwlock_info all_server_rwlocks[]= { @@ -1038,7 +1042,9 @@ static PSI_rwlock_info all_server_rwlocks[]= { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL}, { &key_LOCK_SEQUENCE, "LOCK_SEQUENCE", 0}, { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL}, - { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0} + { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0}, + { &key_rwlock_LOCK_vers_stats, "Vers_field_stats::lock", 0}, + { &key_rwlock_LOCK_stat_serial, "TABLE_SHARE::LOCK_stat_serial", 0} }; #ifdef HAVE_MMAP @@ -1121,7 +1127,8 @@ static PSI_cond_info all_server_conds[]= { &key_COND_slave_background, "COND_slave_background", 0}, { &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL}, { &key_COND_wait_gtid, "COND_wait_gtid", 0}, - { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0} + { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0}, + { &key_TABLE_SHARE_COND_rotation, "TABLE_SHARE::COND_rotation", 0} }; PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, @@ -9432,6 +9439,17 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument) WSREP_SYNC_WAIT_BEFORE_READ); break; #endif /* WITH_WSREP */ + case OPT_VERS_CURRENT_TIME: + sys_var *var= static_cast<sys_var*>(opt->app_type); + DBUG_ASSERT(var); + if (var->option_updated()) + { + sql_print_error("Can't start server: " + "cannot process --vers-current-time=%.*s", + FN_REFLEN, argument); + return 1; + } + break; } return 0; } diff --git a/sql/mysqld.h b/sql/mysqld.h index 8364eecdb7c..6f5550d20ae 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -179,6 +179,48 @@ extern char *opt_backup_history_logname, *opt_backup_progress_logname, *opt_backup_settings_name; extern const char *log_output_str; extern const char *log_backup_output_str; + +/* System Versioning begin */ +enum vers_range_type_t +{ + FOR_SYSTEM_TIME_UNSPECIFIED = 0, + FOR_SYSTEM_TIME_AS_OF, + FOR_SYSTEM_TIME_FROM_TO, + FOR_SYSTEM_TIME_BETWEEN, + FOR_SYSTEM_TIME_ALL, + FOR_SYSTEM_TIME_BEFORE +}; + +/* Used only for @@versioning_current_time sysvar. This struct must be POD + * because of str_value, which is used as interface to user. + * So no virtual-anything! */ +struct st_vers_current_time +{ + char *str_value; // must be first + vers_range_type_t type; + MYSQL_TIME ltime; + st_vers_current_time() : + str_value(NULL), + type(FOR_SYSTEM_TIME_UNSPECIFIED) + {} +}; + +enum vers_hide_enum +{ + VERS_HIDE_AUTO= 0, + VERS_HIDE_IMPLICIT, + VERS_HIDE_FULL, + VERS_HIDE_NEVER +}; + +enum vers_alter_history_enum +{ + VERS_ALTER_HISTORY_KEEP= 0, + VERS_ALTER_HISTORY_SURVIVE, + VERS_ALTER_HISTORY_DROP +}; +/* System Versioning end */ + extern char *mysql_home_ptr, *pidfile_name_ptr; extern MYSQL_PLUGIN_IMPORT char glob_hostname[FN_REFLEN]; extern char mysql_home[FN_REFLEN]; @@ -313,13 +355,16 @@ extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, extern PSI_mutex_key key_TABLE_SHARE_LOCK_share, key_LOCK_stats, key_LOCK_global_user_client_stats, key_LOCK_global_table_stats, - key_LOCK_global_index_stats, key_LOCK_wakeup_ready, key_LOCK_wait_commit; + key_LOCK_global_index_stats, key_LOCK_wakeup_ready, key_LOCK_wait_commit, + key_TABLE_SHARE_LOCK_rotation; extern PSI_mutex_key key_LOCK_gtid_waiting; extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave, key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock, - key_LOCK_SEQUENCE; + key_LOCK_SEQUENCE, + key_rwlock_LOCK_vers_stats, key_rwlock_LOCK_stat_serial; + #ifdef HAVE_MMAP extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool; #endif /* HAVE_MMAP */ @@ -347,6 +392,7 @@ extern PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_queue, key_COND_rpl_thread_stop, key_COND_rpl_thread_pool, key_COND_parallel_entry, key_COND_group_commit_orderer; extern PSI_cond_key key_COND_wait_gtid, key_COND_gtid_ignore_duplicates; +extern PSI_cond_key key_TABLE_SHARE_COND_rotation; extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, key_thread_handle_manager, key_thread_kill_server, key_thread_main, @@ -649,6 +695,7 @@ enum options_mysqld OPT_SSL_KEY, OPT_THREAD_CONCURRENCY, OPT_WANT_CORE, + OPT_VERS_CURRENT_TIME, #ifdef WITH_WSREP OPT_WSREP_CAUSAL_READS, OPT_WSREP_SYNC_WAIT, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3180c509737..675064067fc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3454,6 +3454,13 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) free_root(&alloc,MYF(0)); // Return memory & allocator DBUG_RETURN(FALSE); } + + if (part_info->part_type == VERSIONING_PARTITION && + part_info->vers_update_range_constants(thd)) + { + retval= TRUE; + goto end2; + } dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set); @@ -3554,6 +3561,7 @@ all_used: mark_all_partitions_as_used(prune_param.part_info); end: dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); +end2: thd->no_errors=0; thd->mem_root= range_par->old_root; free_root(&alloc,MYF(0)); // Return memory & allocator @@ -3980,7 +3988,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) simply set res= -1 as if the mapper had returned that. TODO: What to do here is defined in WL#4065. */ - if (ppar->arg_stack[0]->part == 0) + if (ppar->arg_stack[0]->part == 0 || ppar->part_info->part_type == VERSIONING_PARTITION) { uint32 i; uint32 store_length_array[MAX_KEY]; diff --git a/sql/partition_element.h b/sql/partition_element.h index c774994b7f5..fc486abffc2 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -26,7 +26,8 @@ enum partition_type { NOT_A_PARTITION= 0, RANGE_PARTITION, HASH_PARTITION, - LIST_PARTITION + LIST_PARTITION, + VERSIONING_PARTITION }; enum partition_state { @@ -89,8 +90,74 @@ typedef struct p_elem_val struct st_ddl_log_memory_entry; -class partition_element :public Sql_alloc { +/* Used for collecting MIN/MAX stats on sys_trx_end for doing pruning + in SYSTEM_TIME partitiong. */ +class Vers_min_max_stats : public Sql_alloc +{ + static const uint buf_size= 4 + (TIME_SECOND_PART_DIGITS + 1) / 2; + uchar min_buf[buf_size]; + uchar max_buf[buf_size]; + Field_timestampf min_value; + Field_timestampf max_value; + mysql_rwlock_t lock; + +public: + Vers_min_max_stats(const LEX_CSTRING *field_name, TABLE_SHARE *share) : + min_value(min_buf, NULL, 0, Field::NONE, field_name, share, 6), + max_value(max_buf, NULL, 0, Field::NONE, field_name, share, 6) + { + min_value.set_max(); + memset(max_buf, 0, buf_size); + mysql_rwlock_init(key_rwlock_LOCK_vers_stats, &lock); + } + ~Vers_min_max_stats() + { + mysql_rwlock_destroy(&lock); + } + bool update_unguarded(Field *from) + { + return + from->update_min(&min_value, false) + + from->update_max(&max_value, false); + } + bool update(Field *from) + { + mysql_rwlock_wrlock(&lock); + bool res= update_unguarded(from); + mysql_rwlock_unlock(&lock); + return res; + } + my_time_t min_time() + { + mysql_rwlock_rdlock(&lock); + my_time_t res= min_value.get_timestamp(); + mysql_rwlock_unlock(&lock); + return res; + } + my_time_t max_time() + { + mysql_rwlock_rdlock(&lock); + my_time_t res= max_value.get_timestamp(); + mysql_rwlock_unlock(&lock); + return res; + } +}; + +enum stat_trx_field +{ + STAT_TRX_END= 0 +}; + +class partition_element :public Sql_alloc +{ public: + enum elem_type + { + CONVENTIONAL= 0, + AS_OF_NOW, + VERSIONING + }; + List<partition_element> subpartitions; List<part_elem_value> list_val_list; ha_rows part_max_rows; @@ -109,6 +176,21 @@ public: bool has_null_value; bool signed_flag; // Range value signed bool max_value; // MAXVALUE range + uint32 id; + bool empty; + + // TODO: subclass partition_element by partitioning type to avoid such semantic + // mixup + elem_type type() + { + return (elem_type)(signed_flag << 1 | max_value); + } + + void type(elem_type val) + { + max_value= val & 1; + signed_flag= val & 2; + } partition_element() : part_max_rows(0), part_min_rows(0), range_value(0), @@ -117,9 +199,10 @@ public: data_file_name(NULL), index_file_name(NULL), engine_type(NULL), connect_string(null_clex_str), part_state(PART_NORMAL), nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE), - signed_flag(FALSE), max_value(FALSE) - { - } + signed_flag(FALSE), max_value(FALSE), + id(UINT32_MAX), + empty(true) + {} partition_element(partition_element *part_elem) : part_max_rows(part_elem->part_max_rows), part_min_rows(part_elem->part_min_rows), @@ -132,10 +215,20 @@ public: connect_string(null_clex_str), part_state(part_elem->part_state), nodegroup_id(part_elem->nodegroup_id), - has_null_value(FALSE) + has_null_value(FALSE), + id(part_elem->id), + empty(part_elem->empty) + {} + ~partition_element() {} + + part_column_list_val& get_col_val(uint idx) { + DBUG_ASSERT(type() == CONVENTIONAL || list_val_list.elements == 1); + part_elem_value *ev= list_val_list.head(); + DBUG_ASSERT(ev); + DBUG_ASSERT(ev->col_val_array); + return ev->col_val_array[idx]; } - ~partition_element() {} }; #endif /* PARTITION_ELEMENT_INCLUDED */ diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 6fdbdfce893..a06179fe132 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -21,6 +21,8 @@ #endif #include "mariadb.h" +#include <my_global.h> +#include <tztime.h> #include "sql_priv.h" // Required to get server definitions for mysql/plugin.h right #include "sql_plugin.h" @@ -30,6 +32,7 @@ #include "sql_parse.h" #include "sql_acl.h" // *_ACL #include "sql_base.h" // fill_record +#include "sql_statistics.h" // vers_stat_end #ifdef WITH_PARTITION_STORAGE_ENGINE #include "ha_partition.h" @@ -42,13 +45,12 @@ partition_info *partition_info::get_clone(THD *thd) List_iterator<partition_element> part_it(partitions); partition_element *part; - partition_info *clone= new (mem_root) partition_info(); + partition_info *clone= new (mem_root) partition_info(*this); if (!clone) { mem_alloc_error(sizeof(partition_info)); DBUG_RETURN(NULL); } - memcpy(clone, this, sizeof(partition_info)); memset(&(clone->read_partitions), 0, sizeof(clone->read_partitions)); memset(&(clone->lock_partitions), 0, sizeof(clone->lock_partitions)); clone->bitmaps_are_initialized= FALSE; @@ -114,6 +116,19 @@ partition_info *partition_info::get_clone(THD *thd) part_clone->list_val_list.push_back(new_val, mem_root); } } + if (part_type == VERSIONING_PARTITION && vers_info) + { + // clone Vers_part_info; set now_part, hist_part + clone->vers_info= new (mem_root) Vers_part_info(*vers_info); + List_iterator<partition_element> it(clone->partitions); + while ((part= it++)) + { + if (vers_info->now_part && part->id == vers_info->now_part->id) + clone->vers_info->now_part= part; + else if (vers_info->hist_part && part->id == vers_info->hist_part->id) + clone->vers_info->hist_part= part; + } // while ((part= it++)) + } // if (part_type == VERSIONING_PARTITION ... DBUG_RETURN(clone); } @@ -200,6 +215,48 @@ bool partition_info::set_named_partition_bitmap(const char *part_name, @param table_list Table list pointing to table to prune. @return Operation status + @retval false Success + @retval true Failure +*/ +bool partition_info::set_read_partitions(List<char> *partition_names) +{ + DBUG_ENTER("partition_info::set_read_partitions"); + if (!partition_names || !partition_names->elements) + { + DBUG_RETURN(true); + } + + uint num_names= partition_names->elements; + List_iterator<char> partition_names_it(*partition_names); + uint i= 0; + /* + TODO: When adding support for FK in partitioned tables, the referenced + table must probably lock all partitions for read, and also write depending + of ON DELETE/UPDATE. + */ + bitmap_clear_all(&read_partitions); + + /* No check for duplicate names or overlapping partitions/subpartitions. */ + + DBUG_PRINT("info", ("Searching through partition_name_hash")); + do + { + char *part_name= partition_names_it++; + if (add_named_partition(part_name, strlen(part_name))) + DBUG_RETURN(true); + } while (++i < num_names); + DBUG_RETURN(false); +} + + + +/** + Prune away partitions not mentioned in the PARTITION () clause, + if used. + + @param table_list Table list pointing to table to prune. + + @return Operation status @retval true Failure @retval false Success */ @@ -780,6 +837,437 @@ bool partition_info::has_unique_name(partition_element *element) DBUG_RETURN(TRUE); } +bool partition_info::vers_init_info(THD * thd) +{ + part_type= VERSIONING_PARTITION; + list_of_part_fields= TRUE; + column_list= TRUE; + num_columns= 1; + vers_info= new (thd->mem_root) Vers_part_info; + if (!vers_info) + { + mem_alloc_error(sizeof(Vers_part_info)); + return true; + } + return false; +} + +bool partition_info::vers_set_interval(const INTERVAL & i) +{ + if (i.neg || i.second_part) + return true; + + DBUG_ASSERT(vers_info); + + // TODO: INTERVAL conversion to seconds leads to mismatch with calendar intervals (MONTH and YEAR) + vers_info->interval= + i.second + + i.minute * 60 + + i.hour * 60 * 60 + + i.day * 24 * 60 * 60 + + i.month * 30 * 24 * 60 * 60 + + i.year * 365 * 30 * 24 * 60 * 60; + + if (vers_info->interval == 0) + return true; + + return false; +} + +bool partition_info::vers_set_limit(ulonglong limit) +{ + if (limit < 1) + return true; + + DBUG_ASSERT(vers_info); + + vers_info->limit= limit; + return false; +} + +partition_element* +partition_info::vers_part_rotate(THD * thd) +{ + DBUG_ASSERT(table && table->s); + DBUG_ASSERT(vers_info && vers_info->initialized()); + + if (table->s->hist_part_id >= vers_info->now_part->id - 1) + { + DBUG_ASSERT(table->s->hist_part_id == vers_info->now_part->id - 1); + push_warning_printf(thd, + Sql_condition::WARN_LEVEL_WARN, + WARN_VERS_PART_FULL, + ER_THD(thd, WARN_VERS_PART_FULL), + vers_info->hist_part->partition_name); + return vers_info->hist_part; + } + + table->s->hist_part_id++; + const char* old_part_name= vers_info->hist_part->partition_name; + vers_hist_part(); + + push_warning_printf(thd, + Sql_condition::WARN_LEVEL_NOTE, + WARN_VERS_PART_ROTATION, + ER_THD(thd, WARN_VERS_PART_ROTATION), + old_part_name, + vers_info->hist_part->partition_name); + + return vers_info->hist_part; +} + +bool partition_info::vers_set_expression(THD *thd, partition_element *el, MYSQL_TIME& t) +{ + curr_part_elem= el; + init_column_part(thd); + el->list_val_list.empty(); + el->list_val_list.push_back(curr_list_val, thd->mem_root); + for (uint i= 0; i < num_columns; ++i) + { + part_column_list_val *col_val= add_column_value(thd); + if (el->type() == partition_element::AS_OF_NOW) + { + col_val->max_value= true; + col_val->item_expression= NULL; + col_val->column_value= NULL; + col_val->part_info= this; + col_val->fixed= 1; + continue; + } + Item *item_expression= new (thd->mem_root) Item_datetime_literal(thd, &t); + if (!item_expression) + return true; + /* We initialize col_val with bogus max value to make fix_partition_func() and check_range_constants() happy. + Later in vers_setup_stats() it is initialized with real stat value if there will be any. */ + /* FIXME: TIME_RESULT in col_val is expensive. It should be INT_RESULT + (got to be fixed when InnoDB is supported). */ + init_col_val(col_val, item_expression); + DBUG_ASSERT(item_expression == el->get_col_val(i).item_expression); + } // for (num_columns) + return false; +} + +bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add) +{ + DBUG_ASSERT(part_type == VERSIONING_PARTITION); + + if (!table->versioned()) + { + my_error(ER_VERSIONING_REQUIRED, MYF(0), table->s->table_name); + return true; + } + + if (alter_add) + { + DBUG_ASSERT(partitions.elements > alter_add + 1); + Vers_min_max_stats** old_array= table->s->stat_trx; + table->s->stat_trx= static_cast<Vers_min_max_stats**>( + alloc_root(&table->s->mem_root, sizeof(void *) * partitions.elements * num_columns)); + memcpy(table->s->stat_trx, old_array, sizeof(void *) * (partitions.elements - alter_add) * num_columns); + } + else + { + /* Prepare part_field_list */ + Field *sys_trx_end= table->vers_end_field(); + part_field_list.push_back(sys_trx_end->field_name.str, thd->mem_root); + DBUG_ASSERT(part_field_list.elements == num_columns); + // needed in handle_list_of_fields() + sys_trx_end->flags|= GET_FIXED_FIELDS_FLAG; + } + + List_iterator<partition_element> it(partitions); + partition_element *el; + MYSQL_TIME t; + memset(&t, 0, sizeof(t)); + my_time_t ts= TIMESTAMP_MAX_VALUE - partitions.elements; + uint32 id= 0; + while ((el= it++)) + { + DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL); + ++ts; + if (alter_add) + { + /* Non-empty historical partitions are left as is. */ + if (el->type() == partition_element::VERSIONING && !el->empty) + { + ++id; + continue; + } + /* Newly added element is inserted before AS_OF_NOW. */ + if (el->id == UINT32_MAX || el->type() == partition_element::AS_OF_NOW) + { + DBUG_ASSERT(table && table->s); + Vers_min_max_stats *stat_trx_end= new (&table->s->mem_root) + Vers_min_max_stats(&table->s->vers_end_field()->field_name, table->s); + table->s->stat_trx[id * num_columns + STAT_TRX_END]= stat_trx_end; + el->id= id++; + if (el->type() == partition_element::AS_OF_NOW) + break; + goto set_expression; + } + /* Existing element expression is recalculated. */ + thd->variables.time_zone->gmt_sec_to_TIME(&t, ts); + for (uint i= 0; i < num_columns; ++i) + { + part_column_list_val &col_val= el->get_col_val(i); + static_cast<Item_datetime_literal *>(col_val.item_expression)->set_time(&t); + col_val.fixed= 0; + } + ++id; + continue; + } + + set_expression: + thd->variables.time_zone->gmt_sec_to_TIME(&t, ts); + if (vers_set_expression(thd, el, t)) + return true; + } + return false; +} + + +// scan table for min/max sys_trx_end +inline +bool partition_info::vers_scan_min_max(THD *thd, partition_element *part) +{ + uint32 sub_factor= num_subparts ? num_subparts : 1; + uint32 part_id= part->id * sub_factor; + uint32 part_id_end= part_id + sub_factor; + DBUG_ASSERT(part->empty); + DBUG_ASSERT(part->type() == partition_element::VERSIONING); + DBUG_ASSERT(table->s->stat_trx); + for (; part_id < part_id_end; ++part_id) + { + handler *file= table->file->part_handler(part_id); // requires update_partition() for ha_innopart + DBUG_ASSERT(file); + int rc= file->ha_external_lock(thd, F_RDLCK); // requires ha_commit_trans() for ha_innobase + if (rc) + { + file->update_partition(part_id); + goto lock_fail; + } + + table->default_column_bitmaps(); + bitmap_set_bit(table->read_set, table->vers_end_field()->field_index); + file->column_bitmaps_signal(); + + rc= file->ha_rnd_init(true); + if (!rc) + { + while ((rc= file->ha_rnd_next(table->record[0])) != HA_ERR_END_OF_FILE) + { + if (part->empty) + part->empty= false; + if (thd->killed) + { + file->ha_rnd_end(); + file->update_partition(part_id); + ha_commit_trans(thd, false); + return true; + } + if (rc) + { + if (rc == HA_ERR_RECORD_DELETED) + continue; + break; + } + if (table->vers_end_field()->is_max()) + { + rc= HA_ERR_INTERNAL_ERROR; + push_warning_printf(thd, + Sql_condition::WARN_LEVEL_WARN, + WARN_VERS_PART_NON_HISTORICAL, + ER_THD(thd, WARN_VERS_PART_NON_HISTORICAL), + part->partition_name); + break; + } + if (table->versioned_by_engine()) + { + uchar buf[8]; + Field_timestampf fld(buf, NULL, 0, Field::NONE, &table->vers_end_field()->field_name, NULL, 6); + if (!vers_trx_id_to_ts(thd, table->vers_end_field(), fld)) + { + vers_stat_trx(STAT_TRX_END, part).update_unguarded(&fld); + } + } + else + { + vers_stat_trx(STAT_TRX_END, part).update_unguarded(table->vers_end_field()); + } + } + file->ha_rnd_end(); + } + file->ha_external_lock(thd, F_UNLCK); + file->update_partition(part_id); + if (rc != HA_ERR_END_OF_FILE) + { + ha_commit_trans(thd, false); + lock_fail: + // TODO: print rc code + my_error(ER_INTERNAL_ERROR, MYF(0), "min/max scan failed in versioned partitions setup (see warnings)"); + return true; + } + } + ha_commit_trans(thd, false); + return false; +} + +void partition_info::vers_update_col_vals(THD *thd, partition_element *el0, partition_element *el1) +{ + MYSQL_TIME t; + memset(&t, 0, sizeof(t)); + DBUG_ASSERT(table && table->s && table->s->stat_trx); + DBUG_ASSERT(!el0 || el1->id == el0->id + 1); + const uint idx= el1->id * num_columns; + my_time_t ts; + part_column_list_val *col_val; + Item_datetime_literal *val_item; + Vers_min_max_stats *stat_trx_x; + for (uint i= 0; i < num_columns; ++i) + { + stat_trx_x= table->s->stat_trx[idx + i]; + if (el0) + { + ts= stat_trx_x->min_time(); + thd->variables.time_zone->gmt_sec_to_TIME(&t, ts); + col_val= &el0->get_col_val(i); + val_item= static_cast<Item_datetime_literal*>(col_val->item_expression); + DBUG_ASSERT(val_item); + if (*val_item > t) + { + val_item->set_time(&t); + col_val->fixed= 0; + } + } + col_val= &el1->get_col_val(i); + if (!col_val->max_value) + { + ts= stat_trx_x->max_time() + 1; + thd->variables.time_zone->gmt_sec_to_TIME(&t, ts); + val_item= static_cast<Item_datetime_literal*>(col_val->item_expression); + DBUG_ASSERT(val_item); + if (*val_item < t) + { + val_item->set_time(&t); + col_val->fixed= 0; + } + } + } +} + + +// setup at open() phase (TABLE_SHARE is initialized) +bool partition_info::vers_setup_stats(THD * thd, bool is_create_table_ind) +{ + DBUG_ASSERT(part_type == VERSIONING_PARTITION); + DBUG_ASSERT(vers_info && vers_info->initialized(false)); + DBUG_ASSERT(table && table->s); + + bool error= false; + + mysql_mutex_lock(&table->s->LOCK_rotation); + if (table->s->busy_rotation) + { + table->s->vers_wait_rotation(); + vers_hist_part(); + } + else + { + table->s->busy_rotation= true; + mysql_mutex_unlock(&table->s->LOCK_rotation); + + DBUG_ASSERT(part_field_list.elements == num_columns); + + bool dont_stat= true; + bool col_val_updated= false; + // initialize stat_trx + if (!table->s->stat_trx) + { + DBUG_ASSERT(partitions.elements > 1); + table->s->stat_trx= static_cast<Vers_min_max_stats**>( + alloc_root(&table->s->mem_root, sizeof(void *) * partitions.elements * num_columns)); + dont_stat= false; + } + + // build freelist, scan min/max, assign hist_part + List_iterator<partition_element> it(partitions); + partition_element *el= NULL, *prev; + while ((prev= el, el= it++)) + { + if (el->type() == partition_element::VERSIONING && dont_stat) + { + if (el->id == table->s->hist_part_id) + { + vers_info->hist_part= el; + break; + } + continue; + } + + { + Vers_min_max_stats *stat_trx_end= new (&table->s->mem_root) + Vers_min_max_stats(&table->s->vers_end_field()->field_name, table->s); + table->s->stat_trx[el->id * num_columns + STAT_TRX_END]= stat_trx_end; + } + + if (!is_create_table_ind) + { + if (el->type() == partition_element::AS_OF_NOW) + { + uchar buf[8]; + Field_timestampf fld(buf, NULL, 0, Field::NONE, &table->vers_end_field()->field_name, NULL, 6); + fld.set_max(); + vers_stat_trx(STAT_TRX_END, el).update_unguarded(&fld); + el->empty= false; + } + else if (vers_scan_min_max(thd, el)) + { + table->s->stat_trx= NULL; // may be a leak on endless table open + error= true; + break; + } + if (!el->empty) + { + vers_update_col_vals(thd, prev, el); + col_val_updated= true; + } + } + + if (el->type() == partition_element::AS_OF_NOW) + break; + + DBUG_ASSERT(el->type() == partition_element::VERSIONING); + + if (vers_info->hist_part) + { + if (!el->empty) + goto set_hist_part; + } + else + { + set_hist_part: + vers_info->hist_part= el; + continue; + } + } // while + + if (!error && !dont_stat) + { + if (col_val_updated) + table->s->stat_serial++; + + table->s->hist_part_id= vers_info->hist_part->id; + if (!is_create_table_ind && (vers_limit_exceed() || vers_interval_exceed())) + vers_part_rotate(thd); + } + mysql_mutex_lock(&table->s->LOCK_rotation); + mysql_cond_broadcast(&table->s->COND_rotation); + table->s->busy_rotation= false; + } + mysql_mutex_unlock(&table->s->LOCK_rotation); + return error; +} + /* Check that the partition/subpartition is setup to use the correct @@ -963,7 +1451,7 @@ error: called for RANGE PARTITIONed tables. */ -bool partition_info::check_range_constants(THD *thd) +bool partition_info::check_range_constants(THD *thd, bool alloc) { partition_element* part_def; bool first= TRUE; @@ -980,12 +1468,15 @@ bool partition_info::check_range_constants(THD *thd) part_column_list_val *UNINIT_VAR(current_largest_col_val); uint num_column_values= part_field_list.elements; uint size_entries= sizeof(part_column_list_val) * num_column_values; - range_col_array= (part_column_list_val*) thd->calloc(num_parts * - size_entries); - if (unlikely(range_col_array == NULL)) + if (alloc) { - mem_alloc_error(num_parts * size_entries); - goto end; + range_col_array= (part_column_list_val*) thd->calloc(num_parts * + size_entries); + if (unlikely(range_col_array == NULL)) + { + mem_alloc_error(num_parts * size_entries); + goto end; + } } loc_range_col_array= range_col_array; i= 0; @@ -1018,11 +1509,14 @@ bool partition_info::check_range_constants(THD *thd) longlong part_range_value; bool signed_flag= !part_expr->unsigned_flag; - range_int_array= (longlong*) thd->alloc(num_parts * sizeof(longlong)); - if (unlikely(range_int_array == NULL)) + if (alloc) { - mem_alloc_error(num_parts * sizeof(longlong)); - goto end; + range_int_array= (longlong*) thd->alloc(num_parts * sizeof(longlong)); + if (unlikely(range_int_array == NULL)) + { + mem_alloc_error(num_parts * sizeof(longlong)); + goto end; + } } i= 0; do @@ -1386,6 +1880,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, uint i, tot_partitions; bool result= TRUE, table_engine_set; const char *same_name; + uint32 hist_parts= 0; + uint32 now_parts= 0; DBUG_ENTER("partition_info::check_partition_info"); DBUG_ASSERT(default_engine_type != partition_hton); @@ -1427,7 +1923,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, } if (unlikely(is_sub_partitioned() && (!(part_type == RANGE_PARTITION || - part_type == LIST_PARTITION)))) + part_type == LIST_PARTITION || + part_type == VERSIONING_PARTITION)))) { /* Only RANGE and LIST partitioning can be subpartitioned */ my_error(ER_SUBPARTITION_ERROR, MYF(0)); @@ -1489,6 +1986,19 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name); goto end; } + + if (part_type == VERSIONING_PARTITION) + { + DBUG_ASSERT(vers_info); + if (num_parts < 2 || !vers_info->now_part) + { + DBUG_ASSERT(info && info->alias); + my_error(ER_VERS_WRONG_PARTS, MYF(0), info->alias); + goto end; + } + DBUG_ASSERT(vers_info->initialized(false)); + DBUG_ASSERT(num_parts == partitions.elements); + } i= 0; { List_iterator<partition_element> part_it(partitions); @@ -1569,6 +2079,18 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, } } } + if (part_type == VERSIONING_PARTITION) + { + if (part_elem->type() == partition_element::VERSIONING) + { + hist_parts++; + } + else + { + DBUG_ASSERT(part_elem->type() == partition_element::AS_OF_NOW); + now_parts++; + } + } } while (++i < num_parts); if (!table_engine_set && num_parts_not_set != 0 && @@ -1600,12 +2122,29 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, if (add_or_reorg_part) { - if (unlikely((part_type == RANGE_PARTITION && + if (unlikely(((part_type == RANGE_PARTITION || part_type == VERSIONING_PARTITION) && check_range_constants(thd)) || (part_type == LIST_PARTITION && check_list_constants(thd)))) goto end; } + + if (hist_parts > 1) + { + if (vers_info->limit == 0 && vers_info->interval == 0) + { + push_warning_printf(thd, + Sql_condition::WARN_LEVEL_WARN, + WARN_VERS_PARAMETERS, + ER_THD(thd, WARN_VERS_PARAMETERS), + "no rotation condition for multiple `VERSIONING` partitions."); + } + } + if (now_parts > 1) + { + my_error(ER_VERS_WRONG_PARTS, MYF(0), info->alias); + goto end; + } result= FALSE; end: DBUG_RETURN(result); @@ -2815,6 +3354,81 @@ bool partition_info::has_same_partitioning(partition_info *new_part_info) } +static bool has_same_column_order(List<Create_field> *create_list, + Field** field_array) +{ + Field **f_ptr; + List_iterator_fast<Create_field> new_field_it; + Create_field *new_field= NULL; + new_field_it.init(*create_list); + + for (f_ptr= field_array; *f_ptr; f_ptr++) + { + while ((new_field= new_field_it++)) + { + if (new_field->field == *f_ptr) + break; + } + if (!new_field) + break; + } + + if (!new_field) + { + /* Not same order!*/ + return false; + } + return true; +} + +bool partition_info::vers_trx_id_to_ts(THD* thd, Field* in_trx_id, Field_timestamp& out_ts) +{ + DBUG_ASSERT(table); + handlerton *hton= plugin_hton(table->s->db_plugin); + DBUG_ASSERT(hton); + ulonglong trx_id= in_trx_id->val_int(); + MYSQL_TIME ts; + bool found= hton->vers_query_trx_id(thd, &ts, trx_id, VTQ_COMMIT_TS); + if (!found) + { + push_warning_printf(thd, + Sql_condition::WARN_LEVEL_WARN, + WARN_VERS_TRX_MISSING, + ER_THD(thd, WARN_VERS_TRX_MISSING), + trx_id); + return true; + } + out_ts.store_time_dec(&ts, 6); + return false; +} + + +/** + Check if the partitioning columns are in the same order as the given list. + + Used to see if INPLACE alter can be allowed or not. If the order is + different then the rows must be redistributed for KEY [sub]partitioning. + + @param[in] create_list Column list after ALTER TABLE. + @return true is same order as before ALTER TABLE, else false. +*/ +bool partition_info::same_key_column_order(List<Create_field> *create_list) +{ + /* Only need to check for KEY [sub] partitioning. */ + if (list_of_part_fields && !column_list) + { + if (!has_same_column_order(create_list, part_field_array)) + return false; + } + if (list_of_subpart_fields) + { + if (!has_same_column_order(create_list, subpart_field_array)) + return false; + } + return true; +} + + void partition_info::print_debug(const char *str, uint *value) { DBUG_ENTER("print_debug"); diff --git a/sql/partition_info.h b/sql/partition_info.h index 38a353c8507..a8b1b386240 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -22,6 +22,7 @@ #include "sql_class.h" #include "partition_element.h" +#include "sql_partition.h" class partition_info; struct TABLE_LIST; @@ -34,6 +35,45 @@ typedef int (*get_subpart_id_func)(partition_info *part_info, struct st_ddl_log_memory_entry; +struct Vers_part_info : public Sql_alloc +{ + Vers_part_info() : + interval(0), + limit(0), + now_part(NULL), + hist_part(NULL), + stat_serial(0) + { + } + Vers_part_info(Vers_part_info &src) : + interval(src.interval), + limit(src.limit), + now_part(NULL), + hist_part(NULL), + stat_serial(src.stat_serial) + { + } + bool initialized(bool fully= true) + { + if (now_part) + { + DBUG_ASSERT(now_part->id != UINT32_MAX); + DBUG_ASSERT(now_part->type() == partition_element::AS_OF_NOW); + DBUG_ASSERT(!fully || (bool) hist_part); + DBUG_ASSERT(!hist_part || ( + hist_part->id != UINT32_MAX && + hist_part->type() == partition_element::VERSIONING)); + return true; + } + return false; + } + my_time_t interval; + ulonglong limit; + partition_element *now_part; + partition_element *hist_part; + ulonglong stat_serial; +}; + class partition_info : public Sql_alloc { public: @@ -143,6 +183,8 @@ public: part_column_list_val *range_col_array; part_column_list_val *list_col_array; }; + + Vers_part_info *vers_info; /******************************************** * INTERVAL ANALYSIS @@ -302,7 +344,7 @@ public: const char *find_duplicate_field(); char *find_duplicate_name(); bool check_engine_mix(handlerton *engine_type, bool default_engine); - bool check_range_constants(THD *thd); + bool check_range_constants(THD *thd, bool alloc= true); bool check_list_constants(THD *thd); bool check_partition_info(THD *thd, handlerton **eng_type, handler *file, HA_CREATE_INFO *info, @@ -332,6 +374,28 @@ public: size_t file_name_size, uint32 *part_id); void report_part_expr_error(bool use_subpart_expr); bool has_same_partitioning(partition_info *new_part_info); + inline bool is_partition_used(uint part_id) const + { + return bitmap_is_set(&read_partitions, part_id); + } + inline bool is_partition_locked(uint part_id) const + { + return bitmap_is_set(&lock_partitions, part_id); + } + inline uint num_partitions_used() + { + return bitmap_bits_set(&read_partitions); + } + inline uint get_first_used_partition() const + { + return bitmap_get_first_set(&read_partitions); + } + inline uint get_next_used_partition(uint part_id) const + { + return bitmap_get_next_set(&read_partitions, part_id); + } + bool same_key_column_order(List<Create_field> *create_list); + private: static int list_part_cmp(const void* a, const void* b); bool set_up_default_partitions(THD *thd, handler *file, HA_CREATE_INFO *info, @@ -342,10 +406,167 @@ private: uint start_no); char *create_default_subpartition_name(THD *thd, uint subpart_no, const char *part_name); + // FIXME: prune_partition_bitmaps() is duplicate of set_read_partitions() bool prune_partition_bitmaps(TABLE_LIST *table_list); bool add_named_partition(const char *part_name, uint length); public: + bool set_read_partitions(List<char> *partition_names); bool has_unique_name(partition_element *element); + + bool vers_init_info(THD *thd); + bool vers_set_interval(const INTERVAL &i); + bool vers_set_limit(ulonglong limit); + partition_element* vers_part_rotate(THD *thd); + bool vers_set_expression(THD *thd, partition_element *el, MYSQL_TIME &t); + bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */ + bool vers_setup_stats(THD *thd, bool is_create_table_ind); /* Stage 2. */ + bool vers_scan_min_max(THD *thd, partition_element *part); + void vers_update_col_vals(THD *thd, partition_element *el0, partition_element *el1); + + partition_element *vers_hist_part() + { + DBUG_ASSERT(table && table->s); + DBUG_ASSERT(vers_info && vers_info->initialized()); + DBUG_ASSERT(table->s->hist_part_id != UINT32_MAX); + if (table->s->hist_part_id == vers_info->hist_part->id) + return vers_info->hist_part; + + List_iterator<partition_element> it(partitions); + partition_element *el; + while ((el= it++)) + { + DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL); + if (el->type() == partition_element::VERSIONING && + el->id == table->s->hist_part_id) + { + vers_info->hist_part= el; + return vers_info->hist_part; + } + } + DBUG_ASSERT(0); + return NULL; + } + partition_element *get_partition(uint part_id) + { + List_iterator<partition_element> it(partitions); + partition_element *el; + while ((el= it++)) + { + if (el->id == part_id) + return el; + } + return NULL; + } + bool vers_limit_exceed(partition_element *part= NULL) + { + DBUG_ASSERT(vers_info); + if (!vers_info->limit) + return false; + if (!part) + { + DBUG_ASSERT(vers_info->initialized()); + part= vers_hist_part(); + } + // TODO: cache thread-shared part_recs and increment on INSERT + return table->file->part_records(part) >= vers_info->limit; + } + Vers_min_max_stats& vers_stat_trx(stat_trx_field fld, uint32 part_element_id) + { + DBUG_ASSERT(table && table->s && table->s->stat_trx); + Vers_min_max_stats* res= table->s->stat_trx[part_element_id * num_columns + fld]; + DBUG_ASSERT(res); + return *res; + } + Vers_min_max_stats& vers_stat_trx(stat_trx_field fld, partition_element *part) + { + DBUG_ASSERT(part); + return vers_stat_trx(fld, part->id); + } + bool vers_interval_exceed(my_time_t max_time, partition_element *part= NULL) + { + DBUG_ASSERT(vers_info); + if (!vers_info->interval) + return false; + if (!part) + { + DBUG_ASSERT(vers_info->initialized()); + part= vers_hist_part(); + } + my_time_t min_time= vers_stat_trx(STAT_TRX_END, part).min_time(); + return max_time - min_time > vers_info->interval; + } + bool vers_interval_exceed(partition_element *part) + { + return vers_interval_exceed(vers_stat_trx(STAT_TRX_END, part).max_time(), part); + } + bool vers_interval_exceed() + { + return vers_interval_exceed(vers_hist_part()); + } + bool vers_trx_id_to_ts(THD *thd, Field *in_trx_id, Field_timestamp &out_ts); + void vers_update_stats(THD *thd, partition_element *el) + { + DBUG_ASSERT(vers_info && vers_info->initialized()); + DBUG_ASSERT(table && table->s); + DBUG_ASSERT(el && el->type() == partition_element::VERSIONING); + bool updated; + mysql_rwlock_wrlock(&table->s->LOCK_stat_serial); + el->empty= false; + if (table->versioned_by_engine()) + { + // transaction is not yet pushed to VTQ, so we use now-time + my_time_t end_ts= my_time(0); + + uchar buf[8]; + Field_timestampf fld(buf, NULL, 0, Field::NONE, &table->vers_end_field()->field_name, NULL, 6); + fld.store_TIME(end_ts, 0); + updated= + vers_stat_trx(STAT_TRX_END, el->id).update(&fld); + } + else + { + updated= + vers_stat_trx(STAT_TRX_END, el->id).update(table->vers_end_field()); + } + if (updated) + table->s->stat_serial++; + mysql_rwlock_unlock(&table->s->LOCK_stat_serial); + if (updated) + { + vers_update_col_vals(thd, + el->id > 0 ? get_partition(el->id - 1) : NULL, + el); + } + } + void vers_update_stats(THD *thd, uint part_id) + { + DBUG_ASSERT(vers_info && vers_info->initialized()); + if (part_id < vers_info->now_part->id) + vers_update_stats(thd, get_partition(part_id)); + } + bool vers_update_range_constants(THD *thd) + { + DBUG_ASSERT(vers_info && vers_info->initialized()); + DBUG_ASSERT(table && table->s); + + mysql_rwlock_rdlock(&table->s->LOCK_stat_serial); + if (vers_info->stat_serial == table->s->stat_serial) + { + mysql_rwlock_unlock(&table->s->LOCK_stat_serial); + return false; + } + + bool result= false; + for (uint i= 0; i < num_columns; ++i) + { + Field *f= part_field_array[i]; + bitmap_set_bit(f->table->write_set, f->field_index); + } + result= check_range_constants(thd, false); + vers_info->stat_serial= table->s->stat_serial; + mysql_rwlock_unlock(&table->s->LOCK_stat_serial); + return result; + } }; uint32 get_next_partition_id_range(struct st_partition_iter* part_iter); diff --git a/sql/set_var.h b/sql/set_var.h index d0143e1e524..48990755ca0 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -224,6 +224,13 @@ private: virtual bool session_update(THD *thd, set_var *var) = 0; virtual bool global_update(THD *thd, set_var *var) = 0; +public: + virtual bool option_updated() + { + DBUG_ASSERT(false); + return true; + } + protected: /** A pointer to a value of the variable for SHOW. diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index e414a674af6..a5b8a639b2f 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7786,3 +7786,110 @@ ER_COMPRESSED_COLUMN_USED_AS_KEY eng "Compressed column '%-.192s' can't be used in key specification" ER_UNKNOWN_COMPRESSION_METHOD eng "Unknown compression method: %s" + +# MariaDB error numbers related to System Versioning + +ER_VERSIONING_REQUIRED + eng "System Versioning required: %s" + +ER_VERS_READONLY_FIELD + eng "System field %`s is read-only" + +ER_UPDATE_INFO_WITH_SYSTEM_VERSIONING + eng "Rows matched: %ld Changed: %ld Inserted: %ld Warnings: %ld" + +ER_VERS_FIELD_WRONG_TYPE + eng "%`s must be of type %`s for versioned table %`s" + +ER_VERS_WRONG_PARAMS + eng "Wrong parameters %s" + +ER_VERS_ENGINE_UNSUPPORTED + eng "Engine does not support System Versioning for %`s" + +ER_VERS_RANGE_UNITS_MISMATCH + eng "Range units mismatch" + +ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY + eng "Attempt to read unversioned field %`s in historical query" + +ER_PARTITION_WRONG_TYPE + eng "Wrong partition type, expected type: %`s" + +WARN_VERS_PART_FULL + eng "Using full partition %`s, need more VERSIONING partitions!" + +WARN_VERS_PARAMETERS + eng "Maybe missing parameters: %s" + +WARN_VERS_PART_ROTATION + eng "Switching from partition %`s to %`s" + +WARN_VERS_TRX_MISSING + eng "VTQ missing transaction ID %lu" + +WARN_VERS_PART_NON_HISTORICAL + eng "Partition %`s contains non-historical data" + +ER_VERS_NOT_ALLOWED + eng "%`s is not allowed for versioned table" + +ER_VERS_RANGE_PROHIBITED + eng "SYSTEM_TIME range selector is prohibited" + +ER_VERS_VIEW_PROHIBITED + eng "Creating VIEW %`s is prohibited!" + +ER_VERS_DERIVED_PROHIBITED + eng "Derived table is prohibited!" + +ER_VERS_UNUSED_CLAUSE + eng "Unused clause: '%s'" + +WARN_VERS_ALIAS_TOO_LONG + eng "Auto generated alias for `%s.%s` is too long; using `%s`" + +ER_VERS_VTMD_ERROR + eng "VTMD error: %s" + +ER_NOT_ALLOWED + eng "for %`s: not allowed '%s'" + +ER_VERS_DIFFERENT_TABLES + eng "for %`s: system fields selected from different tables" + +ER_VERS_NO_COLS_DEFINED + eng "for %`s: no columns defined '%s'" + +ER_VERS_NOT_VERSIONED + eng "for %`s: table is not versioned" + +ER_MISSING + eng "for %`s: missing '%s'" + +ER_MISMATCH + eng "for %`s: mismatch '%s' and '%s'" + +ER_PART_WRONG_VALUE + eng "for partitioned %`s: wrong value for '%s'" + +ER_VERS_WRONG_PARTS + eng "Wrong partitions consistency for %`s: must have at least one 'VERSIONING' and exactly one last 'AS OF NOW'" + +ER_VERS_HISTORY_LOCK + eng "Versioned SELECT write-locking of history rows" + +ER_VERS_NO_TRX_ID + eng "TRX_ID %lu not found in VTQ" + +ER_WRONG_TABLESPACE_NAME 42000 + eng "Incorrect tablespace name `%-.192s`" + +ER_VERS_ALTER_SYSTEM_FIELD + eng "Can not change system versioning field '%s'" + +ER_VERS_SYS_FIELD_NOT_HIDDEN + eng "System versioning field '%s' is not hidden" + +ER_NOT_LOG_TABLE + eng "Table `%s.%s` is not a log table" diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index 342673bf619..cf890f316bc 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -238,6 +238,10 @@ void sp_cache_flush_obsolete(sp_cache **cp, sp_head **sp) } } +void sp_cache_flush(sp_cache *cp, sp_head *sp) +{ + cp->remove(sp); +} /** Return the current global version of the cache. diff --git a/sql/sp_cache.h b/sql/sp_cache.h index a045ff5d3c5..59e0fc186dd 100644 --- a/sql/sp_cache.h +++ b/sql/sp_cache.h @@ -60,6 +60,7 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp); sp_head *sp_cache_lookup(sp_cache **cp, const Database_qualified_name *name); void sp_cache_invalidate(); void sp_cache_flush_obsolete(sp_cache **cp, sp_head **sp); +void sp_cache_flush(sp_cache *cp, sp_head *sp); ulong sp_cache_version(); void sp_cache_enforce_limit(sp_cache *cp, ulong upper_limit_for_elements); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index df9471880d9..1fb780528c8 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2530,6 +2530,7 @@ sp_head::restore_thd_mem_root(THD *thd) Item *flist= free_list; // The old list set_query_arena(thd); // Get new free_list and mem_root state= STMT_INITIALIZED_FOR_SP; + is_stored_procedure= true; DBUG_PRINT("info", ("mem_root %p returned from thd mem root %p", &mem_root, &thd->mem_root)); diff --git a/sql/sp_head.h b/sql/sp_head.h index 734c0dea3e3..815a68c922f 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -209,7 +209,7 @@ public: ulong sp_cache_version() const { return m_sp_cache_version; } /** Set the value of the SP cache version. */ - void set_sp_cache_version(ulong version_arg) + void set_sp_cache_version(ulong version_arg) const { m_sp_cache_version= version_arg; } @@ -231,7 +231,7 @@ private: is obsolete and should not be used -- sp_cache_flush_obsolete() will purge it. */ - ulong m_sp_cache_version; + mutable ulong m_sp_cache_version; Stored_program_creation_ctx *m_creation_ctx; /** Boolean combination of (1<<flag), where flag is a member of diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7e31d448bdf..4b9c0e325a3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -170,6 +170,11 @@ TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { { C_STRING_WITH_LEN("Trigger_priv") }, { C_STRING_WITH_LEN("enum('N','Y')") }, { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Delete_versioning_rows_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } } }; @@ -695,9 +700,9 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, const char *username, #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ #define NORMAL_HANDSHAKE_SIZE 6 -#define ROLE_ASSIGN_COLUMN_IDX 43 -#define DEFAULT_ROLE_COLUMN_IDX 44 -#define MAX_STATEMENT_TIME_COLUMN_IDX 45 +#define ROLE_ASSIGN_COLUMN_IDX 44 +#define DEFAULT_ROLE_COLUMN_IDX 45 +#define MAX_STATEMENT_TIME_COLUMN_IDX 46 /* various flags valid for ACL_USER */ #define IS_ROLE (1L << 0) @@ -2013,6 +2018,9 @@ static bool acl_load(THD *thd, const Grant_tables& tables) if (user_table.num_fields() <= 38 && (user.access & SUPER_ACL)) user.access|= TRIGGER_ACL; + if (user_table.num_fields() <= 46 && (user.access & DELETE_ACL)) + user.access|= DELETE_VERSIONING_ROWS_ACL; + user.sort= get_sort(2, user.host.hostname, user.user.str); user.hostname_length= safe_strlen(user.host.hostname); user.user_resource.user_conn= 0; @@ -8465,13 +8473,14 @@ static const char *command_array[]= "ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT", "CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE", "ALTER ROUTINE", - "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE" + "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE", + "DELETE VERSIONING ROWS" }; static uint command_lengths[]= { 6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9, - 14, 13, 11, 5, 7, 17 + 14, 13, 11, 5, 7, 17, 22, }; diff --git a/sql/sql_acl.h b/sql/sql_acl.h index e3dba20422d..49a7844108e 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -49,6 +49,7 @@ #define EVENT_ACL (1UL << 26) #define TRIGGER_ACL (1UL << 27) #define CREATE_TABLESPACE_ACL (1UL << 28) +#define DELETE_VERSIONING_ROWS_ACL (1UL << 29) /* don't forget to update 1. static struct show_privileges_st sys_privileges[] @@ -62,12 +63,13 @@ (UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL | \ LOCK_TABLES_ACL | EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | \ - CREATE_PROC_ACL | ALTER_PROC_ACL | EVENT_ACL | TRIGGER_ACL) + CREATE_PROC_ACL | ALTER_PROC_ACL | EVENT_ACL | TRIGGER_ACL | \ + DELETE_VERSIONING_ROWS_ACL) #define TABLE_ACLS \ (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_VIEW_ACL | \ - SHOW_VIEW_ACL | TRIGGER_ACL) + SHOW_VIEW_ACL | TRIGGER_ACL | DELETE_VERSIONING_ROWS_ACL) #define COL_ACLS \ (SELECT_ACL | INSERT_ACL | UPDATE_ACL | REFERENCES_ACL) @@ -85,7 +87,7 @@ CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \ EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | CREATE_PROC_ACL | \ ALTER_PROC_ACL | CREATE_USER_ACL | EVENT_ACL | TRIGGER_ACL | \ - CREATE_TABLESPACE_ACL) + CREATE_TABLESPACE_ACL | DELETE_VERSIONING_ROWS_ACL) #define DEFAULT_CREATE_PROC_ACLS \ (ALTER_PROC_ACL | EXECUTE_ACL) @@ -117,31 +119,37 @@ CREATE_PROC_ACL | ALTER_PROC_ACL ) #define DB_CHUNK4 (EXECUTE_ACL) #define DB_CHUNK5 (EVENT_ACL | TRIGGER_ACL) +#define DB_CHUNK6 (DELETE_VERSIONING_ROWS_ACL) #define fix_rights_for_db(A) (((A) & DB_CHUNK0) | \ (((A) << 4) & DB_CHUNK1) | \ (((A) << 6) & DB_CHUNK2) | \ (((A) << 9) & DB_CHUNK3) | \ - (((A) << 2) & DB_CHUNK4))| \ - (((A) << 9) & DB_CHUNK5) + (((A) << 2) & DB_CHUNK4) | \ + (((A) << 9) & DB_CHUNK5) | \ + (((A) << 10) & DB_CHUNK6)) #define get_rights_for_db(A) (((A) & DB_CHUNK0) | \ (((A) & DB_CHUNK1) >> 4) | \ (((A) & DB_CHUNK2) >> 6) | \ (((A) & DB_CHUNK3) >> 9) | \ - (((A) & DB_CHUNK4) >> 2))| \ - (((A) & DB_CHUNK5) >> 9) + (((A) & DB_CHUNK4) >> 2) | \ + (((A) & DB_CHUNK5) >> 9) | \ + (((A) & DB_CHUNK6) >> 10)) #define TBL_CHUNK0 DB_CHUNK0 #define TBL_CHUNK1 DB_CHUNK1 #define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL) #define TBL_CHUNK3 TRIGGER_ACL +#define TBL_CHUNK4 (DELETE_VERSIONING_ROWS_ACL) #define fix_rights_for_table(A) (((A) & TBL_CHUNK0) | \ (((A) << 4) & TBL_CHUNK1) | \ (((A) << 11) & TBL_CHUNK2) | \ - (((A) << 15) & TBL_CHUNK3)) + (((A) << 15) & TBL_CHUNK3) | \ + (((A) << 16) & TBL_CHUNK4)) #define get_rights_for_table(A) (((A) & TBL_CHUNK0) | \ (((A) & TBL_CHUNK1) >> 4) | \ (((A) & TBL_CHUNK2) >> 11) | \ - (((A) & TBL_CHUNK3) >> 15)) + (((A) & TBL_CHUNK3) >> 15) | \ + (((A) & TBL_CHUNK4) >> 16)) #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8)) #define get_rights_for_column(A) (((A) & 7) | ((A) >> 8)) #define fix_rights_for_procedure(A) ((((A) << 18) & EXECUTE_ACL) | \ @@ -175,6 +183,7 @@ enum mysql_db_table_field MYSQL_DB_FIELD_EXECUTE_PRIV, MYSQL_DB_FIELD_EVENT_PRIV, MYSQL_DB_FIELD_TRIGGER_PRIV, + MYSQL_DB_FIELD_DELETE_VERSIONING_ROWS_PRIV, MYSQL_DB_FIELD_COUNT }; diff --git a/sql/sql_alter.h b/sql/sql_alter.h index a37d96934ea..39458c45b80 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -100,6 +100,22 @@ public: enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; + bool vers_data_modifying() const + { + return flags & ( + ALTER_ADD_COLUMN | + ALTER_DROP_COLUMN | + ALTER_CHANGE_COLUMN | + ALTER_DROP_PARTITION | + ALTER_COALESCE_PARTITION | + ALTER_REORGANIZE_PARTITION | + ALTER_TABLE_REORG | + ALTER_REMOVE_PARTITIONING | + ALTER_EXCHANGE_PARTITION | + ALTER_TRUNCATE_PARTITION | + ALTER_COLUMN_ORDER); + } + /** The different values of the ALGORITHM clause. Describes which algorithm to use when altering the table. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7fd6599df51..99971a53a3c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5712,6 +5712,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, if (field_to_set) { TABLE *table= field_to_set->table; + DBUG_ASSERT(table); if (thd->mark_used_columns == MARK_COLUMNS_READ) bitmap_set_bit(table->read_set, field_to_set->field_index); else @@ -6389,6 +6390,19 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, bool is_using_column_1; if (!(nj_col_1= it_1.get_or_create_column_ref(thd, leaf_1))) goto err; + + if (nj_col_1->field() && nj_col_1->field()->vers_sys_field()) + continue; + + if (table_ref_1->is_view() && table_ref_1->table->versioned()) + { + Item *item= nj_col_1->view_field->item; + DBUG_ASSERT(item->type() == Item::FIELD_ITEM); + Item_field *item_field= (Item_field *)item; + if (item_field->field->vers_sys_field()) + continue; + } + field_name_1= nj_col_1->name(); is_using_column_1= using_fields && test_if_string_in_list(field_name_1->str, using_fields); @@ -7083,7 +7097,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, thd->lex->current_select->is_item_list_lookup= 0; /* - To prevent fail on forward lookup we fill it with zerows, + To prevent fail on forward lookup we fill it with zeroes, then if we got pointer on zero after find_item_in_list we will know that it is forward lookup. @@ -7483,6 +7497,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, Field_iterator_table_ref field_iterator; bool found; char name_buff[SAFE_NAME_LEN+1]; + ulong vers_hide= thd->variables.vers_hide; DBUG_ENTER("insert_fields"); DBUG_PRINT("arena", ("stmt arena: %p",thd->stmt_arena)); @@ -7586,6 +7601,52 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, if (!(item= field_iterator.create_item(thd))) DBUG_RETURN(TRUE); + if (item->type() == Item::FIELD_ITEM) + { + Item_field *f= static_cast<Item_field *>(item); + DBUG_ASSERT(f->field); + uint32 fl= f->field->flags; + bool sys_field= fl & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG); + SELECT_LEX *slex= thd->lex->current_select; + TABLE *table= f->field->table; + DBUG_ASSERT(table && table->pos_in_table_list); + TABLE_LIST *tl= table->pos_in_table_list; + vers_range_type_t vers_type= tl->vers_conditions.type; + + enum_sql_command sql_command= thd->lex->sql_command; + unsigned int create_options= thd->lex->create_info.options; + + if ( + sql_command == SQLCOM_CREATE_TABLE ? + sys_field && !(create_options & HA_VERSIONED_TABLE) : ( + sys_field ? + (sql_command == SQLCOM_CREATE_VIEW || + slex->nest_level > 0 || + vers_hide == VERS_HIDE_FULL || + ((fl & HIDDEN_FLAG) && ( + vers_hide == VERS_HIDE_IMPLICIT || + (vers_hide == VERS_HIDE_AUTO && ( + vers_type == FOR_SYSTEM_TIME_UNSPECIFIED || + vers_type == FOR_SYSTEM_TIME_AS_OF))))) : + (fl & HIDDEN_FLAG))) + { + continue; + } + } + else if (item->type() == Item::REF_ITEM) + { + Item *i= item; + while (i->type() == Item::REF_ITEM) + i= *((Item_ref *)i)->ref; + if (i->type() == Item::FIELD_ITEM) + { + Item_field *f= (Item_field *)i; + DBUG_ASSERT(f->field); + if (f->field->flags & HIDDEN_FLAG) + continue; + } + } + /* cache the table for the Item_fields inserted by expanding stars */ if (item->type() == Item::FIELD_ITEM && tables->cacheable_table) ((Item_field *)item)->cached_table= tables; @@ -7980,6 +8041,13 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN), rfield->field_name.str, table->s->table_name.str); } + if (table->versioned() && rfield->vers_sys_field() && + !ignore_errors) + { + my_error(ER_VERS_READONLY_FIELD, MYF(0), rfield->field_name.str); + goto err; + } + if (rfield->stored_in_db() && (value->save_in_field(rfield, 0)) < 0 && !ignore_errors) { @@ -8020,7 +8088,7 @@ void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *table) Field** field= table->field_to_fill(); /* True if we have NOT NULL fields and BEFORE triggers */ - if (field != table->field) + if (field != table->field && field != table->non_generated_field) { List_iterator_fast<Item> it(items); Item *item; @@ -8227,6 +8295,13 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, } } + if (table->versioned() && field->vers_sys_field() && + !ignore_errors) + { + my_error(ER_VERS_READONLY_FIELD, MYF(0), field->field_name.str); + goto err; + } + if (use_value) value->save_val(field); else @@ -8478,7 +8553,6 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) { List_iterator<Item_func_match> li(*(select_lex->ftfunc_list)); Item_func_match *ifm; - DBUG_PRINT("info",("Performing FULLTEXT search")); while ((ifm=li++)) ifm->init_search(thd, no_order); @@ -8667,10 +8741,31 @@ open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup) if ((table= open_ltable(thd, one_table, one_table->lock_type, flags))) { - DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_LOG); - /* Make sure all columns get assigned to a default value */ - table->use_all_columns(); - DBUG_ASSERT(table->s->no_replicate); + if (table->s->table_category == TABLE_CATEGORY_LOG) + { + /* Make sure all columns get assigned to a default value */ + table->use_all_columns(); + DBUG_ASSERT(table->s->no_replicate); + } + else + { + my_error(ER_NOT_LOG_TABLE, MYF(0), table->s->db.str, table->s->table_name.str); + int error= 0; + if (table->current_lock != F_UNLCK) + { + table->current_lock= F_UNLCK; + error= table->file->ha_external_lock(thd, F_UNLCK); + } + if (error) + table->file->print_error(error, MYF(0)); + else + { + tc_release_table(table); + thd->reset_open_tables_state(thd); + thd->restore_backup_open_tables_state(backup); + table= NULL; + } + } } else thd->restore_backup_open_tables_state(backup); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 889acc57b76..65d9afcf509 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -710,6 +710,11 @@ extern "C" void thd_kill_timeout(THD* thd) mysql_mutex_unlock(&thd->LOCK_thd_data); } +Time_zone * thd_get_timezone(THD * thd) +{ + DBUG_ASSERT(thd && thd->variables.time_zone); + return thd->variables.time_zone; +} THD::THD(my_thread_id id, bool is_wsrep_applier) :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION, @@ -3700,6 +3705,7 @@ void Query_arena::set_query_arena(Query_arena *set) mem_root= set->mem_root; free_list= set->free_list; state= set->state; + is_stored_procedure= set->is_stored_procedure; } @@ -4772,12 +4778,18 @@ extern "C" int thd_rpl_is_parallel(const MYSQL_THD thd) return thd->rgi_slave && thd->rgi_slave->is_parallel_exec; } +/* Returns high resolution timestamp for the start + of the current query. */ +extern "C" time_t thd_start_time(const MYSQL_THD thd) +{ + return thd->start_time; +} /* Returns high resolution timestamp for the start of the current query. */ extern "C" unsigned long long thd_start_utime(const MYSQL_THD thd) { - return thd->start_utime; + return thd->start_time * 1000000 + thd->start_time_sec_part; } @@ -7051,6 +7063,15 @@ static bool protect_against_unsafe_warning_flood(int unsafe_type) DBUG_RETURN(unsafe_warning_suppression_active[unsafe_type]); } +MYSQL_TIME THD::query_start_TIME() +{ + MYSQL_TIME res; + variables.time_zone->gmt_sec_to_TIME(&res, query_start()); + res.second_part= query_start_sec_part(); + time_zone_used= 1; + return res; +} + /** Auxiliary method used by @c binlog_query() to raise warnings. @@ -7670,3 +7691,16 @@ void Database_qualified_name::copy(MEM_ROOT *mem_root, #endif /* !defined(MYSQL_CLIENT) */ + + +Query_arena_stmt::Query_arena_stmt(THD *_thd) : + thd(_thd) +{ + arena= thd->activate_stmt_arena_if_needed(&backup); +} + +Query_arena_stmt::~Query_arena_stmt() +{ + if (arena) + thd->restore_active_arena(arena, &backup); +} diff --git a/sql/sql_class.h b/sql/sql_class.h index fda56c8cc3a..1ef3ca21471 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -702,6 +702,12 @@ typedef struct system_variables uint idle_write_transaction_timeout; uint column_compression_threshold; uint column_compression_zlib_level; + + st_vers_current_time vers_current_time; + my_bool vers_force; + ulong vers_hide; + my_bool vers_innodb_algorithm_simple; + ulong vers_alter_history; } SV; /** @@ -938,6 +944,11 @@ public: enum_state state; +protected: + friend class sp_head; + bool is_stored_procedure; + +public: /* We build without RTTI, so dynamic_cast can't be used. */ enum Type { @@ -945,7 +956,8 @@ public: }; Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) : - free_list(0), mem_root(mem_root_arg), state(state_arg) + free_list(0), mem_root(mem_root_arg), state(state_arg), + is_stored_procedure(state_arg == STMT_INITIALIZED_FOR_SP ? true : false) { INIT_ARENA_DBUG_INFO; } /* This constructor is used only when Query_arena is created as @@ -965,6 +977,8 @@ public: { return state == STMT_PREPARED || state == STMT_EXECUTED; } inline bool is_conventional() const { return state == STMT_CONVENTIONAL_EXECUTION; } + inline bool is_sp_execute() const + { return is_stored_procedure; } inline void* alloc(size_t size) { return alloc_root(mem_root,size); } inline void* calloc(size_t size) @@ -1009,6 +1023,22 @@ public: }; +class Query_arena_stmt +{ + THD *thd; + Query_arena backup; + Query_arena *arena; + +public: + Query_arena_stmt(THD *_thd); + ~Query_arena_stmt(); + bool arena_replaced() + { + return arena != NULL; + } +}; + + class Server_side_cursor; /** @@ -3287,6 +3317,7 @@ public: inline my_time_t query_start() { query_start_used=1; return start_time; } inline ulong query_start_sec_part() { query_start_sec_part_used=1; return start_time_sec_part; } + MYSQL_TIME query_start_TIME(); inline void set_current_time() { my_hrtime_t hrtime= my_hrtime(); @@ -4083,7 +4114,12 @@ public: Lex_input_stream *lip= &m_parser_state->m_lip; if (!yytext) { - if (!(yytext= lip->get_tok_start())) + if (lip->lookahead_token >= 0) + yytext= lip->get_tok_start_prev(); + else + yytext= lip->get_tok_start(); + + if (!yytext) yytext= ""; } /* Push an error into the error stack */ @@ -5712,6 +5748,12 @@ class multi_update :public select_result_interceptor /* Need this to protect against multiple prepare() calls */ bool prepared; + + // For System Versioning (may need to insert new fields to a table). + ha_rows updated_sys_ver; + + bool has_vers_fields; + public: multi_update(THD *thd_arg, TABLE_LIST *ut, List<TABLE_LIST> *leaves_list, List<Item> *fields, List<Item> *values, @@ -6229,6 +6271,24 @@ inline bool lex_string_eq(const LEX_CSTRING *a, return strcasecmp(a->str, b->str) != 0; } -#endif /* MYSQL_SERVER */ +class ScopedStatementReplication +{ +public: + ScopedStatementReplication(THD *thd) : thd(thd) + { + if (thd) + saved_binlog_format= thd->set_current_stmt_binlog_format_stmt(); + } + ~ScopedStatementReplication() + { + if (thd) + thd->restore_stmt_binlog_format(saved_binlog_format); + } +private: + enum_binlog_format saved_binlog_format; + THD *thd; +}; + +#endif /* MYSQL_SERVER */ #endif /* SQL_CLASS_INCLUDED */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index c880374f9ab..39502a6637c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -217,6 +217,13 @@ void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root, static bool record_should_be_deleted(THD *thd, TABLE *table, SQL_SELECT *sel, Explain_delete *explain) { + if (table->versioned()) + { + bool row_is_alive= table->vers_end_field()->is_max(); + if (table->pos_in_table_list->vers_conditions ? row_is_alive : !row_is_alive) + return false; + } + explain->tracker.on_record_read(); thd->inc_examined_row_count(1); if (table->vfield) @@ -230,6 +237,18 @@ static bool record_should_be_deleted(THD *thd, TABLE *table, SQL_SELECT *sel, } +inline +int TABLE::delete_row() +{ + if (!versioned_by_sql() || !vers_end_field()->is_max()) + return file->ha_delete_row(record[0]); + + store_record(this, record[1]); + vers_end_field()->set_time(); + return file->ha_update_row(record[1], record[0]); +} + + /** Implement DELETE SQL word. @@ -273,6 +292,23 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (open_and_lock_tables(thd, table_list, TRUE, 0)) DBUG_RETURN(TRUE); + bool truncate_history= table_list->vers_conditions; + if (truncate_history) + { + TABLE *table= table_list->table; + DBUG_ASSERT(table); + + DBUG_ASSERT(!conds); + if (vers_setup_select(thd, table_list, &conds, select_lex)) + DBUG_RETURN(TRUE); + + // trx_sees() in InnoDB reads sys_trx_start + if (!table->versioned_by_sql()) { + DBUG_ASSERT(table_list->vers_conditions.type == FOR_SYSTEM_TIME_BEFORE); + bitmap_set_bit(table->read_set, table->vers_end_field()->field_index); + } + } + if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT)) DBUG_RETURN(TRUE); if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE)) @@ -365,7 +401,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, */ if (!with_select && !using_limit && const_cond_result && (!thd->is_current_stmt_binlog_format_row() && - !(table->triggers && table->triggers->has_delete_triggers()))) + !(table->triggers && table->triggers->has_delete_triggers())) + && !table->versioned_by_sql()) { /* Update the table->file->stats.records number */ table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -620,7 +657,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, delete_record= record_should_be_deleted(thd, table, select, explain); if (delete_record) { - if (table->triggers && + if (!truncate_history && table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)) { @@ -634,10 +671,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, break; } - if (!(error= table->file->ha_delete_row(table->record[0]))) + error= table->delete_row(); + if (!error) { deleted++; - if (table->triggers && + if (!truncate_history && table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) { @@ -723,6 +761,8 @@ cleanup: else errcode= query_error_code(thd, killed_status == NOT_KILLED); + ScopedStatementReplication scoped_stmt_rpl( + table->versioned_by_engine() ? thd : NULL); /* [binlog]: If 'handler::delete_all_rows()' was called and the storage engine does not inject the rows itself, we replicate @@ -1104,6 +1144,11 @@ int multi_delete::send_data(List<Item> &values) if (table->status & (STATUS_NULL_ROW | STATUS_DELETED)) continue; + if (table->versioned() && !table->vers_end_field()->is_max()) + { + continue; + } + table->file->position(table->record[0]); found++; @@ -1116,7 +1161,9 @@ int multi_delete::send_data(List<Item> &values) TRG_ACTION_BEFORE, FALSE)) DBUG_RETURN(1); table->status|= STATUS_DELETED; - if (!(error=table->file->ha_delete_row(table->record[0]))) + + error= table->delete_row(); + if (!error) { deleted++; if (!table->file->has_transactions()) @@ -1295,8 +1342,8 @@ int multi_delete::do_table_deletes(TABLE *table, SORT_INFO *sort_info, local_error= 1; break; } - - local_error= table->file->ha_delete_row(table->record[0]); + + local_error= table->delete_row(); if (local_error && !ignore) { table->file->print_error(local_error, MYF(0)); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 2df3af03af5..c8aa8702329 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -732,6 +732,131 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) cursor= cursor->next_local) cursor->outer_join|= JOIN_TYPE_OUTER; } + + // System Versioning: fix system fields of versioned derived table +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wformat-extra-args" + if ((thd->stmt_arena->is_stmt_prepare() || !thd->stmt_arena->is_stmt_execute()) + && sl->table_list.elements > 0) + { + // Similar logic as in mysql_create_view() + // Leading versioning table detected implicitly (first one selected) + TABLE_LIST *impli_table= NULL; + // Leading versioning table specified explicitly + // (i.e. if at least one system field is selected) + TABLE_LIST *expli_table= NULL; + const LString_i *impli_start, *impli_end; + Item_field *expli_start= NULL, *expli_end= NULL; + + for (TABLE_LIST *table= sl->table_list.first; table; table= table->next_local) + { + if (!table->table || !table->table->versioned()) + continue; + + const LString_i table_start= table->table->vers_start_field()->field_name; + const LString_i table_end= table->table->vers_end_field()->field_name; + if (!impli_table) + { + impli_table= table; + impli_start= &table_start; + impli_end= &table_end; + } + + /* Implicitly add versioning fields if needed */ + Item *item; + List_iterator_fast<Item> it(sl->item_list); + + DBUG_ASSERT(table->alias); + while ((item= it++)) + { + if (item->real_item()->type() != Item::FIELD_ITEM) + continue; + Item_field *fld= (Item_field*) (item->real_item()); + if (fld->table_name && 0 != my_strcasecmp(table_alias_charset, table->alias, fld->table_name)) + continue; + DBUG_ASSERT(fld->field_name.str); + if (table_start == fld->field_name) + { + if (expli_start) + { + my_printf_error( + ER_VERS_DERIVED_PROHIBITED, + "Derived table is prohibited: multiple start system fields `%s.%s`, `%s.%s` in query!", MYF(0), + expli_table->alias, + expli_start->field_name.str, + table->alias, + fld->field_name.str); + res= true; + goto exit; + } + if (expli_table) + { + if (expli_table != table) + { +expli_table_err: + my_printf_error( + ER_VERS_DERIVED_PROHIBITED, + "Derived table is prohibited: system fields from multiple tables %`s, %`s in query!", MYF(0), + expli_table->alias, + table->alias); + res= true; + goto exit; + } + } + else + expli_table= table; + expli_start= fld; + impli_end= &table_end; + } + else if (table_end == fld->field_name) + { + if (expli_end) + { + my_printf_error( + ER_VERS_DERIVED_PROHIBITED, + "Derived table is prohibited: multiple end system fields `%s.%s`, `%s.%s` in query!", MYF(0), + expli_table->alias, + expli_end->field_name.str, + table->alias, + fld->field_name.str); + res= true; + goto exit; + } + if (expli_table) + { + if (expli_table != table) + goto expli_table_err; + } + else + expli_table= table; + expli_end= fld; + impli_start= &table_start; + } + } // while ((item= it++)) + } // for (TABLE_LIST *table) + + if (expli_table) + impli_table= expli_table; + + if (impli_table) + { + Query_arena_stmt on_stmt_arena(thd); + if (!expli_start && (res= sl->vers_push_field(thd, impli_table, *impli_start))) + goto exit; + if (!expli_end && (res= sl->vers_push_field(thd, impli_table, *impli_end))) + goto exit; + + if (impli_table->vers_conditions) + { + sl->vers_export_outer= impli_table->vers_conditions; + } + else + sl->vers_import_outer= true; // FIXME: is needed? + } + } // if (sl->table_list.elements > 0) +#pragma GCC diagnostic pop + // System Versioning end } unit->derived= derived; diff --git a/sql/sql_error.h b/sql/sql_error.h index f8b8adc805a..b89af72cc44 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -1174,7 +1174,7 @@ public: void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi); -private: +protected: Warning_info *get_warning_info() { return m_wi_stack.front(); } const Warning_info *get_warning_info() const { return m_wi_stack.front(); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b12b470209c..9debb07aa9f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -222,7 +222,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(-1); } - if (values.elements != table->s->fields) + if (values.elements != table->vers_user_fields()) { my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L); DBUG_RETURN(-1); @@ -1033,6 +1033,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } } + if (table->versioned_by_sql()) + table->vers_update_fields(); + if ((res= table_list->view_check_option(thd, (values_list.elements == 1 ? 0 : @@ -1138,8 +1141,10 @@ values_loop_end: } else errcode= query_error_code(thd, thd->killed == NOT_KILLED); - - /* bug#22725: + + ScopedStatementReplication scoped_stmt_rpl( + table->versioned_by_engine() ? thd : NULL); + /* bug#22725: A query which per-row-loop can not be interrupted with KILLED, like INSERT, and that does not invoke stored @@ -1559,6 +1564,13 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, if (!table) table= table_list->table; + if (table->versioned_by_sql() && duplic == DUP_REPLACE) + { + // Additional memory may be required to create historical items. + if (table_list->set_insert_values(thd->mem_root)) + DBUG_RETURN(TRUE); + } + if (!select_insert) { Item *fake_conds= 0; @@ -1610,6 +1622,25 @@ static int last_uniq_key(TABLE *table,uint keynr) /* + Inserts one historical row to a table. + + Copies content of the row from table->record[1] to table->record[0], + sets Sys_end to now() and calls ha_write_row() . +*/ + +int vers_insert_history_row(TABLE *table) +{ + DBUG_ASSERT(table->versioned_by_sql()); + restore_record(table,record[1]); + + // Set Sys_end to now() + if (table->vers_end_field()->set_time()) + DBUG_ASSERT(0); + + return table->file->ha_write_row(table->record[0]); +} + +/* Write a record to table with optional deleting of conflicting records, invoke proper triggers if needed. @@ -1813,7 +1844,23 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) } if (error != HA_ERR_RECORD_IS_THE_SAME) + { info->updated++; + if (table->versioned()) + { + if (table->versioned_by_sql()) + { + store_record(table, record[2]); + if ((error= vers_insert_history_row(table))) + { + restore_record(table, record[2]); + goto err; + } + restore_record(table, record[2]); + } + info->copied++; + } + } else error= 0; /* @@ -1865,13 +1912,16 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) tables which have ON UPDATE but have no ON DELETE triggers, we just should not expose this fact to users by invoking ON UPDATE triggers. - */ - if (last_uniq_key(table,key_nr) && - !table->file->referenced_by_foreign_key() && - (!table->triggers || !table->triggers->has_delete_triggers())) + For system versioning wa also use path through delete since we would + save nothing through this cheating. + */ + if (last_uniq_key(table,key_nr) && + !table->file->referenced_by_foreign_key() && + (!table->triggers || !table->triggers->has_delete_triggers()) && + !table->versioned_by_sql()) { if ((error=table->file->ha_update_row(table->record[1], - table->record[0])) && + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) goto err; if (error != HA_ERR_RECORD_IS_THE_SAME) @@ -1891,9 +1941,29 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, TRUE)) goto before_trg_err; - if ((error=table->file->ha_delete_row(table->record[1]))) + + if (!table->versioned_by_sql()) + error= table->file->ha_delete_row(table->record[1]); + else + { + DBUG_ASSERT(table->insert_values); + store_record(table,insert_values); + restore_record(table,record[1]); + if (table->vers_end_field()->set_time()) + { + error= 1; + goto err; + } + error= table->file->ha_update_row(table->record[1], + table->record[0]); + restore_record(table,insert_values); + } + if (error) goto err; - info->deleted++; + if (!table->versioned_by_sql()) + info->deleted++; + else + info->updated++; if (!table->file->has_transactions()) thd->transaction.stmt.modified_non_trans_table= TRUE; if (table->triggers && @@ -1981,7 +2051,9 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, TABLE_LIST *t for (Field **field=entry->field ; *field ; field++) { if (!bitmap_is_set(write_set, (*field)->field_index) && - has_no_default_value(thd, *field, table_list)) + !(*field)->vers_sys_field() && + has_no_default_value(thd, *field, table_list) && + ((*field)->real_type() != MYSQL_TYPE_ENUM)) err=1; } return thd->abort_on_warning ? err : 0; @@ -3737,6 +3809,8 @@ int select_insert::send_data(List<Item> &values) DBUG_RETURN(0); thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields + if (table->versioned_by_sql()) + table->vers_update_fields(); store_values(values); if (table->default_field && table->update_default_fields(0, info.ignore)) DBUG_RETURN(1); @@ -3795,12 +3869,16 @@ int select_insert::send_data(List<Item> &values) void select_insert::store_values(List<Item> &values) { + DBUG_ENTER("select_insert::store_values"); + if (fields->elements) fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1, TRG_EVENT_INSERT); else fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(), values, 1, TRG_EVENT_INSERT); + + DBUG_VOID_RETURN; } bool select_insert::prepare_eof() @@ -4090,6 +4168,12 @@ static TABLE *create_table_from_items(THD *thd, alter_info->create_list.push_back(cr_field, thd->mem_root); } + if (create_info->vers_info.check_and_fix_implicit( + thd, alter_info, create_info, create_table->table_name)) + { + DBUG_RETURN(NULL); + } + DEBUG_SYNC(thd,"create_table_select_before_create"); /* Check if LOCK TABLES + CREATE OR REPLACE of existing normal table*/ diff --git a/sql/sql_insert.h b/sql/sql_insert.h index aea0dac6b0d..6efd680d188 100644 --- a/sql/sql_insert.h +++ b/sql/sql_insert.h @@ -37,6 +37,7 @@ void upgrade_lock_type_for_insert(THD *thd, thr_lock_type *lock_type, bool is_multi_insert); int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, TABLE_LIST *table_list); +int vers_insert_history_row(TABLE *table); int write_record(THD *thd, TABLE *table, COPY_INFO *info); void kill_delayed_threads(void); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ce43a45b872..e4b0877e2d7 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -33,9 +33,9 @@ #include "sql_signal.h" -void LEX::parse_error() +void LEX::parse_error(uint err_number) { - thd->parse_error(); + thd->parse_error(err_number); } @@ -771,6 +771,8 @@ void LEX::start(THD *thd_arg) frame_bottom_bound= NULL; win_spec= NULL; + vers_conditions.empty(); + is_lex_started= TRUE; DBUG_VOID_RETURN; } @@ -1339,6 +1341,8 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd) return WITH_CUBE_SYM; case ROLLUP_SYM: return WITH_ROLLUP_SYM; + case SYSTEM: + return WITH_SYSTEM_SYM; default: /* Save the token following 'WITH' @@ -1349,6 +1353,27 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd) return WITH; } break; + case FOR_SYM: + /* + * Additional look-ahead to resolve doubtful cases like: + * SELECT ... FOR UPDATE + * SELECT ... FOR SYSTEM_TIME ... . + */ + token= lex_one_token(yylval, thd); + lip->add_digest_token(token, yylval); + switch(token) { + case SYSTEM_TIME_SYM: + return FOR_SYSTEM_TIME_SYM; + default: + /* + Save the token following 'FOR_SYM' + */ + lip->lookahead_yylval= lip->yylval; + lip->yylval= NULL; + lip->lookahead_token= token; + return FOR_SYM; + } + break; default: break; } @@ -2185,6 +2210,7 @@ void st_select_lex::init_query() join= 0; having= prep_having= where= prep_where= 0; cond_pushed_into_where= cond_pushed_into_having= 0; + saved_where= 0; olap= UNSPECIFIED_OLAP_TYPE; having_fix_field= 0; context.select_lex= this; @@ -2261,6 +2287,8 @@ void st_select_lex::init_select() with_dep= 0; join= 0; lock_type= TL_READ_DEFAULT; + vers_import_outer= false; + vers_export_outer.empty(); } /* @@ -2997,8 +3025,7 @@ void Query_tables_list::destroy_query_tables_list() */ LEX::LEX() - : explain(NULL), - result(0), arena_for_set_stmt(0), mem_root_for_set_stmt(0), + : explain(NULL), result(0), arena_for_set_stmt(0), mem_root_for_set_stmt(0), option_type(OPT_DEFAULT), context_analysis_only(0), sphead(0), is_lex_started(0), limit_rows_examined_cnt(ULONGLONG_MAX) { @@ -7227,6 +7254,19 @@ int set_statement_var_if_exists(THD *thd, const char *var_name, } +Query_tables_backup::Query_tables_backup(THD* _thd) : + thd(_thd) +{ + thd->lex->reset_n_backup_query_tables_list(&backup); +} + + +Query_tables_backup::~Query_tables_backup() +{ + thd->lex->restore_backup_query_tables_list(&backup); +} + + bool LEX::sp_add_cfetch(THD *thd, const LEX_CSTRING *name) { uint offset; @@ -7357,3 +7397,25 @@ Item *LEX::make_item_func_replace(THD *thd, new (thd->mem_root) Item_func_replace_oracle(thd, org, find, replace) : new (thd->mem_root) Item_func_replace(thd, org, find, replace); } + + +bool SELECT_LEX::vers_push_field(THD *thd, TABLE_LIST *table, const LEX_CSTRING field_name) +{ + Item_field *fld= new (thd->mem_root) Item_field(thd, &context, + table->db, table->alias, &field_name); + if (!fld) + return true; + + item_list.push_back(fld); + + if (thd->lex->view_list.elements) + { + if (LEX_STRING *l= thd->make_lex_string(field_name.str, field_name.length)) + thd->lex->view_list.push_back(l); + else + return true; + } + + return false; +} + diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7619353d922..48afd2246bf 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -831,6 +831,7 @@ public: Item *prep_having;/* saved HAVING clause for prepared statement processing */ Item *cond_pushed_into_where; /* condition pushed into the select's WHERE */ Item *cond_pushed_into_having; /* condition pushed into the select's HAVING */ + Item *saved_where; /* Saved values of the WHERE and HAVING clauses*/ Item::cond_result cond_value, having_value; /* point on lex in which it was created, used in view subquery detection */ @@ -1018,6 +1019,12 @@ public: /* it is for correct printing SELECT options */ thr_lock_type lock_type; + /* System Versioning */ + vers_select_conds_t vers_export_outer; + bool vers_import_outer; + /* push new Item_field into item_list */ + bool vers_push_field(THD *thd, TABLE_LIST *table, const LEX_CSTRING field_name); + void init_query(); void init_select(); st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } @@ -1946,6 +1953,18 @@ private: }; +class Query_tables_backup +{ + THD *thd; + Query_tables_list backup; + +public: + Query_tables_backup(THD *_thd); + ~Query_tables_backup(); + const Query_tables_list& get() const { return backup; } +}; + + /* st_parsing_options contains the flags for constructions that are allowed in the current statement. @@ -2682,7 +2701,6 @@ struct LEX: public Query_tables_list private: Query_arena_memroot *arena_for_set_stmt; MEM_ROOT *mem_root_for_set_stmt; - void parse_error(); bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock, class sp_label **splabel); bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive); @@ -2696,6 +2714,7 @@ private: bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop); public: + void parse_error(uint err_number= ER_SYNTAX_ERROR); inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;} bool set_arena_for_set_stmt(Query_arena *backup); void reset_arena_for_set_stmt(Query_arena *backup); @@ -2946,6 +2965,9 @@ public: Window_frame_bound *frame_bottom_bound; Window_spec *win_spec; + /* System Versioning */ + vers_select_conds_t vers_conditions; + inline void free_set_stmt_mem_root() { DBUG_ASSERT(!is_arena_for_set_stmt()); @@ -3647,6 +3669,11 @@ public: bool add_grant_command(THD *thd, enum_sql_command sql_command_arg, stored_procedure_type type_arg); + + Vers_parse_info &vers_get_info() + { + return create_info.vers_info; + } }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2f886d91780..20c0ea7a528 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -112,6 +112,7 @@ #include "wsrep_mysqld.h" #include "wsrep_thd.h" +#include "vtmd.h" static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state, @@ -3165,6 +3166,11 @@ bool Sql_cmd_call::execute(THD *thd) if (do_execute_sp(thd, sp)) return true; + if (sp->sp_cache_version() == ULONG_MAX) + { + sp_cache_flush(thd->sp_proc_cache, sp); + } + /* Disable slow log for the above call(), if calls are disabled. Instead we will log the executed statements to the slow log. @@ -4015,7 +4021,6 @@ mysql_execute_command(THD *thd) copy. */ Alter_info alter_info(lex->alter_info, thd->mem_root); - if (thd->is_fatal_error) { /* If out of memory when creating a copy of alter_info. */ @@ -4043,6 +4048,7 @@ mysql_execute_command(THD *thd) */ if (!(create_info.used_fields & HA_CREATE_USED_ENGINE)) create_info.use_default_db_type(thd); + /* If we are using SET CHARSET without DEFAULT, add an implicit DEFAULT to not confuse old users. (This may change). @@ -4229,6 +4235,11 @@ mysql_execute_command(THD *thd) } else { + if (create_info.vers_info.check_and_fix_implicit( + thd, &alter_info, &create_info, create_table->table_name)) + { + goto end_with_restore_list; + } /* In STATEMENT format, we probably have to replicate also temporary tables, like mysql replication does. Also check if the requested @@ -6386,6 +6397,21 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) if (check_dependencies_in_with_clauses(lex->with_clauses_list)) return 1; + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE) + { + for (TABLE_LIST *table= all_tables; table; table= table->next_local) + { + if (table->vers_conditions) + { + VTMD_exists vtmd(*table); + if (vtmd.check_exists(thd)) + return 1; + if (vtmd.exists && vtmd.setup_select(thd)) + return 1; + } + } + } + if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0))) { if (lex->describe) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index fadd7009822..8784e1f1f62 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -67,6 +67,7 @@ #include "opt_range.h" // store_key_image_to_rec #include "sql_alter.h" // Alter_table_ctx #include "sql_select.h" +#include "sql_tablespace.h" // check_tablespace_name #include <algorithm> using std::max; @@ -87,6 +88,7 @@ static int get_partition_id_list_col(partition_info *, uint32 *, longlong *); static int get_partition_id_list(partition_info *, uint32 *, longlong *); static int get_partition_id_range_col(partition_info *, uint32 *, longlong *); static int get_partition_id_range(partition_info *, uint32 *, longlong *); +static int vers_get_partition_id(partition_info *, uint32 *, longlong *); static int get_part_id_charset_func_part(partition_info *, uint32 *, longlong *); static int get_part_id_charset_func_subpart(partition_info *, uint32 *); static int get_partition_id_hash_nosub(partition_info *, uint32 *, longlong *); @@ -1295,6 +1297,24 @@ static void set_up_partition_func_pointers(partition_info *part_info) part_info->get_subpartition_id= get_partition_id_hash_sub; } } + else if (part_info->part_type == VERSIONING_PARTITION) + { + part_info->get_part_partition_id= vers_get_partition_id; + if (part_info->list_of_subpart_fields) + { + if (part_info->linear_hash_ind) + part_info->get_subpartition_id= get_partition_id_linear_key_sub; + else + part_info->get_subpartition_id= get_partition_id_key_sub; + } + else + { + if (part_info->linear_hash_ind) + part_info->get_subpartition_id= get_partition_id_linear_hash_sub; + else + part_info->get_subpartition_id= get_partition_id_hash_sub; + } + } else /* LIST Partitioning */ { if (part_info->column_list) @@ -1335,6 +1355,10 @@ static void set_up_partition_func_pointers(partition_info *part_info) else part_info->get_partition_id= get_partition_id_list; } + else if (part_info->part_type == VERSIONING_PARTITION) + { + part_info->get_partition_id= vers_get_partition_id; + } else /* HASH partitioning */ { if (part_info->list_of_part_fields) @@ -1607,6 +1631,7 @@ bool fix_partition_func(THD *thd, TABLE *table, } } DBUG_ASSERT(part_info->part_type != NOT_A_PARTITION); + DBUG_ASSERT(part_info->part_type != VERSIONING_PARTITION || part_info->column_list); /* Partition is defined. We need to verify that partitioning function is correct. @@ -1639,6 +1664,9 @@ bool fix_partition_func(THD *thd, TABLE *table, const char *error_str; if (part_info->column_list) { + if (part_info->part_type == VERSIONING_PARTITION && + part_info->vers_setup_expression(thd)) + goto end; List_iterator<const char> it(part_info->part_field_list); if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE))) goto end; @@ -1662,6 +1690,12 @@ bool fix_partition_func(THD *thd, TABLE *table, if (unlikely(part_info->check_list_constants(thd))) goto end; } + else if (part_info->part_type == VERSIONING_PARTITION) + { + error_str= "SYSTEM_TIME"; + if (unlikely(part_info->check_range_constants(thd))) + goto end; + } else { DBUG_ASSERT(0); @@ -2182,6 +2216,20 @@ static int add_partition_values(String *str, partition_info *part_info, } while (++i < num_items); err+= str->append(')'); } + else if (part_info->part_type == VERSIONING_PARTITION) + { + switch (p_elem->type()) + { + case partition_element::AS_OF_NOW: + err+= str->append(STRING_WITH_LEN(" AS OF NOW")); + break; + case partition_element::VERSIONING: + err+= str->append(STRING_WITH_LEN(" VERSIONING")); + break; + default: + DBUG_ASSERT(0 && "wrong p_elem->type"); + } + } end: return err; } @@ -2275,13 +2323,32 @@ char *generate_partition_syntax(THD *thd, partition_info *part_info, else err+= str.append(STRING_WITH_LEN("HASH ")); break; + case VERSIONING_PARTITION: + err+= str.append(STRING_WITH_LEN("SYSTEM_TIME")); + break; default: DBUG_ASSERT(0); /* We really shouldn't get here, no use in continuing from here */ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); DBUG_RETURN(NULL); } - if (part_info->part_expr) + if (part_info->part_type == VERSIONING_PARTITION) + { + Vers_part_info *vers_info= part_info->vers_info; + DBUG_ASSERT(vers_info); + if (vers_info->interval) + { + err+= str.append(STRING_WITH_LEN("INTERVAL ")); + err+= str.append_ulonglong(vers_info->interval); + err+= str.append(STRING_WITH_LEN(" SECOND ")); + } + if (vers_info->limit) + { + err+= str.append(STRING_WITH_LEN("LIMIT ")); + err+= str.append_ulonglong(vers_info->limit); + } + } + else if (part_info->part_expr) { err+= str.append('('); part_info->part_expr->print_for_table_def(&str); @@ -3088,6 +3155,83 @@ int get_partition_id_range_col(partition_info *part_info, } +int vers_get_partition_id(partition_info *part_info, + uint32 *part_id, + longlong *func_value) +{ + DBUG_ENTER("vers_get_partition_id"); + DBUG_ASSERT(part_info); + Field *sys_trx_end= part_info->part_field_array[STAT_TRX_END]; + DBUG_ASSERT(sys_trx_end); + TABLE *table= part_info->table; + DBUG_ASSERT(table); + Vers_part_info *vers_info= part_info->vers_info; + DBUG_ASSERT(vers_info); + DBUG_ASSERT(vers_info->initialized()); + DBUG_ASSERT(sys_trx_end->table == table); + bool tmp_off= false; + if (!table->versioned() && table->file->native_versioned()) + { + // in copy_data_between_tables() versioning may be temporarily turned off + tmp_off= true; + table->s->versioned= true; + } + DBUG_ASSERT(table->versioned()); + DBUG_ASSERT(table->vers_end_field() == sys_trx_end); + + // new rows have NULL in sys_trx_end + if (sys_trx_end->is_max() || sys_trx_end->is_null()) + { + *part_id= vers_info->now_part->id; + } + else // row is historical + { + THD *thd= current_thd; + + switch (thd->lex->sql_command) + { + case SQLCOM_DELETE: + case SQLCOM_DELETE_MULTI: + case SQLCOM_UPDATE: + case SQLCOM_UPDATE_MULTI: + case SQLCOM_ALTER_TABLE: + mysql_mutex_lock(&table->s->LOCK_rotation); + if (table->s->busy_rotation) + { + table->s->vers_wait_rotation(); + part_info->vers_hist_part(); + } + else + { + table->s->busy_rotation= true; + mysql_mutex_unlock(&table->s->LOCK_rotation); + // transaction is not yet pushed to VTQ, so we use now-time + my_time_t end_ts= sys_trx_end->table->versioned_by_engine() ? + my_time(0) : sys_trx_end->get_timestamp(); + if (part_info->vers_limit_exceed() || part_info->vers_interval_exceed(end_ts)) + { + part_info->vers_part_rotate(thd); + } + mysql_mutex_lock(&table->s->LOCK_rotation); + mysql_cond_broadcast(&table->s->COND_rotation); + table->s->busy_rotation= false; + } + mysql_mutex_unlock(&table->s->LOCK_rotation); + break; + default: + ; + } + *part_id= vers_info->hist_part->id; + } + + if (tmp_off) + table->s->versioned= false; + + DBUG_PRINT("exit",("partition: %d", *part_id)); + DBUG_RETURN(0); +} + + int get_partition_id_range(partition_info *part_info, uint32 *part_id, longlong *func_value) @@ -4654,7 +4798,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, must know the number of new partitions in this case. */ if (thd->lex->no_write_to_binlog && - tab_part_info->part_type != HASH_PARTITION) + tab_part_info->part_type != HASH_PARTITION && + tab_part_info->part_type != VERSIONING_PARTITION) { my_error(ER_NO_BINLOG_ERROR, MYF(0)); goto err; @@ -4859,6 +5004,21 @@ that are reorganised. partition configuration is made. */ { + partition_element *now_part= NULL; + if (tab_part_info->part_type == VERSIONING_PARTITION) + { + List_iterator<partition_element> it(tab_part_info->partitions); + partition_element *el; + while ((el= it++)) + { + if (el->type() == partition_element::AS_OF_NOW) + { + DBUG_ASSERT(tab_part_info->vers_info && el == tab_part_info->vers_info->now_part); + it.remove(); + now_part= el; + } + } + } List_iterator<partition_element> alt_it(alt_part_info->partitions); uint part_count= 0; do @@ -4873,6 +5033,15 @@ that are reorganised. } } while (++part_count < num_new_partitions); tab_part_info->num_parts+= num_new_partitions; + if (tab_part_info->part_type == VERSIONING_PARTITION) + { + DBUG_ASSERT(now_part); + if (tab_part_info->partitions.push_back(now_part, thd->mem_root)) + { + mem_alloc_error(1); + goto err; + } + } } /* If we specify partitions explicitly we don't use defaults anymore. @@ -4906,16 +5075,28 @@ that are reorganised. List_iterator<partition_element> part_it(tab_part_info->partitions); tab_part_info->is_auto_partitioned= FALSE; - if (!(tab_part_info->part_type == RANGE_PARTITION || - tab_part_info->part_type == LIST_PARTITION)) + if (tab_part_info->part_type == VERSIONING_PARTITION) { - my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "DROP"); - goto err; + if (num_parts_dropped >= tab_part_info->num_parts - 1) + { + DBUG_ASSERT(table && table->s && table->s->table_name.str); + my_error(ER_VERS_WRONG_PARTS, MYF(0), table->s->table_name.str); + goto err; + } } - if (num_parts_dropped >= tab_part_info->num_parts) + else { - my_error(ER_DROP_LAST_PARTITION, MYF(0)); - goto err; + if (!(tab_part_info->part_type == RANGE_PARTITION || + tab_part_info->part_type == LIST_PARTITION)) + { + my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "DROP"); + goto err; + } + if (num_parts_dropped >= tab_part_info->num_parts) + { + my_error(ER_DROP_LAST_PARTITION, MYF(0)); + goto err; + } } do { @@ -4923,6 +5104,12 @@ that are reorganised. if (is_name_in_list(part_elem->partition_name, alter_info->partition_names)) { + if (part_elem->type() == partition_element::AS_OF_NOW) + { + DBUG_ASSERT(table && table->s && table->s->table_name.str); + my_error(ER_VERS_WRONG_PARTS, MYF(0), table->s->table_name.str); + goto err; + } /* Set state to indicate that the partition is to be dropped. */ @@ -5245,6 +5432,12 @@ the generated partition syntax in a correct manner. tab_part_info->use_default_subpartitions= FALSE; tab_part_info->use_default_num_subpartitions= FALSE; } + + if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION && + tab_part_info->part_type == VERSIONING_PARTITION && + tab_part_info->vers_setup_expression(thd, alt_part_info->partitions.elements)) + goto err; + if (tab_part_info->check_partition_info(thd, (handlerton**)NULL, table->file, 0, TRUE)) { @@ -6916,6 +7109,39 @@ err: } #endif + +/* + Prepare for calling val_int on partition function by setting fields to + point to the record where the values of the PF-fields are stored. + + SYNOPSIS + set_field_ptr() + ptr Array of fields to change ptr + new_buf New record pointer + old_buf Old record pointer + + DESCRIPTION + Set ptr in field objects of field array to refer to new_buf record + instead of previously old_buf. Used before calling val_int and after + it is used to restore pointers to table->record[0]. + This routine is placed outside of partition code since it can be useful + also for other programs. +*/ + +void set_field_ptr(Field **ptr, const uchar *new_buf, + const uchar *old_buf) +{ + my_ptrdiff_t diff= (new_buf - old_buf); + DBUG_ENTER("set_field_ptr"); + + do + { + (*ptr)->move_field_offset(diff); + } while (*(++ptr)); + DBUG_VOID_RETURN; +} + + /* Prepare for calling val_int on partition function by setting fields to point to the record where the values of the PF-fields are stored. @@ -6954,6 +7180,61 @@ void set_key_field_ptr(KEY *key_info, const uchar *new_buf, } +/** + Append all fields in read_set to string + + @param[in,out] str String to append to. + @param[in] row Row to append. + @param[in] table Table containing read_set and fields for the row. +*/ +void append_row_to_str(String &str, const uchar *row, TABLE *table) +{ + Field **fields, **field_ptr; + const uchar *rec; + uint num_fields= bitmap_bits_set(table->read_set); + uint curr_field_index= 0; + bool is_rec0= !row || row == table->record[0]; + if (!row) + rec= table->record[0]; + else + rec= row; + + /* Create a new array of all read fields. */ + fields= (Field**) my_malloc(sizeof(void*) * (num_fields + 1), + MYF(0)); + if (!fields) + return; + fields[num_fields]= NULL; + for (field_ptr= table->field; + *field_ptr; + field_ptr++) + { + if (!bitmap_is_set(table->read_set, (*field_ptr)->field_index)) + continue; + fields[curr_field_index++]= *field_ptr; + } + + + if (!is_rec0) + set_field_ptr(fields, rec, table->record[0]); + + for (field_ptr= fields; + *field_ptr; + field_ptr++) + { + Field *field= *field_ptr; + str.append(" "); + str.append(field->field_name); + str.append(":"); + field_unpack(&str, field, rec, 0, false); + } + + if (!is_rec0) + set_field_ptr(fields, table->record[0], rec); + my_free(fields); +} + + /* SYNOPSIS mem_alloc_error() @@ -7100,6 +7381,7 @@ static void set_up_range_analysis_info(partition_info *part_info) switch (part_info->part_type) { case RANGE_PARTITION: case LIST_PARTITION: + case VERSIONING_PARTITION: if (!part_info->column_list) { if (part_info->part_expr->get_monotonicity_info() != NON_MONOTONIC) @@ -7400,7 +7682,7 @@ int get_part_iter_for_interval_cols_via_map(partition_info *part_info, uint full_length= 0; DBUG_ENTER("get_part_iter_for_interval_cols_via_map"); - if (part_info->part_type == RANGE_PARTITION) + if (part_info->part_type == RANGE_PARTITION || part_info->part_type == VERSIONING_PARTITION) { get_col_endpoint= get_partition_id_cols_range_for_endpoint; part_iter->get_next= get_next_partition_id_range; @@ -7446,7 +7728,7 @@ int get_part_iter_for_interval_cols_via_map(partition_info *part_info, } if (flags & NO_MAX_RANGE) { - if (part_info->part_type == RANGE_PARTITION) + if (part_info->part_type == RANGE_PARTITION || part_info->part_type == VERSIONING_PARTITION) part_iter->part_nums.end= part_info->num_parts; else /* LIST_PARTITION */ { @@ -8143,4 +8425,52 @@ uint get_partition_field_store_length(Field *field) store_length+= HA_KEY_BLOB_LENGTH; return store_length; } + +// FIXME: duplicate of ha_partition::set_up_table_before_create +bool set_up_table_before_create(THD *thd, + TABLE_SHARE *share, + const char *partition_name_with_path, + HA_CREATE_INFO *info, + partition_element *part_elem) +{ + bool error= false; + const char *partition_name; + DBUG_ENTER("set_up_table_before_create"); + + DBUG_ASSERT(part_elem); + + if (!part_elem) + DBUG_RETURN(true); + share->max_rows= part_elem->part_max_rows; + share->min_rows= part_elem->part_min_rows; + partition_name= strrchr(partition_name_with_path, FN_LIBCHAR); + if ((part_elem->index_file_name && + (error= append_file_to_dir(thd, + const_cast<const char**>(&part_elem->index_file_name), + partition_name+1))) || + (part_elem->data_file_name && + (error= append_file_to_dir(thd, + const_cast<const char**>(&part_elem->data_file_name), + partition_name+1)))) + { + DBUG_RETURN(error); + } + if (part_elem->index_file_name != NULL) + { + info->index_file_name= part_elem->index_file_name; + } + if (part_elem->data_file_name != NULL) + { + info->data_file_name= part_elem->data_file_name; + } + if (part_elem->tablespace_name != NULL) + { + if (check_tablespace_name(part_elem->tablespace_name) != IDENT_NAME_OK) + { + DBUG_RETURN(true); + } + info->tablespace= part_elem->tablespace_name; + } + DBUG_RETURN(error); +} #endif diff --git a/sql/sql_partition.h b/sql/sql_partition.h index 992229afb05..626ceee3f13 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -41,6 +41,7 @@ typedef struct st_key_range key_range; #define HA_CAN_UPDATE_PARTITION_KEY (1 << 1) #define HA_CAN_PARTITION_UNIQUE (1 << 2) #define HA_USE_AUTO_PARTITION (1 << 3) +#define HA_ONLY_VERS_PARTITION (1 << 4) #define NORMAL_PART_NAME 0 #define TEMP_PART_NAME 1 @@ -128,6 +129,14 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool check_part_func_fields(Field **ptr, bool ok_with_charsets); bool field_is_partition_charset(Field *field); Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs); +/** + Append all fields in read_set to string + + @param[in,out] str String to append to. + @param[in] row Row to append. + @param[in] table Table containing read_set and fields for the row. +*/ +void append_row_to_str(String &str, const uchar *row, TABLE *table); void mem_alloc_error(size_t size); void truncate_partition_filename(char *path); @@ -291,4 +300,30 @@ int __attribute__((warn_unused_result)) void set_key_field_ptr(KEY *key_info, const uchar *new_buf, const uchar *old_buf); +/** Set up table for creating a partition. +Copy info from partition to the table share so the created partition +has the correct info. + @param thd THD object + @param share Table share to be updated. + @param info Create info to be updated. + @param part_elem partition_element containing the info. + + @return status + @retval TRUE Error + @retval FALSE Success + + @details + Set up + 1) Comment on partition + 2) MAX_ROWS, MIN_ROWS on partition + 3) Index file name on partition + 4) Data file name on partition +*/ +bool set_up_table_before_create(THD *thd, + TABLE_SHARE *share, + const char *partition_name_with_path, + HA_CREATE_INFO *info, + partition_element *part_elem); + #endif /* SQL_PARTITION_INCLUDED */ + diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 61e312646da..31cc6bcdd31 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -30,6 +30,7 @@ #include "sql_base.h" // tdc_remove_table, lock_table_names, #include "sql_handler.h" // mysql_ha_rm_tables #include "sql_statistics.h" +#include "vtmd.h" static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error); @@ -299,12 +300,23 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const char *new_db, LEX_CSTRING new_db_name= { new_db, strlen(new_db)}; (void) rename_table_in_stat_tables(thd, &db_name, &table_name, &new_db_name, &new_table); - if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db, - old_alias, - ren_table->table_name, - new_db, - new_alias))) + VTMD_rename vtmd(*ren_table); + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE) { + rc= vtmd.try_rename(thd, new_db_name, new_table); + if (rc) + goto revert_table_name; + } + rc= Table_triggers_list::change_table_name(thd, ren_table->db, + old_alias, + ren_table->table_name, + new_db, + new_alias); + if (rc) + { + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE) + vtmd.revert_rename(thd, new_db_name); +revert_table_name: /* We've succeeded in renaming table's .frm and in updating corresponding handler data, but have failed to update table's diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 53d445177f7..7b537bef53b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -54,12 +54,14 @@ #include "sql_statistics.h" #include "sql_cte.h" #include "sql_window.h" +#include "tztime.h" #include "debug_sync.h" // DEBUG_SYNC #include <m_ctype.h> #include <my_bit.h> #include <hash.h> #include <ft_global.h> +#include "sys_vars_shared.h" /* A key part number that means we're using a fulltext scan. @@ -669,6 +671,362 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array, DBUG_RETURN(res); } +bool vers_select_conds_t::init_from_sysvar(THD *thd) +{ + st_vers_current_time &in= thd->variables.vers_current_time; + type= in.type; + unit_start= UNIT_TIMESTAMP; + if (type != FOR_SYSTEM_TIME_UNSPECIFIED && type != FOR_SYSTEM_TIME_ALL) + { + DBUG_ASSERT(type == FOR_SYSTEM_TIME_AS_OF); + start= new (thd->mem_root) + Item_datetime_literal(thd, &in.ltime, TIME_SECOND_PART_DIGITS); + if (!start) + return true; + } + else + start= NULL; + end= NULL; + return false; +} + +int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr, + SELECT_LEX *slex) +{ + DBUG_ENTER("vers_setup_select"); +#define newx new (thd->mem_root) + + TABLE_LIST *table; + int versioned_tables= 0; + + if (!thd->stmt_arena->is_conventional() && + !thd->stmt_arena->is_stmt_prepare() && !thd->stmt_arena->is_sp_execute()) + { + // statement is already prepared + DBUG_RETURN(0); + } + + for (table= tables; table; table= table->next_local) + { + if (table->table && table->table->versioned()) + versioned_tables++; + else if (table->vers_conditions) + { + my_error(ER_VERSIONING_REQUIRED, MYF(0), table->alias); + DBUG_RETURN(-1); + } + } + + if (versioned_tables == 0) + DBUG_RETURN(0); + + /* For prepared statements we create items on statement arena, + because they must outlive execution phase for multiple executions. */ + Query_arena_stmt on_stmt_arena(thd); + + if (slex->saved_where) + { + DBUG_ASSERT(thd->stmt_arena->is_sp_execute()); + /* 2. this copy_andor_structure() is also required by the same reason */ + *where_expr= slex->saved_where->copy_andor_structure(thd); + } + else if (thd->stmt_arena->is_sp_execute()) + { + if (thd->stmt_arena->is_stmt_execute()) // SP executed second time (STMT_EXECUTED) + *where_expr= 0; + else if (*where_expr) // SP executed first time (STMT_INITIALIZED_FOR_SP) + /* 1. copy_andor_structure() is required since this andor tree + is modified later (and on shorter arena) */ + slex->saved_where= (*where_expr)->copy_andor_structure(thd); + } + + /* We have to save also non-versioned on_expr since we may have + conjuction of versioned + non-versioned */ + if (thd->stmt_arena->is_sp_execute()) + { + for (table= tables; table; table= table->next_local) + { + if (!table->table) + continue; + + if (table->saved_on_expr) // same logic as saved_where + { + if (table->on_expr) + table->on_expr= table->saved_on_expr->copy_andor_structure(thd); + else + // on_expr was moved to WHERE (see below: Add ON expression to the WHERE) + *where_expr= and_items(thd, + *where_expr, + table->saved_on_expr->copy_andor_structure(thd)); + } + else if (table->on_expr && + thd->stmt_arena->state == Query_arena::STMT_INITIALIZED_FOR_SP) + { + table->saved_on_expr= table->on_expr->copy_andor_structure(thd); + } + } + } + + SELECT_LEX *outer_slex= slex->next_select_in_list(); + // propagate derived conditions to outer SELECT_LEX + if (outer_slex && slex->vers_export_outer) + { + for (table= outer_slex->table_list.first; table; table= table->next_local) + { + if (!table->vers_conditions) + { + table->vers_conditions= slex->vers_export_outer; + table->vers_conditions.from_inner= true; + } + } + } + + for (table= tables; table; table= table->next_local) + { + if (table->table && table->table->versioned()) + { + vers_select_conds_t &vers_conditions= table->vers_conditions; + + // propagate system_time from nearest outer SELECT_LEX + if (!vers_conditions && outer_slex && slex->vers_import_outer) + { + TABLE_LIST* derived= slex->master_unit()->derived; + while (outer_slex && (!derived->vers_conditions || derived->vers_conditions.from_inner)) + { + derived= outer_slex->master_unit()->derived; + outer_slex= outer_slex->next_select_in_list(); + } + if (outer_slex) + { + DBUG_ASSERT(derived); + DBUG_ASSERT(derived->vers_conditions); + vers_conditions= derived->vers_conditions; + } + } + + // propagate system_time from sysvar + if (!vers_conditions) + { + if (vers_conditions.init_from_sysvar(thd)) + DBUG_RETURN(-1); + } + + if (vers_conditions) + { + switch (slex->lock_type) + { + case TL_WRITE_ALLOW_WRITE: + case TL_WRITE_CONCURRENT_INSERT: + case TL_WRITE_DELAYED: + case TL_WRITE_DEFAULT: + case TL_WRITE_LOW_PRIORITY: + case TL_WRITE: + case TL_WRITE_ONLY: + my_error(ER_VERS_HISTORY_LOCK, MYF(0)); + DBUG_RETURN(-1); + default: + break; + } + + if (vers_conditions == FOR_SYSTEM_TIME_ALL) + continue; + } // if (vers_conditions) + + COND** dst_cond= where_expr; + if (table->on_expr) + { + dst_cond= &table->on_expr; + } + + if (TABLE_LIST *t= table->embedding) + { + if (t->on_expr) + dst_cond= &t->on_expr; + } + + const LEX_CSTRING *fstart= &table->table->vers_start_field()->field_name; + const LEX_CSTRING *fend= &table->table->vers_end_field()->field_name; + + Item *row_start= + newx Item_field(thd, &slex->context, table->db, table->alias, fstart); + Item *row_end= + newx Item_field(thd, &slex->context, table->db, table->alias, fend); + Item *row_end2= row_end; + + bool tmp_from_ib= + table->table->s->table_category == TABLE_CATEGORY_TEMPORARY && + table->table->vers_start_field()->type() == MYSQL_TYPE_LONGLONG; + bool timestamps_only= table->table->versioned_by_sql() && !tmp_from_ib; + + if (vers_conditions) + { + vers_conditions.resolve_units(timestamps_only); + if (timestamps_only) + { + if (vers_conditions.unit_start == UNIT_TRX_ID || vers_conditions.unit_end == UNIT_TRX_ID) + { + my_error(ER_VERS_ENGINE_UNSUPPORTED, MYF(0), table->table_name); + DBUG_RETURN(-1); + } + } + else if (thd->variables.vers_innodb_algorithm_simple) + { + DBUG_ASSERT(table->table->s && table->table->s->db_plugin); + handlerton *hton= plugin_hton(table->table->s->db_plugin); + DBUG_ASSERT(hton); + bool convert_start= false; + bool convert_end= false; + switch (vers_conditions.type) + { + case FOR_SYSTEM_TIME_AS_OF: + if (vers_conditions.unit_start == UNIT_TIMESTAMP) + convert_start= convert_end= true; + break; + case FOR_SYSTEM_TIME_BEFORE: + if (vers_conditions.unit_start == UNIT_TIMESTAMP) + convert_end= true; + break; + case FOR_SYSTEM_TIME_FROM_TO: + case FOR_SYSTEM_TIME_BETWEEN: + if (vers_conditions.unit_start == UNIT_TIMESTAMP) + convert_end= true; + if (vers_conditions.unit_end == UNIT_TIMESTAMP) + convert_start= true; + default: + break; + } + if (convert_start) + row_start= newx Item_func_vtq_ts( + thd, + hton, + row_start, + VTQ_COMMIT_TS); + if (convert_end) + row_end= newx Item_func_vtq_ts( + thd, + hton, + row_end, + VTQ_COMMIT_TS); + } + } + + Item *cond1= 0, *cond2= 0, *curr= 0; + // Temporary tables of can be created from INNODB tables and thus will + // have uint64 type of sys_trx_(start|end) field. + // They need special handling. + TABLE *t= table->table; + if (tmp_from_ib || t->versioned_by_sql() || + thd->variables.vers_innodb_algorithm_simple) + { + switch (vers_conditions.type) + { + case FOR_SYSTEM_TIME_UNSPECIFIED: + if (t->vers_start_field()->real_type() != MYSQL_TYPE_LONGLONG) + { + MYSQL_TIME max_time; + thd->variables.time_zone->gmt_sec_to_TIME(&max_time, TIMESTAMP_MAX_VALUE); + max_time.second_part= TIME_MAX_SECOND_PART; + curr= newx Item_datetime_literal(thd, &max_time, + TIME_SECOND_PART_DIGITS); + cond1= newx Item_func_eq(thd, row_end, curr); + } + else + { + curr= newx Item_int(thd, ULONGLONG_MAX); + cond1= newx Item_func_eq(thd, row_end2, curr); + } + break; + case FOR_SYSTEM_TIME_AS_OF: + cond1= newx Item_func_le(thd, row_start, + vers_conditions.start); + cond2= newx Item_func_gt(thd, row_end, + vers_conditions.start); + break; + case FOR_SYSTEM_TIME_FROM_TO: + cond1= newx Item_func_lt(thd, row_start, + vers_conditions.end); + cond2= newx Item_func_ge(thd, row_end, + vers_conditions.start); + break; + case FOR_SYSTEM_TIME_BETWEEN: + cond1= newx Item_func_le(thd, row_start, + vers_conditions.end); + cond2= newx Item_func_ge(thd, row_end, + vers_conditions.start); + break; + case FOR_SYSTEM_TIME_BEFORE: + cond1= newx Item_func_lt(thd, row_end, + vers_conditions.start); + break; + default: + DBUG_ASSERT(0); + } + } + else + { + DBUG_ASSERT(table->table->s && table->table->s->db_plugin); + handlerton *hton= plugin_hton(table->table->s->db_plugin); + DBUG_ASSERT(hton); + + Item *trx_id0, *trx_id1; + + switch (vers_conditions.type) + { + case FOR_SYSTEM_TIME_UNSPECIFIED: + curr= newx Item_int(thd, ULONGLONG_MAX); + cond1= newx Item_func_eq(thd, row_end2, curr); + break; + case FOR_SYSTEM_TIME_AS_OF: + trx_id0= vers_conditions.unit_start == UNIT_TIMESTAMP ? + newx Item_func_vtq_id(thd, hton, vers_conditions.start, VTQ_TRX_ID) : + vers_conditions.start; + cond1= newx Item_func_vtq_trx_sees_eq(thd, hton, trx_id0, row_start); + cond2= newx Item_func_vtq_trx_sees(thd, hton, row_end, trx_id0); + break; + case FOR_SYSTEM_TIME_FROM_TO: + case FOR_SYSTEM_TIME_BETWEEN: + trx_id0= vers_conditions.unit_start == UNIT_TIMESTAMP ? + newx Item_func_vtq_id(thd, hton, vers_conditions.start, VTQ_TRX_ID, true) : + vers_conditions.start; + trx_id1= vers_conditions.unit_end == UNIT_TIMESTAMP ? + newx Item_func_vtq_id(thd, hton, vers_conditions.end, VTQ_TRX_ID, false) : + vers_conditions.end; + cond1= vers_conditions.type == FOR_SYSTEM_TIME_FROM_TO ? + newx Item_func_vtq_trx_sees(thd, hton, trx_id1, row_start) : + newx Item_func_vtq_trx_sees_eq(thd, hton, trx_id1, row_start); + cond2= newx Item_func_vtq_trx_sees_eq(thd, hton, row_end, trx_id0); + break; + case FOR_SYSTEM_TIME_BEFORE: + trx_id0= vers_conditions.unit_start == UNIT_TIMESTAMP ? + newx Item_func_vtq_id(thd, hton, vers_conditions.start, VTQ_TRX_ID) : + vers_conditions.start; + cond1= newx Item_func_lt(thd, row_end, trx_id0); + break; + default: + DBUG_ASSERT(0); + } + } + + if (cond1) + { + cond1= and_items(thd, + *dst_cond, + and_items(thd, + cond2, + cond1)); + + if (on_stmt_arena.arena_replaced()) + *dst_cond= cond1; + else + thd->change_item_tree(dst_cond, cond1); + } + } // if (... table->table->versioned()) + } // for (table= tables; ...) + + DBUG_RETURN(0); +#undef newx +} + /***************************************************************************** Check fields, find best join, do the select and output fields. mysql_select assumes that all tables are already opened @@ -744,7 +1102,11 @@ JOIN::prepare(TABLE_LIST *tables_init, { remove_redundant_subquery_clauses(select_lex); } - + + /* System Versioning: handle FOR SYSTEM_TIME clause. */ + if (vers_setup_select(thd, tables_list, &conds, select_lex) < 0) + DBUG_RETURN(-1); + /* TRUE if the SELECT list mixes elements with and without grouping, and there is no GROUP BY clause. Mixing non-aggregated fields with @@ -1026,6 +1388,46 @@ JOIN::prepare(TABLE_LIST *tables_init, if (!procedure && result && result->prepare(fields_list, unit_arg)) goto err; /* purecov: inspected */ + if (!thd->stmt_arena->is_stmt_prepare()) + { + bool have_versioned_tables= false; + for (TABLE_LIST *table= tables_list; table; table= table->next_local) + { + if (table->table && table->table->versioned()) + { + have_versioned_tables= true; + break; + } + } + + if (have_versioned_tables) + { + Item_transformer transformer= &Item::vers_optimized_fields_transformer; + + if (conds) + { + conds= conds->transform(thd, transformer, NULL); + } + + for (ORDER *ord= order; ord; ord= ord->next) + { + ord->item_ptr= (*ord->item)->transform(thd, transformer, NULL); + ord->item= &ord->item_ptr; + } + + for (ORDER *ord= group_list; ord; ord= ord->next) + { + ord->item_ptr= (*ord->item)->transform(thd, transformer, NULL); + ord->item= &ord->item_ptr; + } + + if (having) + { + having= having->transform(thd, transformer, NULL); + } + } + } + unit= unit_arg; if (prepare_stage2()) goto err; @@ -3545,6 +3947,16 @@ void JOIN::exec_inner() result->send_result_set_metadata( procedure ? procedure_fields_list : *fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); + + { + List_iterator<Item> it(*columns_list); + while (Item *item= it++) + { + Item_transformer transformer= &Item::vers_optimized_fields_transformer; + it.replace(item->transform(thd, transformer, NULL)); + } + } + error= do_select(this, procedure); /* Accumulate the counts from all join iterations of all join parts. */ thd->inc_examined_row_count(join_examined_rows); @@ -16289,7 +16701,12 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, item->result_field= new_field; else new_field->field_name= *name; - new_field->flags|= (org_field->flags & NO_DEFAULT_VALUE_FLAG); + new_field->flags|= (org_field->flags & ( + NO_DEFAULT_VALUE_FLAG | + HIDDEN_FLAG | + VERS_SYS_START_FLAG | + VERS_SYS_END_FLAG | + VERS_OPTIMIZED_UPDATE_FLAG)); if (org_field->maybe_null() || (item && item->maybe_null)) new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join if (org_field->type() == MYSQL_TYPE_VAR_STRING || @@ -16884,6 +17301,8 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, List_iterator_fast<Item> li(fields); Item *item; Field **tmp_from_field=from_field; + Field *sys_trx_start= NULL; + Field *sys_trx_end= NULL; while ((item=li++)) { Item::Type type= item->type(); @@ -17006,6 +17425,31 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, continue; // Some kind of const item } DBUG_ASSERT(!new_field->field_name.str || strlen(new_field->field_name.str) == new_field->field_name.length); + + if (type == Item::FIELD_ITEM || type == Item::REF_ITEM) + { + if (item->real_item()->type() == Item::FIELD_ITEM) + { + Item_field *item_field= (Item_field *)item->real_item(); + Field *field= item_field->field; + TABLE_SHARE *s= field->table->s; + if (s->versioned) + { + if (field->flags & VERS_SYS_START_FLAG) + sys_trx_start= new_field; + else if (field->flags & VERS_SYS_END_FLAG) + sys_trx_end= new_field; + } + } + } + if (type == Item::TYPE_HOLDER) + { + Item_type_holder *ith= (Item_type_holder*)item; + if (ith->flags & VERS_SYS_START_FLAG) + sys_trx_start= new_field; + else if (ith->flags & VERS_SYS_END_FLAG) + sys_trx_end= new_field; + } if (type == Item::SUM_FUNC_ITEM) { Item_sum *agg_item= (Item_sum *) item; @@ -17086,6 +17530,21 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, total_uneven_bit_length= 0; } } + + if (sys_trx_start && sys_trx_end) + { + sys_trx_start->flags|= VERS_SYS_START_FLAG | HIDDEN_FLAG; + sys_trx_end->flags|= VERS_SYS_END_FLAG | HIDDEN_FLAG; + share->versioned= true; + share->field= table->field; + share->row_start_field= sys_trx_start->field_index; + share->row_end_field= sys_trx_end->field_index; + } + else + { + DBUG_ASSERT(!sys_trx_start && !sys_trx_end); + } + DBUG_ASSERT(fieldnr == (uint) (reg_field - table->field)); DBUG_ASSERT(field_count >= (uint) (reg_field - table->field)); field_count= fieldnr; @@ -25575,6 +26034,11 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str, } #endif /* WITH_PARTITION_STORAGE_ENGINE */ } + if (table && table->versioned()) + { + // versioning conditions are already unwrapped to WHERE clause + str->append(" FOR SYSTEM_TIME ALL"); + } if (my_strcasecmp(table_alias_charset, cmp_name, alias)) { char t_alias_buff[MAX_ALIAS_NAME]; diff --git a/sql/sql_select.h b/sql/sql_select.h index b6b8deb99f5..b57452f8934 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2330,4 +2330,7 @@ int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort); JOIN_TAB *first_explain_order_tab(JOIN* join); JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab); +int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr, + SELECT_LEX *slex); + #endif /* SQL_SELECT_INCLUDED */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cd08959cc26..4b28b0d18da 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -62,6 +62,8 @@ #ifdef WITH_PARTITION_STORAGE_ENGINE #include "ha_partition.h" #endif +#include "vtmd.h" +#include "transaction.h" enum enum_i_s_events_fields { @@ -569,6 +571,7 @@ static struct show_privileges_st sys_privileges[]= {"Create view", "Tables", "To create new views"}, {"Create user", "Server Admin", "To create new users"}, {"Delete", "Tables", "To delete existing rows"}, + {"Delete versioning rows", "Tables", "To delete versioning table historical rows"}, {"Drop", "Databases,Tables", "To drop databases, tables, and views"}, #ifdef HAVE_EVENT_SCHEDULER {"Event","Server Admin","To create, alter, drop and execute events"}, @@ -1281,6 +1284,15 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) */ MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); + TABLE_LIST archive; + bool versioned= table_list->vers_conditions; + if (versioned) + { + DBUG_ASSERT(table_list->vers_conditions == FOR_SYSTEM_TIME_AS_OF); + VTMD_table vtmd(*table_list); + if (vtmd.setup_select(thd)) + goto exit; + } if (mysqld_show_create_get_fields(thd, table_list, &field_list, &buffer)) goto exit; @@ -1323,6 +1335,13 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) my_eof(thd); exit: + if (versioned) + { + /* If commit fails, we should be able to reset the OK status. */ + thd->get_stmt_da()->set_overwrite_status(true); + trans_commit_stmt(thd); + thd->get_stmt_da()->set_overwrite_status(false); + } close_thread_tables(thd); /* Release any metadata locks taken during SHOW CREATE. */ thd->mdl_context.rollback_to_savepoint(mdl_savepoint); @@ -1685,6 +1704,7 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value, has_default= (field->default_value || (!(field->flags & NO_DEFAULT_VALUE_FLAG) && + !field->vers_sys_field() && field->unireg_check != Field::NEXT_NUMBER)); def_value->length(0); @@ -2004,6 +2024,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, TABLE *table= table_list->table; TABLE_SHARE *share= table->s; sql_mode_t sql_mode= thd->variables.sql_mode; + ulong vers_hide= thd->variables.vers_hide; bool foreign_db_mode= sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | MODE_MSSQL | MODE_DB2 | MODE_MAXDB | MODE_ANSI); @@ -2043,7 +2064,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, alias= table_list->schema_table->table_name; else { - if (lower_case_table_names == 2) + if (lower_case_table_names == 2 || table_list->vers_force_alias) alias= table->alias.c_ptr(); else { @@ -2082,6 +2103,10 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, { uint flags = field->flags; + if (vers_hide == VERS_HIDE_FULL && + (flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG))) + continue; + if (ptr != table->field) packet->append(STRING_WITH_LEN(",\n")); @@ -2126,9 +2151,18 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, } else { + if (field->flags & VERS_SYS_START_FLAG) + { + packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW START")); + } + else if (field->flags & VERS_SYS_END_FLAG) + { + packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW END")); + } + if (flags & NOT_NULL_FLAG) packet->append(STRING_WITH_LEN(" NOT NULL")); - else if (field->type() == MYSQL_TYPE_TIMESTAMP) + else if (field->type() == MYSQL_TYPE_TIMESTAMP && !field->vers_sys_field()) { /* TIMESTAMP field require explicit NULL flag, because unlike @@ -2144,6 +2178,11 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(def_value.ptr(), def_value.length(), system_charset_info); } + if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG) + { + packet->append(STRING_WITH_LEN(" WITHOUT SYSTEM VERSIONING")); + } + if (!limited_mysql_mode && print_on_update_clause(field, &def_value, false)) { @@ -2235,6 +2274,17 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, hton->index_options); } + if (table->versioned() && vers_hide != VERS_HIDE_FULL) + { + const Field *fs = table->vers_start_field(); + const Field *fe = table->vers_end_field(); + packet->append(STRING_WITH_LEN(",\n PERIOD FOR SYSTEM_TIME (")); + append_identifier(thd,packet,fs->field_name.str, fs->field_name.length); + packet->append(STRING_WITH_LEN(", ")); + append_identifier(thd,packet,fe->field_name.str, fe->field_name.length); + packet->append(STRING_WITH_LEN(")")); + } + /* Get possible foreign key definitions stored in InnoDB and append them to the CREATE TABLE statement @@ -2273,6 +2323,11 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, add_table_options(thd, table, create_info_arg, table_list->schema_table != 0, 0, packet); + if (table->versioned() && vers_hide != VERS_HIDE_FULL) + { + packet->append(STRING_WITH_LEN(" WITH SYSTEM VERSIONING")); + } + #ifdef WITH_PARTITION_STORAGE_ENGINE { if (table->part_info && @@ -4184,7 +4239,7 @@ int schema_tables_add(THD *thd, Dynamic_array<LEX_CSTRING*> *files, @retval 2 Not fatal error; Safe to ignore this file list */ -static int +int make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names, LEX *lex, LOOKUP_FIELD_VALUES *lookup_field_vals, LEX_CSTRING *db_name) @@ -4835,6 +4890,59 @@ public: } }; +static bool get_all_archive_tables(THD *thd, + Dynamic_array<String> &all_archive_tables) +{ + if (thd->variables.vers_hide == VERS_HIDE_NEVER) + return false; + + Dynamic_array<LEX_CSTRING *> all_db; + LOOKUP_FIELD_VALUES lookup_field_values= { + {C_STRING_WITH_LEN("%")}, {NULL, 0}, true, false}; + if (make_db_list(thd, &all_db, &lookup_field_values)) + return true; + + LEX_STRING information_schema= {C_STRING_WITH_LEN("information_schema")}; + for (size_t i= 0; i < all_db.elements(); i++) + { + LEX_CSTRING db= *all_db.at(i); + if (db.length == information_schema.length && + !memcmp(db.str, information_schema.str, db.length)) + { + all_db.del(i); + break; + } + } + + for (size_t i= 0; i < all_db.elements(); i++) + { + LEX_CSTRING db_name= *all_db.at(i); + Dynamic_array<String> archive_tables; + if (VTMD_table::get_archive_tables(thd, db_name.str, db_name.length, + archive_tables)) + return true; + for (size_t i= 0; i < archive_tables.elements(); i++) + if (all_archive_tables.push(archive_tables.at(i))) + return true; + } + + return false; +} + +static bool is_archive_table(const Dynamic_array<String> &all_archive_tables, + const LEX_CSTRING candidate) +{ + for (size_t i= 0; i < all_archive_tables.elements(); i++) + { + const String &archive_table= all_archive_tables.at(i); + if (candidate.length == archive_table.length() && + !memcmp(candidate.str, archive_table.ptr(), candidate.length)) + { + return true; + } + } + return false; +} /** @brief Fill I_S tables whose data are retrieved @@ -4877,6 +4985,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) #endif uint table_open_method= tables->table_open_method; bool can_deadlock; + Dynamic_array<String> all_archive_tables; DBUG_ENTER("get_all_tables"); /* @@ -4939,6 +5048,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) if (make_db_list(thd, &db_names, &plan->lookup_field_vals)) goto err; + + if (get_all_archive_tables(thd, all_archive_tables)) + goto err; + for (size_t i=0; i < db_names.elements(); i++) { LEX_CSTRING *db_name= db_names.at(i); @@ -4964,6 +5077,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) LEX_CSTRING *table_name= table_names.at(i); DBUG_ASSERT(table_name->length <= NAME_LEN); + if (is_archive_table(all_archive_tables, *table_name)) + continue; + #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!(thd->col_access & TABLE_ACLS)) { @@ -7025,6 +7141,10 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, tmp_res.append(STRING_WITH_LEN("HASH")); table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs); break; + case VERSIONING_PARTITION: + tmp_res.length(0); + tmp_res.append(STRING_WITH_LEN("SYSTEM_TIME")); + break; default: DBUG_ASSERT(0); my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); @@ -7730,7 +7850,8 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) if (!(item=new (mem_root) Item_return_date_time(thd, fields_info->field_name, field_name_length, - fields_info->field_type))) + fields_info->field_type, + fields_info->field_length))) DBUG_RETURN(0); item->decimals= fields_info->field_length; break; diff --git a/sql/sql_show.h b/sql/sql_show.h index dc2fe9738fe..ac13099ca48 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -199,6 +199,9 @@ typedef struct st_lookup_field_values bool wild_table_value; } LOOKUP_FIELD_VALUES; +int make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING *> *table_names, + LEX *lex, LOOKUP_FIELD_VALUES *lookup_field_vals, + LEX_CSTRING *db_name); /* INFORMATION_SCHEMA: Execution plan for get_all_tables() call diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7371889cc7f..d6b4522fd50 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -55,6 +55,9 @@ #include "transaction.h" #include "sql_audit.h" #include "sql_sequence.h" +#include "tztime.h" +#include "vtmd.h" // System Versioning + #ifdef __WIN__ #include <io.h> @@ -2293,6 +2296,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, const char *db= table->db; size_t db_length= table->db_length; handlerton *table_type= 0; + VTMD_drop vtmd(*table); DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p", table->db, table->table_name, table->table, @@ -2453,6 +2457,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, else { char *end; + int frm_delete_error= 0; /* It could happen that table's share in the table definition cache is the only thing that keeps the engine plugin loaded @@ -2491,30 +2496,51 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, // Remove extension for delete *(end= path + path_length - reg_ext_length)= '\0'; - error= ha_delete_table(thd, table_type, path, db, table->table_name, - !dont_log_query); - - if (!error) + if ((thd->lex->sql_command == SQLCOM_DROP_TABLE || + thd->lex->sql_command == SQLCOM_CREATE_TABLE) && + thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE && + table_type && table_type != view_pseudo_hton) + { + error= vtmd.check_exists(thd); + if (error) + goto non_tmp_err; + if (!vtmd.exists) + goto drop_table; + error= mysql_rename_table(table_type, table->db, table->table_name, + table->db, vtmd.archive_name(thd), NO_FK_CHECKS); + } + else { - int frm_delete_error, trigger_drop_error= 0; - /* Delete the table definition file */ - strmov(end,reg_ext); - if (table_type && table_type != view_pseudo_hton && - table_type->discover_table) + drop_table: + error= ha_delete_table(thd, table_type, path, db, table->table_name, + !dont_log_query); + if (!error) { - /* - Table type is using discovery and may not need a .frm file. - Delete it silently if it exists - */ - (void) mysql_file_delete(key_file_frm, path, MYF(0)); - frm_delete_error= 0; + /* Delete the table definition file */ + strmov(end,reg_ext); + if (table_type && table_type != view_pseudo_hton && + table_type->discover_table) + { + /* + Table type is using discovery and may not need a .frm file. + Delete it silently if it exists + */ + (void) mysql_file_delete(key_file_frm, path, MYF(0)); + } + else if (mysql_file_delete(key_file_frm, path, + MYF(MY_WME))) + { + frm_delete_error= my_errno; + DBUG_ASSERT(frm_delete_error); + } } - else - frm_delete_error= mysql_file_delete(key_file_frm, path, - MYF(MY_WME)); - if (frm_delete_error) - frm_delete_error= my_errno; - else + } + + if (!error) + { + int trigger_drop_error= 0; + + if (!frm_delete_error) { non_tmp_table_deleted= TRUE; trigger_drop_error= @@ -2527,8 +2553,21 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, else if (frm_delete_error && if_exists) thd->clear_error(); } + non_tmp_err: non_tmp_error|= MY_TEST(error); } + + if (!error && vtmd.exists) + { + enum_sql_command sql_command= thd->lex->sql_command; + thd->lex->sql_command= SQLCOM_DROP_TABLE; + error= vtmd.update(thd); + thd->lex->sql_command= sql_command; + if (error) + mysql_rename_table(table_type, table->db, vtmd.archive_name(), + table->db, table->table_name, NO_FK_CHECKS); + } + if (error) { if (wrong_tables.length()) @@ -3022,10 +3061,12 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions) if (column_definition->is_timestamp_type() || // TIMESTAMP column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy { + DBUG_PRINT("info", ("field-ptr:%p", column_definition->field)); if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL, column_definition->default_value == NULL && // no constant default, column_definition->unireg_check == Field::NONE && // no function default - column_definition->vcol_info == NULL) + column_definition->vcol_info == NULL && + !(column_definition->flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG))) // column isn't generated { DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to " "DEFAULT CURRENT_TIMESTAMP ON UPDATE " @@ -3336,6 +3377,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } select_field_pos= alter_info->create_list.elements - select_field_count; + for (field_no=0; (sql_field=it++) ; field_no++) { /* @@ -4281,6 +4323,51 @@ bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root) } +static bool +vers_prepare_keys(THD *thd, + HA_CREATE_INFO *create_info, + Alter_info *alter_info, + KEY **key_info, + uint key_count) +{ + DBUG_ASSERT(create_info->versioned()); + + const char *row_start_field= create_info->vers_info.as_row.start; + DBUG_ASSERT(row_start_field); + const char *row_end_field= create_info->vers_info.as_row.end; + DBUG_ASSERT(row_end_field); + + List_iterator<Key> key_it(alter_info->key_list); + Key *key= NULL; + while ((key=key_it++)) + { + if (key->type != Key::PRIMARY && key->type != Key::UNIQUE) + continue; + + Key_part_spec *key_part= NULL; + List_iterator<Key_part_spec> part_it(key->columns); + while ((key_part=part_it++)) + { + if (!my_strcasecmp(system_charset_info, + row_start_field, + key_part->field_name.str) || + + !my_strcasecmp(system_charset_info, + row_end_field, + key_part->field_name.str)) + break; + } + if (key_part) + continue; // Key already contains Sys_start or Sys_end + + Key_part_spec *key_part_sys_end_col= + new (thd->mem_root) Key_part_spec(&create_info->vers_info.as_row.end, 0); + key->columns.push_back(key_part_sys_end_col); + } + + return false; +} + handler *mysql_create_frm_image(THD *thd, const char *db, const char *table_name, HA_CREATE_INFO *create_info, @@ -4439,7 +4526,10 @@ handler *mysql_create_frm_image(THD *thd, part_info->part_info_string= part_syntax_buf; part_info->part_info_len= syntax_len; if ((!(engine_type->partition_flags && - engine_type->partition_flags() & HA_CAN_PARTITION)) || + ((engine_type->partition_flags() & HA_CAN_PARTITION) || + (part_info->part_type == VERSIONING_PARTITION && + engine_type->partition_flags() & HA_ONLY_VERS_PARTITION)) + )) || create_info->db_type == partition_hton) { /* @@ -4520,6 +4610,13 @@ handler *mysql_create_frm_image(THD *thd, } #endif + if (create_info->versioned()) + { + if(vers_prepare_keys(thd, create_info, alter_info, key_info, + *key_count)) + goto err; + } + if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options, file, key_info, key_count, create_table_mode)) @@ -4977,6 +5074,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, { thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); result= 1; + goto err; } else { @@ -4985,6 +5083,20 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, } } + if (create_info->versioned() && + thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE) + { + VTMD_table vtmd(*create_table); + if (vtmd.update(thd)) + { + thd->variables.vers_alter_history = VERS_ALTER_HISTORY_KEEP; + mysql_rm_table_no_locks(thd, create_table, 0, 0, 0, 0, 1, 1); + thd->variables.vers_alter_history = VERS_ALTER_HISTORY_SURVIVE; + result= 1; + goto err; + } + } + err: /* In RBR we don't need to log CREATE TEMPORARY TABLE */ if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table()) @@ -5095,6 +5207,66 @@ static void make_unique_constraint_name(THD *thd, LEX_CSTRING *name, ** Alter a table definition ****************************************************************************/ +bool operator!=(const MYSQL_TIME &lhs, const MYSQL_TIME &rhs) +{ + return lhs.year != rhs.year || lhs.month != rhs.month || lhs.day != rhs.day || + lhs.hour != rhs.hour || lhs.minute != rhs.minute || + lhs.second_part != rhs.second_part || lhs.neg != rhs.neg || + lhs.time_type != rhs.time_type; +} + +// Sets sys_trx_end=MAX for rows with sys_trx_end=now(6) +static bool vers_reset_alter_copy(THD *thd, TABLE *table) +{ + const MYSQL_TIME query_start= thd->query_start_TIME(); + + READ_RECORD info; + int error= 0; + bool will_batch= false; + uint dup_key_found= 0; + if (init_read_record(&info, thd, table, NULL, NULL, 0, 1, true)) + goto err; + + will_batch= !table->file->start_bulk_update(); + + while (!(error= info.read_record())) + { + MYSQL_TIME current; + if (table->vers_end_field()->get_date(¤t, 0)) + goto err_read_record; + if (current != query_start) + { + continue; + } + + store_record(table, record[1]); + table->vers_end_field()->set_max(); + if (will_batch) + error= table->file->ha_bulk_update_row(table->record[1], table->record[0], + &dup_key_found); + else + error= table->file->ha_update_row(table->record[1], table->record[0]); + if (error && table->file->is_fatal_error(error, HA_CHECK_ALL)) + { + table->file->print_error(error, MYF(ME_FATALERROR)); + goto err_read_record; + } + } + + if (will_batch && (error= table->file->exec_bulk_update(&dup_key_found))) + table->file->print_error(error, MYF(ME_FATALERROR)); + if (will_batch) + table->file->end_bulk_update(); + +err_read_record: + end_read_record(&info); + +err: + if (table->file->ha_external_lock(thd, F_UNLCK)) + return true; + + return error ? true : false; +} /** Rename a table. @@ -5318,6 +5490,13 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, thd->work_part_info= src_table->table->part_info->get_clone(thd); #endif + if (src_table->table->versioned() && + local_create_info.vers_info.fix_create_like(thd, &local_alter_info, + &local_create_info, src_table)) + { + goto err; + } + /* Adjust description of source table before using it for creation of target table. @@ -5330,6 +5509,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, /* Replace type of source table with one specified in the statement. */ local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE; local_create_info.options|= create_info->tmp_table(); + local_create_info.options|= create_info->options; /* Reset auto-increment counter for the new table. */ local_create_info.auto_increment_value= 0; /* @@ -6214,6 +6394,8 @@ static bool fill_alter_inplace_info(THD *thd, ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_ADD_CHECK_CONSTRAINT; if (alter_info->flags & Alter_info::ALTER_DROP_CHECK_CONSTRAINT) ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_DROP_CHECK_CONSTRAINT; + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_DROP) + ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_DROP_HISTORICAL; /* If we altering table with old VARCHAR fields we will be automatically @@ -8479,18 +8661,30 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list, if (mysql_rename_table(old_db_type, alter_ctx->db, alter_ctx->table_name, alter_ctx->new_db, alter_ctx->new_alias, 0)) error= -1; - else if (Table_triggers_list::change_table_name(thd, - alter_ctx->db, - alter_ctx->alias, - alter_ctx->table_name, - alter_ctx->new_db, - alter_ctx->new_alias)) - { - (void) mysql_rename_table(old_db_type, - alter_ctx->new_db, alter_ctx->new_alias, - alter_ctx->db, alter_ctx->table_name, - NO_FK_CHECKS); - error= -1; + else + { + VTMD_rename vtmd(*table_list); + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE && + vtmd.try_rename(thd, new_db_name, new_table_name)) + { + goto revert_table_name; + } + else if (Table_triggers_list::change_table_name(thd, + alter_ctx->db, + alter_ctx->alias, + alter_ctx->table_name, + alter_ctx->new_db, + alter_ctx->new_alias)) + { + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE) + vtmd.revert_rename(thd, new_db_name); +revert_table_name: + (void) mysql_rename_table(old_db_type, + alter_ctx->new_db, alter_ctx->new_alias, + alter_ctx->db, alter_ctx->table_name, + NO_FK_CHECKS); + error= -1; + } } } @@ -8621,6 +8815,30 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, bool error= open_tables(thd, &table_list, &tables_opened, 0, &alter_prelocking_strategy); thd->open_options&= ~HA_OPEN_FOR_ALTER; + bool versioned= table_list->table && table_list->table->versioned(); + bool vers_data_mod= versioned && + thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE && + alter_info->vers_data_modifying(); + + if (vers_data_mod) + { + table_list->set_lock_type(thd, TL_WRITE); + if (thd->mdl_context.upgrade_shared_lock(table_list->table->mdl_ticket, + MDL_EXCLUSIVE, + thd->variables.lock_wait_timeout)) + { + DBUG_RETURN(true); + } + + if (table_list->table->versioned_by_engine() && + alter_info->requested_algorithm == + Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT && + !table_list->table->s->partition_info_str) + { + // Changle default ALGORITHM to COPY for INNODB + alter_info->requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY; + } + } DEBUG_SYNC(thd, "alter_opened_table"); @@ -8749,6 +8967,12 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, if (check_engine(thd, alter_ctx.new_db, alter_ctx.new_name, create_info)) DBUG_RETURN(true); + if (create_info->vers_info.check_and_fix_alter(thd, alter_info, create_info, + table->s)) + { + DBUG_RETURN(true); + } + if ((create_info->db_type != table->s->db_type() || alter_info->flags & Alter_info::ALTER_PARTITION) && !table->file->can_switch_engines()) @@ -8927,9 +9151,11 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, Upgrade from MDL_SHARED_UPGRADABLE to MDL_SHARED_NO_WRITE. Afterwards it's safe to take the table level lock. */ - if (thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_SHARED_NO_WRITE, - thd->variables.lock_wait_timeout) - || lock_tables(thd, table_list, alter_ctx.tables_opened, 0)) + if ((!vers_data_mod && + thd->mdl_context.upgrade_shared_lock( + mdl_ticket, MDL_SHARED_NO_WRITE, + thd->variables.lock_wait_timeout)) || + lock_tables(thd, table_list, alter_ctx.tables_opened, 0)) { DBUG_RETURN(true); } @@ -8991,6 +9217,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, handlerton *new_db_type= create_info->db_type; handlerton *old_db_type= table->s->db_type(); TABLE *new_table= NULL; + bool new_versioned= false; ha_rows copied=0,deleted=0; /* @@ -9327,6 +9554,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, } if (!new_table) goto err_new_table_cleanup; + new_versioned= new_table->versioned(); /* Note: In case of MERGE table, we do not attach children. We do not copy data for MERGE tables. Only the children have data. @@ -9353,7 +9581,14 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, order_num, order, &copied, &deleted, alter_info->keys_onoff, &alter_ctx)) + { + if (vers_data_mod && new_versioned && table->versioned_by_sql()) + { + // Failure of this function may result in corruption of an original table. + vers_reset_alter_copy(thd, table); + } goto err_new_table_cleanup; + } } else { @@ -9448,9 +9683,14 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, Rename the old table to temporary name to have a backup in case anything goes wrong while renaming the new table. */ - char backup_name[32]; - my_snprintf(backup_name, sizeof(backup_name), "%s2-%lx-%lx", tmp_file_prefix, - current_pid, (long) thd->thread_id); + char backup_name[FN_LEN]; + if (vers_data_mod) + VTMD_table::archive_name(thd, alter_ctx.table_name, backup_name, + sizeof(backup_name)); + else + my_snprintf(backup_name, sizeof(backup_name), "%s2-%lx-%lx", + tmp_file_prefix, current_pid, thd->thread_id); + if (lower_case_table_names) my_casedn_str(files_charset_info, backup_name); if (mysql_rename_table(old_db_type, alter_ctx.db, alter_ctx.table_name, @@ -9478,6 +9718,17 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, goto err_with_mdl; } + if (vers_data_mod && new_versioned) + { + DBUG_ASSERT(alter_info && table_list); + VTMD_rename vtmd(*table_list); + bool rc= alter_info->flags & Alter_info::ALTER_RENAME ? + vtmd.try_rename(thd, alter_ctx.new_db, alter_ctx.new_alias, backup_name) : + vtmd.update(thd, backup_name); + if (rc) + goto err_after_rename; + } + // Check if we renamed the table and if so update trigger files. if (alter_ctx.is_table_renamed()) { @@ -9488,6 +9739,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, alter_ctx.new_db, alter_ctx.new_alias)) { +err_after_rename: // Rename succeeded, delete the new table. (void) quick_rm_table(thd, new_db_type, alter_ctx.new_db, alter_ctx.new_alias, 0); @@ -9502,7 +9754,8 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, } // ALTER TABLE succeeded, delete the backup of the old table. - if (quick_rm_table(thd, old_db_type, alter_ctx.db, backup_name, FN_IS_TMP)) + if (!(vers_data_mod && new_versioned) && + quick_rm_table(thd, old_db_type, alter_ctx.db, backup_name, FN_IS_TMP)) { /* The fact that deletion of the backup failed is not critical @@ -9689,6 +9942,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, sql_mode_t save_sql_mode= thd->variables.sql_mode; ulonglong prev_insert_id, time_to_report_progress; Field **dfield_ptr= to->default_field; + bool make_versioned= !from->versioned() && to->versioned(); + bool make_unversioned= from->versioned() && !to->versioned(); + bool keep_versioned= from->versioned() && to->versioned(); + Field *to_sys_trx_start= NULL, *to_sys_trx_end= NULL, *from_sys_trx_end= NULL; + MYSQL_TIME query_start; DBUG_ENTER("copy_data_between_tables"); /* Two or 3 stages; Sorting, copying data and update indexes */ @@ -9789,6 +10047,30 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, thd_progress_next_stage(thd); } + if (make_versioned) + { + query_start= thd->query_start_TIME(); + to_sys_trx_start= to->vers_start_field(); + to_sys_trx_end= to->vers_end_field(); + } + else if (make_unversioned) + { + from_sys_trx_end= from->vers_end_field(); + } + else if (keep_versioned) + { + to->file->vers_auto_decrement= 0xffffffffffffffff; + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE) + { + query_start= thd->query_start_TIME(); + from_sys_trx_end= from->vers_end_field(); + to_sys_trx_start= to->vers_start_field(); + } else if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_DROP) + { + from_sys_trx_end= from->vers_end_field(); + } + } + THD_STAGE_INFO(thd, stage_copy_to_tmp_table); /* Tell handler that we have values for all columns in the to table */ to->use_all_columns(); @@ -9842,6 +10124,36 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, { copy_ptr->do_copy(copy_ptr); } + + if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_DROP && + from_sys_trx_end && !from_sys_trx_end->is_max()) + { + continue; + } + + if (make_versioned) + { + to_sys_trx_start->set_notnull(); + to_sys_trx_start->store_time(&query_start); + to_sys_trx_end->set_max(); + } + else if (make_unversioned) + { + if (!from_sys_trx_end->is_max()) + continue; // Drop history rows. + } + else if (keep_versioned && + thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE) + { + if (!from_sys_trx_end->is_max()) + continue; // Do not copy history rows. + + store_record(from, record[1]); + from->vers_end_field()->store_time(&query_start); + from->file->ha_update_row(from->record[1], from->record[0]); + to_sys_trx_start->store_time(&query_start); + } + prev_insert_id= to->file->next_insert_id; if (to->default_field) to->update_default_fields(0, ignore); @@ -9856,7 +10168,17 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, error= 1; break; } - error=to->file->ha_write_row(to->record[0]); + if (keep_versioned && to->versioned_by_engine() && + thd->variables.vers_alter_history != VERS_ALTER_HISTORY_SURVIVE) + { + to->s->versioned= false; + } + error= to->file->ha_write_row(to->record[0]); + if (keep_versioned && to->versioned_by_engine() && + thd->variables.vers_alter_history != VERS_ALTER_HISTORY_SURVIVE) + { + to->s->versioned= true; + } to->auto_increment_field_not_null= FALSE; if (error) { diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index 93a3007d1ea..b07ec0b418c 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -22,6 +22,70 @@ #include "sql_table.h" // write_bin_log #include "sql_class.h" // THD +/** + Check if tablespace name is valid + + @param tablespace_name Name of the tablespace + + @note Tablespace names are not reflected in the file system, so + character case conversion or consideration is not relevant. + + @note Checking for path characters or ending space is not done. + The only checks are for identifier length, both in terms of + number of characters and number of bytes. + + @retval IDENT_NAME_OK Identifier name is ok (Success) + @retval IDENT_NAME_WRONG Identifier name is wrong, if length == 0 +* (ER_WRONG_TABLESPACE_NAME) + @retval IDENT_NAME_TOO_LONG Identifier name is too long if it is greater + than 64 characters (ER_TOO_LONG_IDENT) + + @note In case of IDENT_NAME_TOO_LONG or IDENT_NAME_WRONG, the function + reports an error (using my_error()). +*/ + +enum_ident_name_check check_tablespace_name(const char *tablespace_name) +{ + size_t name_length= 0; //< Length as number of bytes + size_t name_length_symbols= 0; //< Length as number of symbols + + // Name must be != NULL and length must be > 0 + if (!tablespace_name || (name_length= strlen(tablespace_name)) == 0) + { + my_error(ER_WRONG_TABLESPACE_NAME, MYF(0), tablespace_name); + return IDENT_NAME_WRONG; + } + + // If we do not have too many bytes, we must check the number of symbols, + // provided the system character set may use more than one byte per symbol. + if (name_length <= NAME_LEN && use_mb(system_charset_info)) + { + const char *name= tablespace_name; //< The actual tablespace name + const char *end= name + name_length; //< Pointer to first byte after name + + // Loop over all symbols as long as we don't have too many already + while (name != end && name_length_symbols <= NAME_CHAR_LEN) + { + int len= my_ismbchar(system_charset_info, name, end); + if (len) + name += len; + else + name++; + + name_length_symbols++; + } + } + + if (name_length_symbols > NAME_CHAR_LEN || name_length > NAME_LEN) + { + my_error(ER_TOO_LONG_IDENT, MYF(0), tablespace_name); + return IDENT_NAME_TOO_LONG; + } + + return IDENT_NAME_OK; +} + + int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) { int error= HA_ADMIN_NOT_IMPLEMENTED; diff --git a/sql/sql_tablespace.h b/sql/sql_tablespace.h index ae77d15cbcb..b97c64f7965 100644 --- a/sql/sql_tablespace.h +++ b/sql/sql_tablespace.h @@ -19,6 +19,41 @@ class THD; class st_alter_tablespace; +/** + Enumerate possible status of a identifier name while determining + its validity +*/ +enum enum_ident_name_check +{ + IDENT_NAME_OK, + IDENT_NAME_WRONG, + IDENT_NAME_TOO_LONG +}; + +/** + Check if tablespace name is valid + + @param tablespace_name Name of the tablespace + + @note Tablespace names are not reflected in the file system, so + character case conversion or consideration is not relevant. + + @note Checking for path characters or ending space is not done. + The only checks are for identifier length, both in terms of + number of characters and number of bytes. + + @retval IDENT_NAME_OK Identifier name is ok (Success) + @retval IDENT_NAME_WRONG Identifier name is wrong, if length == 0 + (ER_WRONG_TABLESPACE_NAME) + @retval IDENT_NAME_TOO_LONG Identifier name is too long if it is greater + than 64 characters (ER_TOO_LONG_IDENT) + + @note In case of IDENT_NAME_TOO_LONG or IDENT_NAME_WRONG, the function + reports an error (using my_error()). +*/ + +enum_ident_name_check check_tablespace_name(const char *tablespace_name); + int mysql_alter_tablespace(THD* thd, st_alter_tablespace *ts_info); #endif /* SQL_TABLESPACE_INCLUDED */ diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 309ede45ecc..276540e9dba 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -475,6 +475,7 @@ void localtime_to_TIME(MYSQL_TIME *to, struct tm *from) to->second= (int) from->tm_sec; } + void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds) { long t_seconds; diff --git a/sql/sql_time.h b/sql/sql_time.h index 1832e4501ed..28a2e2f50d2 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -170,6 +170,7 @@ bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, int lsign, MYSQL_TIME *l_time3, ulonglong fuzzydate); int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b); void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); + void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds); uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year); diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 8847680c7b2..8cbb6c44c66 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -310,7 +310,7 @@ private: inline Field **TABLE::field_to_fill() { return triggers && triggers->nullable_fields() ? triggers->nullable_fields() - : field; + : non_generated_field ? non_generated_field : field; } diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 1d6edbc5fc9..27e405cd6b9 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -27,7 +27,8 @@ #include "sql_truncate.h" #include "wsrep_mysqld.h" #include "sql_show.h" //append_identifier() - +#include "sql_select.h" +#include "sql_delete.h" /** Append a list of field names to a string. @@ -481,7 +482,6 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) DBUG_RETURN(error); } - /** Execute a TRUNCATE statement at runtime. @@ -493,13 +493,20 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) bool Sql_cmd_truncate_table::execute(THD *thd) { bool res= TRUE; - TABLE_LIST *first_table= thd->lex->select_lex.table_list.first; + TABLE_LIST *table= thd->lex->select_lex.table_list.first; DBUG_ENTER("Sql_cmd_truncate_table::execute"); - if (check_one_table_access(thd, DROP_ACL, first_table)) + if (table->vers_conditions) + { + if (check_one_table_access(thd, DELETE_VERSIONING_ROWS_ACL, table)) + DBUG_RETURN(res); + DBUG_RETURN(mysql_delete(thd, table, NULL, NULL, -1, 0, NULL)); + } + + if (check_one_table_access(thd, DROP_ACL, table)) DBUG_RETURN(res); - if (! (res= truncate_table(thd, first_table))) + if (! (res= truncate_table(thd, table))) my_ok(thd); DBUG_RETURN(res); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 62dcff33f1d..b23ee1b314d 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -658,7 +658,9 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h) Item_result a= cmp_type(); Item_result b= h->cmp_type(); - if (a == STRING_RESULT && b == STRING_RESULT) + if (m_vers_trx_id && (a == STRING_RESULT || b == STRING_RESULT)) + m_type_handler= &type_handler_datetime; + else if (a == STRING_RESULT && b == STRING_RESULT) m_type_handler= &type_handler_long_blob; else if (a == INT_RESULT && b == INT_RESULT) m_type_handler= &type_handler_longlong; diff --git a/sql/sql_type.h b/sql/sql_type.h index d94c5a87811..1310666e667 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -2811,14 +2811,16 @@ public: class Type_handler_hybrid_field_type { const Type_handler *m_type_handler; + bool m_vers_trx_id; bool aggregate_for_min_max(const Type_handler *other); + public: Type_handler_hybrid_field_type(); Type_handler_hybrid_field_type(const Type_handler *handler) - :m_type_handler(handler) + :m_type_handler(handler), m_vers_trx_id(false) { } Type_handler_hybrid_field_type(const Type_handler_hybrid_field_type *other) - :m_type_handler(other->m_type_handler) + :m_type_handler(other->m_type_handler), m_vers_trx_id(other->m_vers_trx_id) { } const Type_handler *type_handler() const { return m_type_handler; } enum_field_types real_field_type() const diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 96f48be5ff2..e019d0f6ac4 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -44,6 +44,9 @@ // mysql_derived_filling +#include "sql_insert.h" // For vers_insert_history_row() that may be + // needed for System Versioning. + /** True if the table's input and output record buffers are comparable using compare_record(TABLE*). @@ -152,6 +155,17 @@ static bool check_fields(THD *thd, List<Item> &items) return FALSE; } +static bool check_has_vers_fields(List<Item> &items) +{ + List_iterator<Item> it(items); + while (Item *item= it++) + { + if (Item_field *item_field= item->field_for_view_update()) + if (!(item_field->field->flags & VERS_OPTIMIZED_UPDATE_FLAG)) + return true; + } + return false; +} /** Re-read record if more columns are needed for error message. @@ -281,6 +295,10 @@ int mysql_update(THD *thd, TABLE_LIST *update_source_table; query_plan.index= MAX_KEY; query_plan.using_filesort= FALSE; + + // For System Versioning (may need to insert new fields to a table). + ha_rows updated_sys_ver= 0; + DBUG_ENTER("mysql_update"); create_explain_query(thd->lex, thd->mem_root); @@ -351,12 +369,17 @@ int mysql_update(THD *thd, { DBUG_RETURN(1); } + bool has_vers_fields= + table->versioned() ? check_has_vers_fields(fields) : false; if (check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); DBUG_RETURN(1); } + if (table->default_field) + table->mark_default_fields_for_write(false); + #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check values */ table_list->grant.want_privilege= table->grant.want_privilege= @@ -737,6 +760,11 @@ int mysql_update(THD *thd, while (!(error=info.read_record()) && !thd->killed) { + if (table->versioned() && !table->vers_end_field()->is_max()) + { + continue; + } + explain->tracker.on_record_read(); thd->inc_examined_row_count(1); if (!select || select->skip_record(thd) > 0) @@ -746,10 +774,14 @@ int mysql_update(THD *thd, explain->tracker.on_record_after_where(); store_record(table,record[1]); + if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0, TRG_EVENT_UPDATE)) break; /* purecov: inspected */ + if (has_vers_fields && table->versioned_by_sql()) + table->vers_update_fields(); + found++; if (!can_compare_record || compare_record(table)) @@ -808,19 +840,35 @@ int mysql_update(THD *thd, else { /* Non-batched update */ - error= table->file->ha_update_row(table->record[1], + error= table->file->ha_update_row(table->record[1], table->record[0]); } - if (!error || error == HA_ERR_RECORD_IS_THE_SAME) - { - if (error != HA_ERR_RECORD_IS_THE_SAME) - updated++; - else - error= 0; - } - else if (!ignore || + if (error == HA_ERR_RECORD_IS_THE_SAME) + { + error= 0; + } + else if (!error) + { + updated++; + + if (has_vers_fields && table->versioned()) + { + if (table->versioned_by_sql()) + { + store_record(table, record[2]); + if ((error = vers_insert_history_row(table))) + { + restore_record(table, record[2]); + break; + } + restore_record(table, record[2]); + } + updated_sys_ver++; + } + } + else if (!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL)) - { + { /* If (ignore && error is ignorable) we don't have to do anything; otherwise... @@ -991,6 +1039,9 @@ int mysql_update(THD *thd, else errcode= query_error_code(thd, killed_status == NOT_KILLED); + ScopedStatementReplication scoped_stmt_rpl( + table->versioned_by_engine() ? thd : NULL); + if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), transactional_table, FALSE, FALSE, errcode)) @@ -1010,9 +1061,15 @@ int mysql_update(THD *thd, if (error < 0 && !thd->lex->analyze_stmt) { char buff[MYSQL_ERRMSG_SIZE]; - my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_UPDATE_INFO), (ulong) found, - (ulong) updated, - (ulong) thd->get_stmt_da()->current_statement_warn_count()); + if (!table->versioned_by_sql()) + my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_UPDATE_INFO), (ulong) found, + (ulong) updated, + (ulong) thd->get_stmt_da()->current_statement_warn_count()); + else + my_snprintf(buff, sizeof(buff), + ER_THD(thd, ER_UPDATE_INFO_WITH_SYSTEM_VERSIONING), + (ulong) found, (ulong) updated, (ulong) updated_sys_ver, + (ulong) thd->get_stmt_da()->current_statement_warn_count()); my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, id, buff); DBUG_PRINT("info",("%ld records updated", (long) updated)); @@ -1619,8 +1676,11 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, tmp_tables(0), updated(0), found(0), fields(field_list), values(value_list), table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(1), - transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0) -{} + transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0), + updated_sys_ver(0) +{ + has_vers_fields= check_has_vers_fields(*field_list); +} /* @@ -1871,7 +1931,7 @@ static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab, return !is_key_used(table, table->s->primary_key, table->write_set); return TRUE; default: - break; // Avoid compler warning + break; // Avoid compiler warning } return FALSE; @@ -2096,6 +2156,11 @@ int multi_update::send_data(List<Item> ¬_used_values) if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED)) continue; + if (table->versioned() && !table->vers_end_field()->is_max()) + { + continue; + } + if (table == table_to_update) { /* @@ -2108,6 +2173,7 @@ int multi_update::send_data(List<Item> ¬_used_values) table->status|= STATUS_UPDATED; store_record(table,record[1]); + if (fill_record_n_invoke_before_triggers(thd, table, *fields_for_table[offset], *values_for_table[offset], 0, @@ -2126,6 +2192,9 @@ int multi_update::send_data(List<Item> ¬_used_values) if (table->default_field && table->update_default_fields(1, ignore)) DBUG_RETURN(1); + if (has_vers_fields && table->versioned_by_sql()) + table->vers_update_fields(); + if ((error= cur_table->view_check_option(thd, ignore)) != VIEW_CHECK_OK) { @@ -2173,6 +2242,21 @@ int multi_update::send_data(List<Item> ¬_used_values) error= 0; updated--; } + else if (has_vers_fields && table->versioned()) + { + if (table->versioned_by_sql()) + { + store_record(table, record[2]); + if (vers_insert_history_row(table)) + { + restore_record(table, record[2]); + error= 1; + break; + } + restore_record(table, record[2]); + } + updated_sys_ver++; + } /* non-transactional or transactional table got modified */ /* either multi_update class' flag is raised in its branch */ if (table->file->has_transactions()) @@ -2199,6 +2283,7 @@ int multi_update::send_data(List<Item> ¬_used_values) */ uint field_num= 0; List_iterator_fast<TABLE> tbl_it(unupdated_check_opt_tables); + /* Set first tbl = table and then tbl to tables from tbl_it */ TABLE *tbl= table; do { @@ -2261,10 +2346,6 @@ void multi_update::abort_result_set() if (do_update && table_count > 1) { /* Add warning here */ - /* - todo/fixme: do_update() is never called with the arg 1. - should it change the signature to become argless? - */ (void) do_updates(); } } @@ -2466,19 +2547,40 @@ int multi_update::do_updates() goto err2; } } - if ((local_error=table->file->ha_update_row(table->record[1], - table->record[0])) && + if (has_vers_fields && table->versioned_by_sql()) + table->vers_update_fields(); + + if ((local_error=table->file->ha_update_row(table->record[1], + table->record[0])) && local_error != HA_ERR_RECORD_IS_THE_SAME) { if (!ignore || table->file->is_fatal_error(local_error, HA_CHECK_ALL)) { err_table= table; - goto err; + goto err; } - } + } if (local_error != HA_ERR_RECORD_IS_THE_SAME) + { updated++; + + if (has_vers_fields && table->versioned()) + { + if (table->versioned_by_sql()) + { + store_record(table, record[2]); + if ((local_error= vers_insert_history_row(table))) + { + restore_record(table, record[2]); + err_table = table; + goto err; + } + restore_record(table, record[2]); + } + updated_sys_ver++; + } + } else local_error= 0; } @@ -2594,9 +2696,21 @@ bool multi_update::send_eof() thd->clear_error(); else errcode= query_error_code(thd, killed_status == NOT_KILLED); - if (thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_tables, FALSE, FALSE, errcode)) + + bool force_stmt= false; + for (TABLE *table= all_tables->table; table; table= table->next) + { + if (table->versioned_by_engine()) + { + force_stmt= true; + break; + } + } + ScopedStatementReplication scoped_stmt_rpl(force_stmt ? thd : NULL); + + if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), + thd->query_length(), transactional_tables, FALSE, + FALSE, errcode)) { local_error= 1; // Rollback update } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 2d8129fd223..0b7f8f50ea3 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -455,6 +455,140 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, goto err; } + for (SELECT_LEX *sl= select_lex; sl; sl= sl->next_select()) + { /* System Versioning: fix system fields of versioned view */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wformat-extra-args" + // Similar logic as in mysql_derived_prepare() + // Leading versioning table detected implicitly (first one selected) + TABLE_LIST *impli_table= NULL; + // Leading versioning table specified explicitly + // (i.e. if at least one system field is selected) + TABLE_LIST *expli_table= NULL; + const LString_i *impli_start, *impli_end; + Item_field *expli_start= NULL, *expli_end= NULL; + + for (TABLE_LIST *table= tables; table; table= table->next_local) + { + DBUG_ASSERT(!table->is_view() || table->view); + + // Any versioned table in VIEW will add `FOR SYSTEM_TIME ALL` + WHERE: + // if there are at least one versioned table then VIEW will contain FOR_SYSTEM_TIME_ALL + // (because it is in fact LEX used to parse its SELECT). + if (table->is_view() && table->view->vers_conditions == FOR_SYSTEM_TIME_ALL) + { + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: versioned VIEW %`s in query!", MYF(0), + view->table_name, + table->table_name); + res= true; + goto err; + } + + if (!table->table || !table->table->versioned()) + continue; + + const LString_i table_start= table->table->vers_start_field()->field_name; + const LString_i table_end= table->table->vers_end_field()->field_name; + + if (!impli_table) + { + impli_table= table; + impli_start= &table_start; + impli_end= &table_end; + } + + /* Implicitly add versioning fields if needed */ + Item *item; + List_iterator_fast<Item> it(sl->item_list); + + DBUG_ASSERT(table->alias); + while ((item= it++)) + { + if (item->real_item()->type() != Item::FIELD_ITEM) + continue; + Item_field *fld= (Item_field*) item->real_item(); + if (fld->table_name && 0 != my_strcasecmp(table_alias_charset, table->alias, fld->table_name)) + continue; + DBUG_ASSERT(fld->field_name.str); + if (table_start == fld->field_name) + { + if (expli_start) + { + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: multiple start system fields `%s.%s`, `%s.%s` in query!", MYF(0), + view->table_name, + expli_table->alias, + expli_start->field_name.str, + table->alias, + fld->field_name.str); + res= true; + goto err; + } + if (expli_table) + { + if (expli_table != table) + { +expli_table_err: + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: system fields from multiple tables %`s, %`s in query!", MYF(0), + view->table_name, + expli_table->alias, + table->alias); + res= true; + goto err; + } + } + else + expli_table= table; + expli_start= fld; + impli_end= &table_end; + } + else if (table_end == fld->field_name) + { + if (expli_end) + { + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: multiple end system fields `%s.%s`, `%s.%s` in query!", MYF(0), + view->table_name, + expli_table->alias, + expli_end->field_name.str, + table->alias, + fld->field_name.str); + res= true; + goto err; + } + if (expli_table) + { + if (expli_table != table) + goto expli_table_err; + } + else + expli_table= table; + expli_end= fld; + impli_start= &table_start; + } + } // while ((item= it++)) + } // for (TABLE_LIST *table) + + if (expli_table) + impli_table= expli_table; + + if (impli_table) + { + if (!expli_start && sl->vers_push_field(thd, impli_table, *impli_start)) + goto err; + if (!expli_end && sl->vers_push_field(thd, impli_table, *impli_end)) + goto err; + } +#pragma GCC diagnostic pop + } /* System Versioning end */ + view= lex->unlink_first_table(&link_to_local); if (check_db_dir_existence(view->db)) @@ -607,14 +741,22 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, view->table_name, item->name.str) & VIEW_ANY_ACL); - if (fld && !fld->field->table->s->tmp_table) + if (!fld) + continue; + TABLE_SHARE *s= fld->field->table->s; + const LString_i field_name= fld->field->field_name; + if (s->tmp_table || + (s->versioned && + (field_name == s->vers_start_field()->field_name || + field_name == s->vers_end_field()->field_name))) { + continue; + } - final_priv&= fld->have_privileges; + final_priv&= fld->have_privileges; - if (~fld->have_privileges & priv) - report_item= item; - } + if (~fld->have_privileges & priv) + report_item= item; } } @@ -2017,7 +2159,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) RETURN FALSE OK - TRUE error (is not sent to cliet) + TRUE error (is not sent to client) */ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) @@ -2034,7 +2176,15 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) { Item_field *fld; if ((fld= entry->item->field_for_view_update())) + { + TABLE_SHARE *s= fld->context->table_list->table->s; + LString_i field_name= fld->field_name; + if (s->versioned && + (field_name == s->vers_start_field()->field_name || + field_name == s->vers_end_field()->field_name)) + continue; list->push_back(fld, thd->mem_root); + } else { my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT"); @@ -2045,7 +2195,7 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) } /* - checking view md5 check suum + checking view md5 check sum SINOPSYS view_checksum() diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 67b73dea506..22dfacc59d8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -67,6 +67,7 @@ #include "lex_token.h" #include "sql_lex.h" #include "sql_sequence.h" +#include "vers_utils.h" /* this is to get the bison compilation windows warnings out */ #ifdef _MSC_VER @@ -752,6 +753,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) %} %union { + bool BOOL; int num; ulong ulong_num; ulonglong ulonglong_number; @@ -856,6 +858,8 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) enum Window_frame::Frame_exclusion frame_exclusion; enum trigger_order_type trigger_action_order_type; DDL_options_st object_ddl_options; + enum vers_range_unit_t vers_range_unit; + enum Column_definition::enum_column_versioning vers_column_versioning; } %{ @@ -866,10 +870,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 102 shift/reduce conflicts. + Currently there are 115 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 102 +%expect 115 /* Comments for TOKENS. @@ -885,6 +889,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); INTERNAL : Not a real token, lex optimization OPERATOR : SQL operator FUTURE-USE : Reserved for future use + 32N2439 : Reserver keywords per ISO/IEC PDTR 19075-2, + http://jtc1sc32.org/doc/N2401-2450/32N2439-text_for_ballot-PDTR_19075-2.pdf + System Versioned Tables This makes the code grep-able, and helps maintenance. */ @@ -1098,6 +1105,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token FORCE_SYM %token FOREIGN /* SQL-2003-R */ %token FOR_SYM /* SQL-2003-R */ +%token FOR_SYSTEM_TIME_SYM /* INTERNAL */ %token FORMAT_SYM %token FOUND_SYM /* SQL-2003-R */ %token FROM @@ -1328,6 +1336,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token PARTITIONING_SYM %token PASSWORD_SYM %token PERCENT_RANK_SYM +%token PERIOD_SYM /* 32N2439 */ %token PERSISTENT_SYM %token PHASE_SYM %token PLUGINS_SYM @@ -1494,6 +1503,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SWAPS_SYM %token SWITCHES_SYM %token SYSDATE +%token SYSTEM /* 32N2439 */ +%token SYSTEM_TIME_SYM /* 32N2439 */ %token TABLES %token TABLESPACE %token TABLE_REF_PRIORITY @@ -1562,6 +1573,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token VARIANCE_SYM %token VARYING /* SQL-2003-R */ %token VAR_SAMP_SYM +%token VERSIONING_SYM /* 32N2439 */ %token VIA_SYM %token VIEW_SYM /* SQL-2003-N */ %token VIRTUAL_SYM @@ -1574,8 +1586,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token WINDOW_SYM %token WHILE_SYM %token WITH /* SQL-2003-R */ +%token WITHOUT /* SQL-2003-R */ %token WITH_CUBE_SYM /* INTERNAL */ %token WITH_ROLLUP_SYM /* INTERNAL */ +%token WITH_SYSTEM_SYM /* INTERNAL */ %token WORK_SYM /* SQL-2003-N */ %token WRAPPER_SYM %token WRITE_SYM /* SQL-2003-N */ @@ -1899,12 +1913,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); keep_gcc_happy key_using_alg part_column_list + period_for_system_time server_def server_options_list server_option definer_opt no_definer definer get_diagnostics parse_vcol_expr vcol_opt_specifier vcol_opt_attribute vcol_opt_attribute_list vcol_attribute opt_serial_attribute opt_serial_attribute_list serial_attribute - explainable_command opt_lock_wait_timeout + explainable_command opt_lock_wait_timeout asrow_attribute END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt @@ -1925,6 +1940,7 @@ END_OF_INPUT %type <num> sp_decl_idents sp_decl_idents_init_vars %type <num> sp_handler_type sp_hcond_list +%type <num> start_or_end %type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value %type <spblock> sp_decls sp_decl sp_decl_body sp_decl_variable_list %type <spname> sp_name @@ -1960,7 +1976,6 @@ END_OF_INPUT %type <frame_exclusion> opt_window_frame_exclusion; %type <window_frame_bound> window_frame_start window_frame_bound; - %type <NONE> '-' '+' '*' '/' '%' '(' ')' ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM @@ -1973,6 +1988,9 @@ END_OF_INPUT %type <lex_str_list> opt_with_column_list +%type <vers_range_unit> opt_trans_or_timestamp +%type <BOOL> opt_for_system_time_clause +%type <vers_column_versioning> with_or_without_system %% @@ -2508,7 +2526,7 @@ create: sequence_definition())) MYSQL_YYABORT; } - opt_sequence opt_create_table_options + opt_sequence opt_create_sequence_options { LEX *lex= thd->lex; @@ -4819,7 +4837,7 @@ create_like: opt_create_select: /* empty */ {} - | opt_duplicate opt_as create_select_query_expression + | opt_duplicate opt_as create_select_query_expression opt_versioning_option ; create_select_query_expression: @@ -4959,6 +4977,10 @@ part_type_def: { Lex->part_info->part_type= LIST_PARTITION; } | LIST_SYM part_column_list { Lex->part_info->part_type= LIST_PARTITION; } + | SYSTEM_TIME_SYM + { if (Lex->part_info->vers_init_info(thd)) MYSQL_YYABORT; } + opt_versioning_interval + opt_versioning_limit ; opt_linear: @@ -5166,6 +5188,7 @@ part_definition: MYSQL_YYABORT; } p_elem->part_state= PART_NORMAL; + p_elem->id= part_info->partitions.elements - 1; part_info->curr_part_elem= p_elem; part_info->current_partition= p_elem; part_info->use_default_partitions= FALSE; @@ -5234,6 +5257,62 @@ opt_part_values: part_info->part_type= LIST_PARTITION; } part_values_in {} + | AS OF_SYM NOW_SYM + { + LEX *lex= Lex; + partition_info *part_info= lex->part_info; + partition_element *elem= part_info->curr_part_elem; + if (! lex->is_partition_management()) + { + if (part_info->part_type != VERSIONING_PARTITION) + my_yyabort_error((ER_PARTITION_WRONG_TYPE, MYF(0), + "BY SYSTEM_TIME")); + } + else + { + DBUG_ASSERT(Lex->create_last_non_select_table); + DBUG_ASSERT(Lex->create_last_non_select_table->table_name); + // FIXME: other ALTER commands? + my_yyabort_error((ER_VERS_WRONG_PARTS, MYF(0), + Lex->create_last_non_select_table->table_name)); + } + elem->type(partition_element::AS_OF_NOW); + DBUG_ASSERT(part_info->vers_info); + part_info->vers_info->now_part= elem; + if (part_info->init_column_part(thd)) + { + MYSQL_YYABORT; + } + } + | VERSIONING_SYM + { + LEX *lex= Lex; + partition_info *part_info= lex->part_info; + partition_element *elem= part_info->curr_part_elem; + if (! lex->is_partition_management()) + { + if (part_info->part_type != VERSIONING_PARTITION) + my_yyabort_error((ER_PARTITION_WRONG_TYPE, MYF(0), + "BY SYSTEM_TIME")); + } + else + { + part_info->vers_init_info(thd); + elem->id= UINT32_MAX; + } + DBUG_ASSERT(part_info->vers_info); + if (part_info->vers_info->now_part) + { + DBUG_ASSERT(Lex->create_last_non_select_table); + DBUG_ASSERT(Lex->create_last_non_select_table->table_name); + my_yyabort_error((ER_VERS_WRONG_PARTS, MYF(0), Lex->create_last_non_select_table->table_name)); + } + elem->type(partition_element::VERSIONING); + if (part_info->init_column_part(thd)) + { + MYSQL_YYABORT; + } + } | DEFAULT { LEX *lex= Lex; @@ -5479,6 +5558,7 @@ sub_part_definition: mem_alloc_error(sizeof(partition_element)); MYSQL_YYABORT; } + sub_p_elem->id= curr_part->subpartitions.elements - 1; part_info->curr_part_elem= sub_p_elem; part_info->use_default_subpartitions= FALSE; part_info->use_default_num_subpartitions= FALSE; @@ -5535,6 +5615,38 @@ opt_part_option: { Lex->part_info->curr_part_elem->part_comment= $3.str; } ; +opt_versioning_interval: + /* empty */ {} + | INTERVAL_SYM expr interval + { + partition_info *part_info= Lex->part_info; + DBUG_ASSERT(part_info->part_type == VERSIONING_PARTITION); + INTERVAL interval; + if (get_interval_value($2, $3, &interval) || + part_info->vers_set_interval(interval)) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_PART_WRONG_VALUE, MYF(0), + Lex->create_last_non_select_table->table_name, "INTERVAL"); + MYSQL_YYABORT; + } + } + ; + +opt_versioning_limit: + /* empty */ {} + | LIMIT ulonglong_num + { + partition_info *part_info= Lex->part_info; + DBUG_ASSERT(part_info->part_type == VERSIONING_PARTITION); + if (part_info->vers_set_limit($2)) + { + my_error_as(ER_VERS_WRONG_PARAMS, ER_PART_WRONG_VALUE, MYF(0), + Lex->create_last_non_select_table->table_name, "LIMIT"); + MYSQL_YYABORT; + } + } + ; + /* End of partition parser part */ @@ -5642,14 +5754,19 @@ create_or_replace: } ; -opt_create_table_options: +opt_create_sequence_options: /* empty */ | create_table_options ; -create_table_options_space_separated: - create_table_option - | create_table_option create_table_options_space_separated +opt_create_table_options: + /* empty */ + | create_table_options_versioning + ; + +alter_table_options: + create_table_option_versioning + | create_table_option_versioning alter_table_options ; create_table_options: @@ -5658,6 +5775,12 @@ create_table_options: | create_table_option ',' create_table_options ; +create_table_options_versioning: + create_table_option_versioning + | create_table_option_versioning create_table_options_versioning + | create_table_option_versioning ',' create_table_options_versioning + ; + create_table_option: ENGINE_SYM opt_equal storage_engines { @@ -5901,6 +6024,28 @@ create_table_option: { Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE; Lex->create_info.sequence= ($3 == HA_CHOICE_YES); + } + ; + +create_table_option_versioning: + create_table_option + | versioning_option + ; + +opt_versioning_option: + /* empty */ + | versioning_option + ; + +versioning_option: + WITH_SYSTEM_SYM VERSIONING_SYM + { + Lex->vers_get_info().with_system_versioning= true; + Lex->create_info.options|= HA_VERSIONED_TABLE; + } + | WITHOUT SYSTEM VERSIONING_SYM + { + Lex->vers_get_info().without_system_versioning= true; } ; @@ -6001,6 +6146,7 @@ field_list_item: column_def { } | key_def | constraint_def + | period_for_system_time ; column_def: @@ -6100,6 +6246,15 @@ constraint_def: } ; +period_for_system_time: + // If FOR_SYM is followed by SYSTEM_TIME_SYM then they are merged to: FOR_SYSTEM_TIME_SYM . + PERIOD_SYM FOR_SYSTEM_TIME_SYM '(' ident ',' ident ')' + { + Vers_parse_info &info= Lex->vers_get_info(); + info.set_period_for_system_time($4, $6); + } + ; + opt_check_constraint: /* empty */ { $$= (Virtual_column_info*) 0; } | check_constraint { $$= $1;} @@ -6185,6 +6340,15 @@ opt_serial_attribute_list: | serial_attribute ; +opt_asrow_attribute: + /* empty */ {} + | opt_asrow_attribute_list {} + ; + +opt_asrow_attribute_list: + opt_asrow_attribute_list asrow_attribute {} + | asrow_attribute + ; field_def: opt_attribute @@ -6194,6 +6358,44 @@ field_def: Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps } vcol_opt_specifier vcol_opt_attribute + | opt_generated_always AS ROW_SYM start_or_end opt_asrow_attribute + { + LEX *lex= Lex; + Vers_parse_info &info= lex->vers_get_info(); + const LEX_CSTRING &field_name= lex->last_field->field_name; + + LString_i *p; + const char* clause; + switch ($4) + { + case 1: + p= &info.as_row.start; + clause= "AS ROW START"; + lex->last_field->flags|= VERS_SYS_START_FLAG; + break; + case 0: + p= &info.as_row.end; + clause= "AS ROW END"; + lex->last_field->flags|= VERS_SYS_END_FLAG; + break; + default: + /* Not Reachable */ + MYSQL_YYABORT; + break; + } + DBUG_ASSERT(p); + *p= field_name; + if (lex->last_field->implicit_not_null) + { + lex->last_field->flags&= ~NOT_NULL_FLAG; + lex->last_field->implicit_not_null= false; + } + } + ; + +start_or_end: + START_SYM { $$ = 1; } + | END { $$ = 0; } ; opt_generated_always: @@ -6426,7 +6628,10 @@ field_type_temporal: Unless --explicit-defaults-for-timestamp is given. */ if (!opt_explicit_defaults_for_timestamp) + { Lex->last_field->flags|= NOT_NULL_FLAG; + Lex->last_field->implicit_not_null= true; + } $$.set(opt_mysql56_temporal_format ? static_cast<const Type_handler*>(&type_handler_timestamp2): static_cast<const Type_handler*>(&type_handler_timestamp), @@ -6617,7 +6822,11 @@ opt_attribute_list: ; attribute: - NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; } + NULL_SYM + { + Lex->last_field->flags&= ~ NOT_NULL_FLAG; + Lex->last_field->implicit_not_null= false; + } | DEFAULT column_default_expr { Lex->last_field->default_value= $2; } | ON UPDATE_SYM NOW_SYM opt_default_time_precision { @@ -6653,15 +6862,35 @@ opt_compression_method: | equal ident { $$= $2.str; } ; -serial_attribute: - not NULL_SYM { Lex->last_field->flags|= NOT_NULL_FLAG; } +asrow_attribute: + not NULL_SYM + { + Lex->last_field->flags|= NOT_NULL_FLAG; + Lex->last_field->implicit_not_null= false; + } | opt_primary KEY_SYM { LEX *lex=Lex; lex->last_field->flags|= PRI_KEY_FLAG | NOT_NULL_FLAG; lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX; } - | vcol_attribute + | UNIQUE_SYM + { + LEX *lex=Lex; + lex->last_field->flags|= UNIQUE_KEY_FLAG; + lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX; + } + | UNIQUE_SYM KEY_SYM + { + LEX *lex=Lex; + lex->last_field->flags|= UNIQUE_KEY_FLAG; + lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX; + } + | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; } + ; + +serial_attribute: + asrow_attribute | IDENT_sys equal TEXT_STRING_sys { if ($3.length > ENGINE_OPTION_MAX_LENGTH) @@ -6689,6 +6918,24 @@ serial_attribute: new (thd->mem_root) engine_option_value($1, &Lex->last_field->option_list, &Lex->option_list_last); } + | with_or_without_system VERSIONING_SYM + { + Lex->last_field->versioning= $1; + Lex->create_info.options|= HA_VERSIONED_TABLE; + } + ; + +with_or_without_system: + WITH_SYSTEM_SYM + { + Lex->create_info.vers_info.versioned_fields= true; + $$= Column_definition::WITH_VERSIONING; + } + | WITHOUT SYSTEM + { + Lex->create_info.vers_info.unversioned_fields= true; + $$= Column_definition::WITHOUT_VERSIONING; + } ; @@ -7647,6 +7894,9 @@ alter_list_item: Lex->create_last_non_select_table= Lex->last_table(); Lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX; } + | ADD period_for_system_time + { + } | add_column '(' create_field_list ')' { Lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN | @@ -7790,7 +8040,7 @@ alter_list_item: MYSQL_YYABORT; Lex->alter_info.flags|= Alter_info::ALTER_OPTIONS; } - | create_table_options_space_separated + | alter_table_options { LEX *lex=Lex; lex->alter_info.flags|= Alter_info::ALTER_OPTIONS; @@ -8666,6 +8916,7 @@ table_expression: opt_group_clause opt_having_clause opt_window_clause + opt_system_time_clause ; opt_table_expression: @@ -8700,6 +8951,85 @@ select_options: } ; +opt_trans_or_timestamp: + /* empty */ + { + $$ = UNIT_AUTO; + } + | TRANSACTION_SYM + { + $$ = UNIT_TRX_ID; + } + | TIMESTAMP + { + $$ = UNIT_TIMESTAMP; + } + ; + +opt_system_time_clause: + /* empty */ + {} + | SYSTEM_TIME_SYM system_time_expr + { + DBUG_ASSERT(Select); + int used= 0; + if (Lex->vers_conditions) + { + for (TABLE_LIST *table= Select->table_list.first; table; table= table->next_local) + { + if (!table->vers_conditions) + { + table->vers_conditions= Lex->vers_conditions; + used++; + } + } + if (!used) + { + my_yyabort_error((ER_VERS_UNUSED_CLAUSE, MYF(0), "SYSTEM_TIME")); + } + } + } + ; + +opt_for_system_time_clause: + /* empty */ + { + $$= false; + } + | FOR_SYSTEM_TIME_SYM system_time_expr + { + $$= true; + } + ; + +system_time_expr: + AS OF_SYM opt_trans_or_timestamp simple_expr + { + Lex->vers_conditions.init(FOR_SYSTEM_TIME_AS_OF, $3, $4); + } + | AS OF_SYM NOW_SYM + { + Item *item= new (thd->mem_root) Item_func_now_local(thd, 6); + if (item == NULL) + MYSQL_YYABORT; + Lex->vers_conditions.init(FOR_SYSTEM_TIME_AS_OF, UNIT_TIMESTAMP, item); + } + | ALL + { + Lex->vers_conditions.init(FOR_SYSTEM_TIME_ALL); + } + | FROM opt_trans_or_timestamp simple_expr + TO_SYM opt_trans_or_timestamp simple_expr + { + Lex->vers_conditions.init(FOR_SYSTEM_TIME_FROM_TO, $2, $3, $5, $6); + } + | BETWEEN_SYM opt_trans_or_timestamp simple_expr + AND_SYM opt_trans_or_timestamp simple_expr + { + Lex->vers_conditions.init(FOR_SYSTEM_TIME_BETWEEN, $2, $3, $5, $6); + } + ; + select_option_list: select_option_list select_option | select_option @@ -11100,12 +11430,13 @@ table_factor: table_primary_ident: { + DBUG_ASSERT(Select); SELECT_LEX *sel= Select; sel->table_join_options= 0; } - table_ident opt_use_partition opt_table_alias opt_key_definition + table_ident opt_use_partition opt_for_system_time_clause opt_table_alias opt_key_definition { - if (!($$= Select->add_table_to_list(thd, $2, $4, + if (!($$= Select->add_table_to_list(thd, $2, $5, Select->get_table_join_options(), YYPS->m_lock_type, YYPS->m_mdl_type, @@ -11113,6 +11444,8 @@ table_primary_ident: $3))) MYSQL_YYABORT; Select->add_joined_table($$); + if ($4) + $$->vers_conditions= Lex->vers_conditions; } ; @@ -11135,11 +11468,11 @@ table_primary_ident: */ table_primary_derived: - '(' get_select_lex select_derived_union ')' opt_table_alias + '(' get_select_lex select_derived_union ')' opt_for_system_time_clause opt_table_alias { /* Use $2 instead of Lex->current_select as derived table will alter value of Lex->current_select. */ - if (!($3 || $5) && $2->embedding && + if (!($3 || $6) && $2->embedding && !$2->embedding->nested_join->join_list.elements) { /* we have a derived table ($3 == NULL) but no alias, @@ -11162,7 +11495,7 @@ table_primary_derived: if (ti == NULL) MYSQL_YYABORT; if (!($$= sel->add_table_to_list(thd, - ti, $5, 0, + ti, $6, 0, TL_READ, MDL_SHARED_READ))) MYSQL_YYABORT; @@ -11170,7 +11503,7 @@ table_primary_derived: lex->pop_context(); lex->nest_level--; } - else if ($5 != NULL) + else if ($6 != NULL) { /* Tables with or without joins within parentheses cannot @@ -11194,11 +11527,13 @@ table_primary_derived: if ($$ && $$->derived && !$$->derived->first_select()->next_select()) $$->select_lex->add_where_field($$->derived->first_select()); + if ($5) + $$->vers_conditions= Lex->vers_conditions; } /* Represents derived table with WITH clause */ | '(' get_select_lex subselect_start with_clause query_expression_body - subselect_end ')' opt_table_alias + subselect_end ')' opt_for_system_time_clause opt_table_alias { LEX *lex=Lex; SELECT_LEX *sel= $2; @@ -11209,10 +11544,12 @@ table_primary_derived: $5->set_with_clause($4); lex->current_select= sel; if (!($$= sel->add_table_to_list(lex->thd, - ti, $8, 0, + ti, $9, 0, TL_READ, MDL_SHARED_READ))) MYSQL_YYABORT; sel->add_joined_table($$); + if ($8) + $$->vers_conditions= Lex->vers_conditions; } ; @@ -12810,8 +13147,17 @@ opt_delete_option: | IGNORE_SYM { Lex->ignore= 1; } ; +truncate_end: + opt_lock_wait_timeout + | TO_SYM SYSTEM_TIME_SYM opt_trans_or_timestamp simple_expr + { + Lex->vers_conditions.init(FOR_SYSTEM_TIME_BEFORE, $3, $4); + Lex->last_table()->vers_conditions= Lex->vers_conditions; + } + ; + truncate: - TRUNCATE_SYM opt_table_sym + TRUNCATE_SYM { LEX* lex= Lex; lex->sql_command= SQLCOM_TRUNCATE; @@ -12822,7 +13168,7 @@ truncate: YYPS->m_lock_type= TL_WRITE; YYPS->m_mdl_type= MDL_EXCLUSIVE; } - table_name opt_lock_wait_timeout + opt_table_sym table_name truncate_end { LEX* lex= thd->lex; DBUG_ASSERT(!lex->m_sql_cmd); @@ -13117,13 +13463,21 @@ show_param: Lex->set_command(SQLCOM_SHOW_CREATE_DB, $3); Lex->name= $4; } - | CREATE TABLE_SYM table_ident + | CREATE TABLE_SYM table_ident opt_for_system_time_clause { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; if (!lex->select_lex.add_table_to_list(thd, $3, NULL,0)) MYSQL_YYABORT; lex->create_info.storage_media= HA_SM_DEFAULT; + + if (lex->vers_conditions.type != FOR_SYSTEM_TIME_UNSPECIFIED && + lex->vers_conditions.type != FOR_SYSTEM_TIME_AS_OF) + { + my_yyabort_error((ER_VERS_RANGE_PROHIBITED, MYF(0))); + } + if ($4) + Lex->last_table()->vers_conditions= Lex->vers_conditions; } | CREATE VIEW_SYM table_ident { @@ -15399,6 +15753,12 @@ set_expr_or_default: if ($$ == NULL) MYSQL_YYABORT; } + | DROP + { + $$=new (thd->mem_root) Item_string_sys(thd, "DROP", 4); + if ($$ == NULL) + MYSQL_YYABORT; + } ; /* Lock function */ @@ -15781,6 +16141,7 @@ object_privilege: | EVENT_SYM { Lex->grant |= EVENT_ACL;} | TRIGGER_SYM { Lex->grant |= TRIGGER_ACL; } | CREATE TABLESPACE { Lex->grant |= CREATE_TABLESPACE_ACL; } + | DELETE_SYM VERSIONING_SYM ROWS_SYM { Lex->grant |= DELETE_VERSIONING_ROWS_ACL; } ; opt_and: @@ -16532,9 +16893,14 @@ trigger_tail: } table_ident /* $10 */ FOR_SYM - remember_name /* $12 */ - { /* $13 */ - Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start(); + remember_name /* $13 */ + { /* $14 */ + /* + FOR token is already passed through (see 'case FOR_SYM' in sql_lex.cc), + so we use _prev() to get it back. + */ + DBUG_ASSERT(YYLIP->lookahead_token >= 0); + Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start_prev(); } EACH_SYM ROW_SYM diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index db45414fd28..b8c60ff8830 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -507,6 +507,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token FORCE_SYM %token FOREIGN /* SQL-2003-R */ %token FOR_SYM /* SQL-2003-R */ +%token FOR_SYSTEM_TIME_SYM /* INTERNAL */ %token FORMAT_SYM %token FOUND_SYM /* SQL-2003-R */ %token FROM @@ -737,6 +738,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token PARTITIONING_SYM %token PASSWORD_SYM %token PERCENT_RANK_SYM +%token PERIOD_SYM /* 32N2439 */ %token PERSISTENT_SYM %token PHASE_SYM %token PLUGINS_SYM @@ -903,6 +905,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SWAPS_SYM %token SWITCHES_SYM %token SYSDATE +%token SYSTEM /* 32N2439 */ +%token SYSTEM_TIME_SYM /* 32N2439 */ %token TABLES %token TABLESPACE %token TABLE_REF_PRIORITY @@ -971,6 +975,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token VARIANCE_SYM %token VARYING /* SQL-2003-R */ %token VAR_SAMP_SYM +%token VERSIONING_SYM /* 32N2439 */ %token VIA_SYM %token VIEW_SYM /* SQL-2003-N */ %token VIRTUAL_SYM @@ -983,8 +988,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token WINDOW_SYM %token WHILE_SYM %token WITH /* SQL-2003-R */ +%token WITHOUT /* SQL-2003-R */ %token WITH_CUBE_SYM /* INTERNAL */ %token WITH_ROLLUP_SYM /* INTERNAL */ +%token WITH_SYSTEM_SYM /* INTERNAL */ %token WORK_SYM /* SQL-2003-N */ %token WRAPPER_SYM %token WRITE_SYM /* SQL-2003-N */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e5f9be5c769..afa4e30ba81 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -387,6 +387,40 @@ static Sys_var_charptr Sys_my_bind_addr( READ_ONLY GLOBAL_VAR(my_bind_addr_str), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(0)); +static Sys_var_vers_asof Sys_vers_current_time( + "versioning_current_timestamp", "Default AS OF value for versioned tables", + SESSION_VAR(vers_current_time), CMD_LINE(REQUIRED_ARG, OPT_VERS_CURRENT_TIME), + IN_FS_CHARSET, DEFAULT("now")); + +static Sys_var_mybool Sys_vers_force( + "versioning_force", "Force system versioning for all created tables", + SESSION_VAR(vers_force), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static const char *vers_hide_keywords[]= {"AUTO", "IMPLICIT", "FULL", "NEVER", NullS}; +static Sys_var_enum Sys_vers_hide( + "versioning_hide", "Hide system versioning from being displayed in table info. " + "AUTO: hide implicit system fields only in non-versioned and AS OF queries; " + "IMPLICIT: hide implicit system fields in all queries; " + "FULL: hide any system fields in all queries and hide versioning info in SHOW commands; " + "NEVER: don't hide system fields", + SESSION_VAR(vers_hide), CMD_LINE(OPT_ARG), vers_hide_keywords, DEFAULT(VERS_HIDE_AUTO)); + +static Sys_var_mybool Sys_vers_innodb_algorithm_simple( + "versioning_innodb_algorithm_simple", + "Use simple algorithm of timestamp handling in InnoDB instead of TRX_SEES", + SESSION_VAR(vers_innodb_algorithm_simple), CMD_LINE(OPT_ARG), + DEFAULT(TRUE)); + +static const char *vers_alter_history_keywords[]= {"KEEP", "SURVIVE", "DROP", + NULL}; +static Sys_var_enum Sys_vers_alter_history( + "versioning_alter_history", "Versioning ALTER TABLE mode. " + "KEEP: leave historical system rows as is on ALTER TABLE; " + "SURVIVE: use DDL survival feature; " + "DROP: delete historical system rows on ALTER TABLE", + SESSION_VAR(vers_alter_history), CMD_LINE(OPT_ARG), + vers_alter_history_keywords, DEFAULT(VERS_ALTER_HISTORY_KEEP)); + static Sys_var_ulonglong Sys_binlog_cache_size( "binlog_cache_size", "The size of the transactional cache for " "updates to transactional engines for the binary log. " diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index 706240727c5..a302bbaa837 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -77,6 +77,11 @@ #define GET_HA_ROWS GET_ULONG #endif +// Disable warning caused by SESSION_VAR() macro +#ifdef __clang__ +#pragma clang diagnostic ignored "-Winvalid-offsetof" +#endif + /* special assert for sysvars. Tells the name of the variable, and fails even in non-debug builds. @@ -2597,3 +2602,131 @@ public: bool global_update(THD *thd, set_var *var); uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base); }; + + +class Sys_var_vers_asof: public sys_var +{ +public: + Sys_var_vers_asof(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, 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) + { + option.var_type|= GET_STR; + if (global_update(def_val)) + { + DBUG_ASSERT(false); + } + } + + bool do_check(THD *thd, set_var *var) + { return false; } + + bool update(String &in, st_vers_current_time &out) + { + if (in.length() == 3 && 0 == my_strcasecmp(in.charset(), "ALL", in.ptr())) + { + out.type= FOR_SYSTEM_TIME_ALL; + } + else if (in.length() == 3 && 0 == my_strcasecmp(in.charset(), "NOW", in.ptr())) + { + out.type= FOR_SYSTEM_TIME_UNSPECIFIED; + } + else + { + MYSQL_TIME_STATUS status; + if (str_to_datetime(in.ptr(), in.length(), &out.ltime, flags, &status) || + out.ltime.time_type != MYSQL_TIMESTAMP_DATETIME || + (status.warnings & ~MYSQL_TIME_NOTE_TRUNCATED) != 0) + { + return true; + } + out.type= FOR_SYSTEM_TIME_AS_OF; + } + return false; + } + bool update(THD *thd, set_var *var, st_vers_current_time &out) + { + Item *item= var->value; + + switch (item->result_type()) + { + case TIME_RESULT: + { + if (item->get_date(&out.ltime, 0)) + break; + out.type= FOR_SYSTEM_TIME_AS_OF; + return false; + } + + case STRING_RESULT: + { + String *str= item->val_str(); + if (!str || update(*str, out)) + break; + return false; + } + default: + break; + } + String *str= item->val_str(); + const char *cstr= str ? str->c_ptr_safe() : "NULL"; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, cstr); + return true; + } + bool global_update(const char *in) + { + String s(in, &my_charset_utf8_general_ci); + return update(s, global_var(st_vers_current_time)); + } + bool option_updated() + { + return global_update(global_var(st_vers_current_time).str_value); + } + bool global_update(THD *thd, set_var *var) + { + return update(thd, var, global_var(st_vers_current_time)); + } + bool session_update(THD *thd, set_var *var) + { + return update(thd, var, session_var(thd, st_vers_current_time)); + } + uchar *valptr(THD *thd, st_vers_current_time &val) + { + switch (val.type) + { + case FOR_SYSTEM_TIME_UNSPECIFIED: + return (uchar*) thd->strdup("NOW"); + case FOR_SYSTEM_TIME_ALL: + return (uchar*) thd->strdup("ALL"); + case FOR_SYSTEM_TIME_AS_OF: + { + uchar *buf= (uchar*) thd->alloc(MAX_DATE_STRING_REP_LENGTH); + if (buf) + { + if (!my_datetime_to_str(&val.ltime, (char*) buf, 6)) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "vers_current_time", "NULL (wrong datetime)"); + return (uchar*) thd->strdup("Error: wrong datetime"); + } + } + return buf; + } + default: + break; + } + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "vers_current_time", "NULL (wrong range type)"); + return (uchar*) thd->strdup("Error: wrong range type"); + } + 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) + { return valptr(thd, session_var(thd, st_vers_current_time)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(st_vers_current_time)); } + uchar *default_value_ptr(THD *thd) + { return (uchar *)option.def_value; } +}; diff --git a/sql/table.cc b/sql/table.cc index 6d32440bb11..6155af12182 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -420,6 +420,9 @@ void TABLE_SHARE::destroy() DBUG_ENTER("TABLE_SHARE::destroy"); DBUG_PRINT("info", ("db: %s table: %s", db.str, table_name.str)); + if (versioned) + vers_destroy(); + if (ha_share) { delete ha_share; @@ -1191,6 +1194,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, uint len; uint ext_key_parts= 0; plugin_ref se_plugin= 0; + const uchar *system_period= 0; + bool vtmd_used= false; + share->vtmd= false; + const uchar *extra2_field_flags= 0; + size_t extra2_field_flags_length= 0; + MEM_ROOT *old_root= thd->mem_root; Virtual_column_info **table_check_constraints; DBUG_ENTER("TABLE_SHARE::init_from_binary_frm_image"); @@ -1226,7 +1235,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (*extra2 != '/') // old frm had '/' there { const uchar *e2end= extra2 + len; - while (extra2 + 3 < e2end) + while (extra2 + 3 <= e2end) { uchar type= *extra2++; size_t length= *extra2++; @@ -1284,6 +1293,25 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } #endif /*HAVE_SPATIAL*/ break; + case EXTRA2_PERIOD_FOR_SYSTEM_TIME: + if (system_period || length != 2 * sizeof(uint16)) + goto err; + system_period = extra2; + break; + case EXTRA2_FIELD_FLAGS: + if (extra2_field_flags) + goto err; + extra2_field_flags= extra2; + extra2_field_flags_length= length; + break; + case EXTRA2_VTMD: + if (vtmd_used) + goto err; + share->vtmd= *extra2; + if (share->vtmd) + share->table_category= TABLE_CATEGORY_LOG; + vtmd_used= true; + break; default: /* abort frm parsing if it's an unknown but important extra2 value */ if (type >= EXTRA2_ENGINE_IMPORTANT) @@ -1602,6 +1630,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, disk_buff= frm_image + pos + FRM_FORMINFO_SIZE; share->fields= uint2korr(forminfo+258); + if (extra2_field_flags && extra2_field_flags_length != share->fields) + goto err; pos= uint2korr(forminfo+260); /* Length of all screens */ n_length= uint2korr(forminfo+268); interval_count= uint2korr(forminfo+270); @@ -1733,6 +1763,27 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, strpos, vcol_screen_pos); } + /* Set system versioning information. */ + if (system_period == NULL) + { + versioned= false; + row_start_field = 0; + row_end_field = 0; + } + else + { + DBUG_PRINT("info", ("Setting system versioning informations")); + uint16 row_start= uint2korr(system_period); + uint16 row_end= uint2korr(system_period + sizeof(uint16)); + if (row_start >= share->fields || row_end >= share->fields) + goto err; + DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, row_end)); + versioned= true; + vers_init(); + row_start_field= row_start; + row_end_field= row_end; + } // if (system_period == NULL) + for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++) { uint pack_flag, interval_nr, unireg_type, recpos, field_length; @@ -1747,6 +1798,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, uint gis_length, gis_decimals, srid= 0; Field::utype unireg_check; const Type_handler *handler; + uint32 flags= 0; if (new_frm_ver >= 3) { @@ -1956,6 +2008,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, swap_variables(uint, null_bit_pos, mysql57_vcol_null_bit_pos); } + if (versioned) + { + if (i == row_start_field) + flags|= VERS_SYS_START_FLAG; + else if (i == row_end_field) + flags|= VERS_SYS_END_FLAG; + } + /* Convert pre-10.2.2 timestamps to use Field::default_value */ unireg_check= (Field::utype) MTYP_TYPENR(unireg_type); name.str= fieldnames.type_names[i]; @@ -1967,7 +2027,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, null_pos, null_bit_pos, pack_flag, handler, charset, geom_type, srid, unireg_check, (interval_nr ? share->intervals+interval_nr-1 : NULL), - &name); + &name, flags); if (!reg_field) // Not supported field type goto err; @@ -1983,6 +2043,15 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, reg_field->field_index= i; reg_field->comment=comment; reg_field->vcol_info= vcol_info; + reg_field->flags|= flags; + if (extra2_field_flags) + { + uchar flags= *extra2_field_flags++; + if (flags & VERS_OPTIMIZED_UPDATE) + reg_field->flags|= VERS_OPTIMIZED_UPDATE_FLAG; + if (flags & HIDDEN) + reg_field->flags|= HIDDEN_FLAG; + } if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag)) { null_bits_are_used= 1; @@ -2553,19 +2622,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, bitmap_clear_all(share->check_set); } - delete handler_file; #ifndef DBUG_OFF if (use_hash) (void) my_hash_check(&share->name_hash); #endif share->db_plugin= se_plugin; + delete handler_file; + share->error= OPEN_FRM_OK; thd->status_var.opened_shares++; thd->mem_root= old_root; DBUG_RETURN(0); - err: +err: + share->db_plugin= NULL; share->error= OPEN_FRM_CORRUPTED; share->open_errno= my_errno; delete handler_file; @@ -3073,25 +3144,30 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, records=0; if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN)) records=1; - if (prgflag & (READ_ALL+EXTRA_RECORD)) + if (prgflag & (READ_ALL + EXTRA_RECORD)) + { records++; - - if (!(record= (uchar*) alloc_root(&outparam->mem_root, - share->rec_buff_length * records))) - goto err; /* purecov: inspected */ + if (share->versioned) + records++; + } if (records == 0) { /* We are probably in hard repair, and the buffers should not be used */ - outparam->record[0]= outparam->record[1]= share->default_values; + record= share->default_values; } else { - outparam->record[0]= record; - if (records > 1) - outparam->record[1]= record+ share->rec_buff_length; - else - outparam->record[1]= outparam->record[0]; // Safety + if (!(record= (uchar*) alloc_root(&outparam->mem_root, + share->rec_buff_length * records))) + goto err; /* purecov: inspected */ + } + + for (i= 0; i < 3;) + { + outparam->record[i]= record; + if (++i < records) + record+= share->rec_buff_length; } if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root, @@ -3116,6 +3192,26 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, } (*field_ptr)= 0; // End marker + if (share->versioned) + { + Field **fptr = NULL; + if (!(fptr = (Field **) alloc_root(&outparam->mem_root, + (uint) ((share->fields+1)* + sizeof(Field*))))) + goto err; + + outparam->non_generated_field = fptr; + for (i=0 ; i < share->fields; i++) + { + if (outparam->field[i]->vers_sys_field()) + continue; + *fptr++ = outparam->field[i]; + } + (*fptr)= 0; // End marker + } + else + outparam->non_generated_field= NULL; + if (share->found_next_number_field) outparam->found_next_number_field= outparam->field[(uint) (share->found_next_number_field - share->field)]; @@ -3207,6 +3303,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, } #ifdef WITH_PARTITION_STORAGE_ENGINE + bool work_part_info_used; if (share->partition_info_str_len && outparam->file) { /* @@ -3227,7 +3324,6 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, thd->set_n_backup_active_arena(&part_func_arena, &backup_arena); thd->stmt_arena= &part_func_arena; bool tmp; - bool work_part_info_used; tmp= mysql_unpack_partition(thd, share->partition_info_str, share->partition_info_str_len, @@ -3387,6 +3483,38 @@ partititon_err: if (share->no_replicate || !binlog_filter->db_ok(share->db.str)) share->can_do_row_logging= 0; // No row based replication +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (outparam->part_info && + outparam->part_info->part_type == VERSIONING_PARTITION) + { + Query_arena *backup_stmt_arena_ptr= thd->stmt_arena; + Query_arena backup_arena; + Query_arena part_func_arena(&outparam->mem_root, + Query_arena::STMT_INITIALIZED); + if (!work_part_info_used) + { + thd->set_n_backup_active_arena(&part_func_arena, &backup_arena); + thd->stmt_arena= &part_func_arena; + } + + bool err= outparam->part_info->vers_setup_stats(thd, is_create_table); + + if (!work_part_info_used) + { + thd->stmt_arena= backup_stmt_arena_ptr; + thd->restore_active_arena(&part_func_arena, &backup_arena); + } + + if (err) + { + outparam->file->ha_close(); + error= OPEN_FRM_OPEN_ERROR; + error_reported= true; + goto err; + } + } +#endif + /* Increment the opened_tables counter, only when open flags set. */ if (db_stat) thd->status_var.opened_tables++; @@ -4634,16 +4762,19 @@ bool TABLE_LIST::create_field_translation(THD *thd) */ if (is_view() && get_unit()->prepared && !field_translation_updated) { + field_translation_updated= TRUE; + if (field_translation_end - field_translation < select->item_list.elements) + goto allocate; while ((item= it++)) { field_translation[field_count++].item= item; } - field_translation_updated= TRUE; } DBUG_RETURN(FALSE); } +allocate: arena= thd->activate_stmt_arena_if_needed(&backup); /* Create view fields translation table */ @@ -6285,6 +6416,15 @@ void TABLE::mark_columns_needed_for_delete() if (need_signal) file->column_bitmaps_signal(); + + /* + For System Versioning we have to write and read Sys_end. + */ + if (s->versioned) + { + bitmap_set_bit(read_set, s->vers_end_field()->field_index); + bitmap_set_bit(write_set, s->vers_end_field()->field_index); + } } @@ -6361,6 +6501,15 @@ void TABLE::mark_columns_needed_for_update() need_signal= true; } } + /* + For System Versioning we have to read all columns since we will store + a copy of previous row with modified Sys_end column back to a table. + */ + if (s->versioned) + { + // We will copy old columns to a new row. + use_all_columns(); + } if (check_constraints) { mark_check_constraint_columns_for_read(); @@ -7546,6 +7695,41 @@ int TABLE::update_default_fields(bool update_command, bool ignore_errors) DBUG_RETURN(res); } +void TABLE::vers_update_fields() +{ + DBUG_ENTER("vers_update_fields"); + + bitmap_set_bit(write_set, vers_start_field()->field_index); + bitmap_set_bit(write_set, vers_end_field()->field_index); + + if (vers_start_field()->set_time()) + DBUG_ASSERT(0); + vers_end_field()->set_max(); + + DBUG_VOID_RETURN; +} + + +bool TABLE_LIST::vers_vtmd_name(String& out) const +{ + static const char *vtmd_suffix= "_vtmd"; + static const size_t vtmd_suffix_len= strlen(vtmd_suffix); + if (table_name_length > NAME_CHAR_LEN - vtmd_suffix_len) + { + my_printf_error(ER_VERS_VTMD_ERROR, "Table name is longer than %d characters", MYF(0), int(NAME_CHAR_LEN - vtmd_suffix_len)); + return true; + } + out.set(table_name, table_name_length, table_alias_charset); + if (out.append(vtmd_suffix, vtmd_suffix_len + 1)) + { + my_message(ER_VERS_VTMD_ERROR, "Failed allocate VTMD name", MYF(0)); + return true; + } + out.length(out.length() - 1); + return false; +} + + /** Reset markers that fields are being updated */ @@ -8291,6 +8475,24 @@ LEX_CSTRING *fk_option_name(enum_fk_option opt) return names + opt; } +void vers_select_conds_t::resolve_units(bool timestamps_only) +{ + DBUG_ASSERT(type != FOR_SYSTEM_TIME_UNSPECIFIED); + DBUG_ASSERT(start); + if (unit_start == UNIT_AUTO) + { + unit_start= (!timestamps_only && (start->result_type() == INT_RESULT || + start->result_type() == REAL_RESULT)) ? + UNIT_TRX_ID : UNIT_TIMESTAMP; + } + if (end && unit_end == UNIT_AUTO) + { + unit_end= (!timestamps_only && (end->result_type() == INT_RESULT || + end->result_type() == REAL_RESULT)) ? + UNIT_TRX_ID : UNIT_TIMESTAMP; + } +} + Field *TABLE::find_field_by_name(LEX_CSTRING *str) const { diff --git a/sql/table.h b/sql/table.h index 94a161eefba..9c4f6cb6527 100644 --- a/sql/table.h +++ b/sql/table.h @@ -561,6 +561,11 @@ struct TABLE_STATISTICS_CB bool histograms_are_read; }; +class Vers_min_max_stats; + +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif /** This structure is shared between different table objects. There is one @@ -737,6 +742,57 @@ struct TABLE_SHARE #endif /** + System versioning support. + */ + + bool versioned; + bool vtmd; + uint16 row_start_field; + uint16 row_end_field; + uint32 hist_part_id; + Vers_min_max_stats** stat_trx; + ulonglong stat_serial; // guards check_range_constants() updates + + bool busy_rotation; + mysql_mutex_t LOCK_rotation; + mysql_cond_t COND_rotation; + mysql_rwlock_t LOCK_stat_serial; + + void vers_init() + { + hist_part_id= UINT32_MAX; + busy_rotation= false; + stat_trx= NULL; + stat_serial= 0; + mysql_mutex_init(key_TABLE_SHARE_LOCK_rotation, &LOCK_rotation, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_TABLE_SHARE_COND_rotation, &COND_rotation, NULL); + mysql_rwlock_init(key_rwlock_LOCK_stat_serial, &LOCK_stat_serial); + } + + void vers_destroy() + { + mysql_mutex_destroy(&LOCK_rotation); + mysql_cond_destroy(&COND_rotation); + mysql_rwlock_destroy(&LOCK_stat_serial); + } + + Field *vers_start_field() + { + return field[row_start_field]; + } + + Field *vers_end_field() + { + return field[row_end_field]; + } + + void vers_wait_rotation() + { + while (busy_rotation) + mysql_cond_wait(&COND_rotation, &LOCK_rotation); + } + + /** Cache the checked structure of this table. The pointer data is used to describe the structure that @@ -1046,7 +1102,7 @@ public: uint32 instance; /** Table cache instance this TABLE is belonging to */ THD *in_use; /* Which thread uses this */ - uchar *record[2]; /* Pointer to records */ + uchar *record[3]; /* Pointer to records */ uchar *write_row_record; /* Used as optimisation in THD::write_row */ uchar *insert_values; /* used by INSERT ... UPDATE */ @@ -1079,6 +1135,8 @@ public: Field **default_field; /* Fields with non-constant DEFAULT */ Field *next_number_field; /* Set if next_number is activated */ Field *found_next_number_field; /* Set on open */ + Field **non_generated_field; /* Like **field but without generated + fields */ Virtual_column_info **check_constraints; /* Table's triggers, 0 if there are no of them */ @@ -1426,6 +1484,7 @@ public: int update_virtual_field(Field *vf); int update_virtual_fields(handler *h, enum_vcol_update_mode update_mode); int update_default_fields(bool update, bool ignore_errors); + void vers_update_fields(); void reset_default_fields(); inline ha_rows stat_records() { return used_stat_records; } @@ -1442,6 +1501,59 @@ public: bool with_cleanup); Field *find_field_by_name(LEX_CSTRING *str) const; bool export_structure(THD *thd, class Row_definition_list *defs); + + /** + System Versioning support + */ + + bool versioned() const + { + DBUG_ASSERT(s); + return s->versioned; + } + + /* Versioned by SQL layer */ + bool versioned_by_sql() const + { + DBUG_ASSERT(s && file); + return s->versioned && !file->native_versioned(); + } + + bool versioned_by_engine() const + { + DBUG_ASSERT(s && file); + return s->versioned && file->native_versioned(); + } + + bool vers_vtmd() const + { + DBUG_ASSERT(s); + return s->versioned && s->vtmd; + } + + Field *vers_start_field() const + { + DBUG_ASSERT(s && s->versioned); + return field[s->row_start_field]; + } + + Field *vers_end_field() const + { + DBUG_ASSERT(s && s->versioned); + return field[s->row_end_field]; + } + + int delete_row(); + +/** Number of additional fields used in versioned tables */ +#define VERSIONING_FIELDS 2 + + uint vers_user_fields() const + { + return s->versioned ? + s->fields - VERSIONING_FIELDS : + s->fields; + } }; @@ -1729,6 +1841,62 @@ class Item_in_subselect; 4) jtbm semi-join (jtbm_subselect != NULL) */ +enum vers_range_unit_t +{ + UNIT_AUTO = 0, + UNIT_TIMESTAMP, + UNIT_TRX_ID +}; + +/** last_leaf_for_name_resolutioning support. */ +struct vers_select_conds_t +{ + vers_range_type_t type; + vers_range_unit_t unit_start, unit_end; + bool import_outer:1; + bool from_inner:1; + Item *start, *end; + + void empty() + { + type= FOR_SYSTEM_TIME_UNSPECIFIED; + unit_start= unit_end= UNIT_AUTO; + import_outer= from_inner= false; + start= end= NULL; + } + + void init( + vers_range_type_t t, + vers_range_unit_t u_start= UNIT_AUTO, + Item * s= NULL, + vers_range_unit_t u_end= UNIT_AUTO, + Item * e= NULL) + { + type= t; + unit_start= u_start; + unit_end= u_end; + start= s; + end= e; + import_outer= from_inner= false; + } + + bool init_from_sysvar(THD *thd); + + bool operator== (vers_range_type_t b) + { + return type == b; + } + bool operator!= (vers_range_type_t b) + { + return type != b; + } + operator bool() const + { + return type != FOR_SYSTEM_TIME_UNSPECIFIED; + } + void resolve_units(bool timestamps_only); +}; + struct LEX; class Index_hint; struct TABLE_LIST @@ -1794,6 +1962,7 @@ struct TABLE_LIST const char *db, *alias, *table_name, *schema_table_name; const char *option; /* Used by cache index */ Item *on_expr; /* Used with outer join */ + Item *saved_on_expr; /* Used with SP and System Versioning */ Item *sj_on_expr; /* @@ -2186,6 +2355,12 @@ struct TABLE_LIST TABLE_LIST *find_underlying_table(TABLE *table); TABLE_LIST *first_leaf_for_name_resolution(); TABLE_LIST *last_leaf_for_name_resolution(); + + /* System Versioning */ + vers_select_conds_t vers_conditions; + bool vers_vtmd_name(String &out) const; + bool vers_force_alias; + /** @brief Find the bottom in the chain of embedded table VIEWs. diff --git a/sql/tztime.h b/sql/tztime.h index eb7d85c48b2..d3f19fa2fd3 100644 --- a/sql/tztime.h +++ b/sql/tztime.h @@ -89,6 +89,7 @@ extern my_time_t sec_since_epoch_TIME(MYSQL_TIME *t); static const int MY_TZ_TABLES_COUNT= 4; +extern Time_zone* thd_get_timezone(THD* thd); #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ #endif /* TZTIME_INCLUDED */ diff --git a/sql/unireg.cc b/sql/unireg.cc index 1ca0233552e..e8d94741800 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -87,6 +87,46 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, return extra2_write(pos, type, reinterpret_cast<LEX_CSTRING *>(str)); } +static const bool ROW_START = true; +static const bool ROW_END = false; + +inline +uint16 +vers_get_field(HA_CREATE_INFO *create_info, List<Create_field> &create_fields, bool row_start) +{ + DBUG_ASSERT(create_info->versioned()); + + List_iterator<Create_field> it(create_fields); + Create_field *sql_field = NULL; + + const LString_i row_field= row_start ? create_info->vers_info.as_row.start + : create_info->vers_info.as_row.end; + DBUG_ASSERT(row_field); + + for (unsigned field_no = 0; (sql_field = it++); ++field_no) + { + if (row_field == sql_field->field_name) + { + DBUG_ASSERT(field_no <= uint16(~0U)); + return uint16(field_no); + } + } + + DBUG_ASSERT(0); /* Not Reachable */ + return 0; +} + +bool has_extra2_field_flags(List<Create_field> &create_fields) +{ + List_iterator<Create_field> it(create_fields); + while (Create_field *f= it++) + { + if (f->flags & (VERS_OPTIMIZED_UPDATE_FLAG | HIDDEN_FLAG)) + return true; + } + return false; +} + /** Create a frm (table definition) file @@ -219,6 +259,22 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, if (gis_extra2_len) extra2_size+= 1 + (gis_extra2_len > 255 ? 3 : 1) + gis_extra2_len; + if (create_info->versioned()) + { + extra2_size+= 1 + 1 + 2 * sizeof(uint16); + } + + if (create_info->vtmd()) + { + extra2_size+= 1 + 1 + 1; + } + + bool has_extra2_field_flags_= has_extra2_field_flags(create_fields); + if (has_extra2_field_flags_) + { + extra2_size+= + 1 + (create_fields.elements <= 255 ? 1 : 3) + create_fields.elements; + } key_buff_length= uint4korr(fileinfo+47); @@ -275,6 +331,39 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, } #endif /*HAVE_SPATIAL*/ + if (create_info->versioned()) + { + *pos++= EXTRA2_PERIOD_FOR_SYSTEM_TIME; + *pos++= 2 * sizeof(uint16); + int2store(pos, vers_get_field(create_info, create_fields, ROW_START)); + pos+= sizeof(uint16); + int2store(pos, vers_get_field(create_info, create_fields, ROW_END)); + pos+= sizeof(uint16); + } + + if (create_info->vtmd()) + { + *pos++= EXTRA2_VTMD; + *pos++= 1; + *pos++= 1; + } + + if (has_extra2_field_flags_) + { + *pos++= EXTRA2_FIELD_FLAGS; + pos= extra2_write_len(pos, create_fields.elements); + List_iterator<Create_field> it(create_fields); + while (Create_field *field= it++) + { + uchar flags= 0; + if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG) + flags|= VERS_OPTIMIZED_UPDATE; + if (field->flags & HIDDEN_FLAG) + flags|= HIDDEN; + *pos++= flags; + } + } + int4store(pos, filepos); // end of the extra2 segment pos+= 4; @@ -960,7 +1049,8 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, field->unireg_check, field->save_interval ? field->save_interval : field->interval, - &field->field_name); + &field->field_name, + field->flags); if (!regfield) { error= 1; diff --git a/sql/unireg.h b/sql/unireg.h index b0cfb3841ef..25cb22207ad 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -172,12 +172,20 @@ enum extra2_frm_value_type { EXTRA2_TABLEDEF_VERSION=0, EXTRA2_DEFAULT_PART_ENGINE=1, EXTRA2_GIS=2, + EXTRA2_PERIOD_FOR_SYSTEM_TIME=4, + EXTRA2_FIELD_FLAGS=8, + EXTRA2_VTMD=16, #define EXTRA2_ENGINE_IMPORTANT 128 EXTRA2_ENGINE_TABLEOPTS=128, }; +enum extra2_field_flags { + VERS_OPTIMIZED_UPDATE=1, + HIDDEN=2, +}; + int rea_create_table(THD *thd, LEX_CUSTRING *frm, const char *path, const char *db, const char *table_name, HA_CREATE_INFO *create_info, handler *file, diff --git a/sql/vers_string.h b/sql/vers_string.h new file mode 100644 index 00000000000..6d501e1b81c --- /dev/null +++ b/sql/vers_string.h @@ -0,0 +1,133 @@ +#ifndef VERS_STRING_INCLUDED +#define VERS_STRING_INCLUDED + +struct Compare_strncmp +{ + int operator()(const LEX_CSTRING& a, const LEX_CSTRING& b) const + { + return strncmp(a.str, b.str, a.length); + } + static CHARSET_INFO* charset() + { + return system_charset_info; + } +}; + +template <CHARSET_INFO* &CS= system_charset_info> +struct Compare_my_strcasecmp +{ + int operator()(const LEX_CSTRING& a, const LEX_CSTRING& b) const + { + DBUG_ASSERT(a.str[a.length] == 0 && b.str[b.length] == 0); + return my_strcasecmp(CS, a.str, b.str); + } + static CHARSET_INFO* charset() + { + return CS; + } +}; + +typedef Compare_my_strcasecmp<files_charset_info> Compare_fs; +typedef Compare_my_strcasecmp<table_alias_charset> Compare_t; + +template <class Storage= LEX_CSTRING> +struct LEX_STRING_u : public Storage +{ + LEX_STRING_u() + { + Storage::str= NULL; + Storage::length= 0; + } + LEX_STRING_u(const char *_str, uint32 _len, CHARSET_INFO *) + { + Storage::str= _str; + Storage::length= _len; + } + uint32 length() const + { + return Storage::length; + } + const char *ptr() const + { + return Storage::str; + } + void set(const char *_str, uint32 _len, CHARSET_INFO *) + { + Storage::str= _str; + Storage::length= _len; + } + const LEX_CSTRING& lex_cstring() const + { + return *this; + } + const LEX_STRING& lex_string() const + { + return *(LEX_STRING *)this; + } +}; + +template <class Compare= Compare_strncmp, class Storage= LEX_STRING_u<> > +struct XString : public Storage +{ +public: + XString() {} + XString(const char *_str, size_t _len) : + Storage(_str, _len, Compare::charset()) + { + } + XString(const LEX_STRING src) : + Storage(src.str, src.length, Compare::charset()) + { + } + XString(const LEX_CSTRING src) : + Storage(src.str, src.length, Compare::charset()) + { + } + XString(const char *_str) : + Storage(_str, strlen(_str), Compare::charset()) + { + } + bool operator== (const XString& b) const + { + return Storage::length() == b.length() && 0 == Compare()(this->lex_cstring(), b.lex_cstring()); + } + bool operator!= (const XString& b) const + { + return !(*this == b); + } + operator const char* () const + { + return Storage::ptr(); + } + operator LEX_CSTRING& () const + { + return this->lex_cstring(); + } + operator LEX_STRING () const + { + LEX_STRING res; + res.str= const_cast<char *>(this->ptr()); + res.length= this->length(); + return res; + } + operator bool () const + { + return Storage::ptr() != NULL; + } +}; + +typedef XString<> LString; +typedef XString<Compare_fs> LString_fs; +typedef XString<Compare_my_strcasecmp<> > LString_i; + +typedef XString<Compare_strncmp, String> SString; +typedef XString<Compare_fs, String> SString_fs; +typedef XString<Compare_t, String> SString_t; + + +#define XSTRING_WITH_LEN(X) (X).ptr(), (X).length() +#define DB_WITH_LEN(X) (X).db, (X).db_length +#define TABLE_NAME_WITH_LEN(X) (X).table_name, (X).table_name_length + + +#endif // VERS_STRING_INCLUDED diff --git a/sql/vers_utils.h b/sql/vers_utils.h new file mode 100644 index 00000000000..948139bfa9b --- /dev/null +++ b/sql/vers_utils.h @@ -0,0 +1,68 @@ +#ifndef VERS_UTILS_INCLUDED +#define VERS_UTILS_INCLUDED + +#include "table.h" +#include "sql_class.h" +#include "vers_string.h" + +class MDL_auto_lock +{ + THD *thd; + TABLE_LIST &table; + bool error; + +public: + MDL_auto_lock(THD *_thd, TABLE_LIST &_table) : + thd(_thd), table(_table) + { + DBUG_ASSERT(thd); + table.mdl_request.init(MDL_key::TABLE, table.db, table.table_name, MDL_EXCLUSIVE, MDL_EXPLICIT); + error= thd->mdl_context.acquire_lock(&table.mdl_request, thd->variables.lock_wait_timeout); + } + ~MDL_auto_lock() + { + if (!error) + { + DBUG_ASSERT(table.mdl_request.ticket); + thd->mdl_context.release_lock(table.mdl_request.ticket); + table.mdl_request.ticket= NULL; + } + } + bool acquire_error() const { return error; } +}; + + +class Local_da : public Diagnostics_area +{ + THD *thd; + uint sql_error; + Diagnostics_area *saved_da; + +public: + Local_da(THD *_thd, uint _sql_error= 0) : + Diagnostics_area(_thd->query_id, false, true), + thd(_thd), + sql_error(_sql_error), + saved_da(_thd->get_stmt_da()) + { + thd->set_stmt_da(this); + } + ~Local_da() + { + if (saved_da) + finish(); + } + void finish() + { + DBUG_ASSERT(saved_da && thd); + thd->set_stmt_da(saved_da); + if (is_error()) + my_error(sql_error ? sql_error : sql_errno(), MYF(0), message()); + if (warn_count() > error_count()) + saved_da->copy_non_errors_from_wi(thd, get_warning_info()); + saved_da= NULL; + } +}; + + +#endif // VERS_UTILS_INCLUDED diff --git a/sql/vtmd.cc b/sql/vtmd.cc new file mode 100644 index 00000000000..b761ed54281 --- /dev/null +++ b/sql/vtmd.cc @@ -0,0 +1,687 @@ +#include "vtmd.h" +#include "sql_base.h" +#include "sql_class.h" +#include "sql_handler.h" // mysql_ha_rm_tables() +#include "sql_table.h" +#include "sql_select.h" +#include "table_cache.h" // tdc_remove_table() +#include "key.h" +#include "sql_show.h" +#include "sql_parse.h" +#include "sql_lex.h" +#include "sp_head.h" +#include "sp_rcontext.h" + +LString VERS_VTMD_TEMPLATE(C_STRING_WITH_LEN("vtmd_template")); + +bool +VTMD_table::create(THD *thd) +{ + Table_specification_st create_info; + TABLE_LIST src_table, table; + create_info.init(DDL_options_st::OPT_LIKE); + create_info.options|= HA_VTMD; + create_info.alias= vtmd_name; + table.init_one_table( + DB_WITH_LEN(about), + XSTRING_WITH_LEN(vtmd_name), + vtmd_name, + TL_READ); + src_table.init_one_table( + LEX_STRING_WITH_LEN(MYSQL_SCHEMA_NAME), + XSTRING_WITH_LEN(VERS_VTMD_TEMPLATE), + VERS_VTMD_TEMPLATE, + TL_READ); + + Query_tables_backup backup(thd); + thd->lex->sql_command= backup.get().sql_command; + thd->lex->add_to_query_tables(&src_table); + + MDL_auto_lock mdl_lock(thd, table); + if (mdl_lock.acquire_error()) + return true; + + Reprepare_observer *reprepare_observer= thd->m_reprepare_observer; + partition_info *work_part_info= thd->work_part_info; + thd->m_reprepare_observer= NULL; + thd->work_part_info= NULL; + bool rc= mysql_create_like_table(thd, &table, &src_table, &create_info); + thd->m_reprepare_observer= reprepare_observer; + thd->work_part_info= work_part_info; + return rc; +} + +bool +VTMD_table::find_record(ulonglong sys_trx_end, bool &found) +{ + int error; + key_buf_t key; + found= false; + + DBUG_ASSERT(vtmd.table); + + if (key.allocate(vtmd.table->s->max_unique_length)) + return true; + + DBUG_ASSERT(sys_trx_end); + vtmd.table->vers_end_field()->set_notnull(); + vtmd.table->vers_end_field()->store(sys_trx_end, true); + key_copy(key, vtmd.table->record[0], vtmd.table->key_info + IDX_TRX_END, 0); + + error= vtmd.table->file->ha_index_read_idx_map(vtmd.table->record[1], IDX_TRX_END, + key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT); + if (error) + { + if (error == HA_ERR_RECORD_DELETED || error == HA_ERR_KEY_NOT_FOUND) + return false; + vtmd.table->file->print_error(error, MYF(0)); + return true; + } + + restore_record(vtmd.table, record[1]); + + found= true; + return false; +} + + +bool +VTMD_table::open(THD *thd, Local_da &local_da, bool *created) +{ + if (created) + *created= false; + + if (0 == vtmd_name.length() && about.vers_vtmd_name(vtmd_name)) + return true; + + while (true) // max 2 iterations + { + vtmd.init_one_table( + DB_WITH_LEN(about), + XSTRING_WITH_LEN(vtmd_name), + vtmd_name, + TL_WRITE_CONCURRENT_INSERT); + + TABLE *res= open_log_table(thd, &vtmd, &open_tables_backup); + if (res) + return false; + + if (created && !*created && local_da.is_error() && local_da.sql_errno() == ER_NO_SUCH_TABLE) + { + local_da.reset_diagnostics_area(); + if (create(thd)) + break; + *created= true; + } + else + break; + } + return true; +} + +bool +VTMD_table::update(THD *thd, const char* archive_name) +{ + bool result= true; + bool found= false; + bool created; + int error; + size_t an_len= 0; + ulonglong save_thd_options; + { + Local_da local_da(thd, ER_VERS_VTMD_ERROR); + + save_thd_options= thd->variables.option_bits; + thd->variables.option_bits&= ~OPTION_BIN_LOG; + + if (open(thd, local_da, &created)) + goto open_error; + + if (!vtmd.table->versioned()) + { + my_message(ER_VERS_VTMD_ERROR, "VTMD is not versioned", MYF(0)); + goto quit; + } + + if (!created && find_record(ULONGLONG_MAX, found)) + goto quit; + + if ((error= vtmd.table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE))) + { + vtmd.table->file->print_error(error, MYF(0)); + goto quit; + } + + /* Honor next number columns if present */ + vtmd.table->next_number_field= vtmd.table->found_next_number_field; + + if (vtmd.table->s->fields != FIELD_COUNT) + { + my_printf_error(ER_VERS_VTMD_ERROR, "`%s.%s` unexpected fields count: %d", MYF(0), + vtmd.table->s->db.str, vtmd.table->s->table_name.str, vtmd.table->s->fields); + goto quit; + } + + if (archive_name) + { + an_len= strlen(archive_name); + vtmd.table->field[FLD_ARCHIVE_NAME]->store(archive_name, an_len, table_alias_charset); + vtmd.table->field[FLD_ARCHIVE_NAME]->set_notnull(); + } + else + { + vtmd.table->field[FLD_ARCHIVE_NAME]->set_null(); + } + vtmd.table->field[FLD_COL_RENAMES]->set_null(); + + if (found) + { + if (thd->lex->sql_command == SQLCOM_CREATE_TABLE) + { + my_printf_error(ER_VERS_VTMD_ERROR, "`%s.%s` exists and not empty!", MYF(0), + vtmd.table->s->db.str, vtmd.table->s->table_name.str); + goto quit; + } + vtmd.table->mark_columns_needed_for_update(); // not needed? + if (archive_name) + { + vtmd.table->s->versioned= false; + error= vtmd.table->file->ha_update_row(vtmd.table->record[1], vtmd.table->record[0]); + vtmd.table->s->versioned= true; + + if (!error) + { + if (thd->lex->sql_command == SQLCOM_DROP_TABLE) + { + error= vtmd.table->file->ha_delete_row(vtmd.table->record[0]); + } + else + { + DBUG_ASSERT(thd->lex->sql_command == SQLCOM_ALTER_TABLE); + ulonglong sys_trx_end= (ulonglong) vtmd.table->vers_start_field()->val_int(); + store_record(vtmd.table, record[1]); + vtmd.table->field[FLD_NAME]->store(TABLE_NAME_WITH_LEN(about), system_charset_info); + vtmd.table->field[FLD_NAME]->set_notnull(); + vtmd.table->field[FLD_ARCHIVE_NAME]->set_null(); + error= vtmd.table->file->ha_update_row(vtmd.table->record[1], vtmd.table->record[0]); + if (error) + goto err; + + DBUG_ASSERT(an_len); + while (true) + { // fill archive_name of last sequential renames + bool found; + if (find_record(sys_trx_end, found)) + goto quit; + if (!found || !vtmd.table->field[FLD_ARCHIVE_NAME]->is_null()) + break; + + store_record(vtmd.table, record[1]); + vtmd.table->field[FLD_ARCHIVE_NAME]->store(archive_name, an_len, table_alias_charset); + vtmd.table->field[FLD_ARCHIVE_NAME]->set_notnull(); + vtmd.table->s->versioned= false; + error= vtmd.table->file->ha_update_row(vtmd.table->record[1], vtmd.table->record[0]); + vtmd.table->s->versioned= true; + if (error) + goto err; + sys_trx_end= (ulonglong) vtmd.table->vers_start_field()->val_int(); + } // while (true) + } // else (thd->lex->sql_command != SQLCOM_DROP_TABLE) + } // if (!error) + } // if (archive_name) + else + { + vtmd.table->field[FLD_NAME]->store(TABLE_NAME_WITH_LEN(about), system_charset_info); + vtmd.table->field[FLD_NAME]->set_notnull(); + error= vtmd.table->file->ha_update_row(vtmd.table->record[1], vtmd.table->record[0]); + } + } // if (found) + else + { + vtmd.table->field[FLD_NAME]->store(TABLE_NAME_WITH_LEN(about), system_charset_info); + vtmd.table->field[FLD_NAME]->set_notnull(); + vtmd.table->mark_columns_needed_for_insert(); // not needed? + error= vtmd.table->file->ha_write_row(vtmd.table->record[0]); + } + + if (error) + { +err: + vtmd.table->file->print_error(error, MYF(0)); + } + else + result= local_da.is_error(); + } + +quit: + close_log_table(thd, &open_tables_backup); + +open_error: + thd->variables.option_bits= save_thd_options; + return result; +} + +bool +VTMD_rename::move_archives(THD *thd, LString &new_db) +{ + vtmd.init_one_table( + DB_WITH_LEN(about), + XSTRING_WITH_LEN(vtmd_name), + vtmd_name, + TL_READ); + int error; + bool rc= false; + SString_fs archive; + bool end_keyread= false; + bool index_end= false; + Open_tables_backup open_tables_backup; + key_buf_t key; + + TABLE *res= open_log_table(thd, &vtmd, &open_tables_backup); + if (!res) + return true; + + if (key.allocate(vtmd.table->key_info[IDX_ARCHIVE_NAME].key_length)) + { + close_log_table(thd, &open_tables_backup); + return true; + } + + if ((error= vtmd.table->file->ha_start_keyread(IDX_ARCHIVE_NAME))) + goto err; + end_keyread= true; + + if ((error= vtmd.table->file->ha_index_init(IDX_ARCHIVE_NAME, true))) + goto err; + index_end= true; + + error= vtmd.table->file->ha_index_first(vtmd.table->record[0]); + while (!error) + { + if (!vtmd.table->field[FLD_ARCHIVE_NAME]->is_null()) + { + vtmd.table->field[FLD_ARCHIVE_NAME]->val_str(&archive); + key_copy(key, + vtmd.table->record[0], + &vtmd.table->key_info[IDX_ARCHIVE_NAME], + vtmd.table->key_info[IDX_ARCHIVE_NAME].key_length, + false); + error= vtmd.table->file->ha_index_read_map( + vtmd.table->record[0], + key, + vtmd.table->key_info[IDX_ARCHIVE_NAME].ext_key_part_map, + HA_READ_PREFIX_LAST); + if (!error) + { + if ((rc= move_table(thd, archive, new_db))) + break; + + error= vtmd.table->file->ha_index_next(vtmd.table->record[0]); + } + } + else + { + archive.length(0); + error= vtmd.table->file->ha_index_next(vtmd.table->record[0]); + } + } + + if (error && error != HA_ERR_END_OF_FILE) + { +err: + vtmd.table->file->print_error(error, MYF(0)); + rc= true; + } + + if (index_end) + vtmd.table->file->ha_index_end(); + if (end_keyread) + vtmd.table->file->ha_end_keyread(); + + close_log_table(thd, &open_tables_backup); + return rc; +} + +bool +VTMD_rename::move_table(THD *thd, SString_fs &table_name, LString &new_db) +{ + handlerton *table_hton= NULL; + if (!ha_table_exists(thd, about.db, table_name, &table_hton) || !table_hton) + { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_VERS_VTMD_ERROR, + "`%s.%s` archive doesn't exist", + about.db, table_name.ptr()); + return false; + } + + if (ha_table_exists(thd, new_db, table_name)) + { + my_printf_error(ER_VERS_VTMD_ERROR, "`%s.%s` archive already exists!", MYF(0), + new_db.ptr(), table_name.ptr()); + return true; + } + + TABLE_LIST tl; + tl.init_one_table( + DB_WITH_LEN(about), + XSTRING_WITH_LEN(table_name), + table_name, + TL_WRITE_ONLY); + tl.mdl_request.set_type(MDL_EXCLUSIVE); + + mysql_ha_rm_tables(thd, &tl); + if (lock_table_names(thd, &tl, 0, thd->variables.lock_wait_timeout, 0)) + return true; + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, about.db, table_name, false); + + bool rc= mysql_rename_table( + table_hton, + about.db, table_name, + new_db, table_name, + NO_FK_CHECKS); + if (!rc) + query_cache_invalidate3(thd, &tl, 0); + + return rc; +} + +bool +VTMD_rename::try_rename(THD *thd, LString new_db, LString new_alias, const char *archive_name) +{ + Local_da local_da(thd, ER_VERS_VTMD_ERROR); + TABLE_LIST new_table; + + if (check_exists(thd)) + return true; + + new_table.init_one_table( + XSTRING_WITH_LEN(new_db), + XSTRING_WITH_LEN(new_alias), + new_alias, TL_READ); + + if (new_table.vers_vtmd_name(vtmd_new_name)) + return true; + + if (ha_table_exists(thd, new_db, vtmd_new_name)) + { + if (exists) + { + my_printf_error(ER_VERS_VTMD_ERROR, "`%s.%s` table already exists!", MYF(0), + new_db.ptr(), vtmd_new_name.ptr()); + return true; + } + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_VERS_VTMD_ERROR, + "`%s.%s` table already exists!", + new_db.ptr(), vtmd_new_name.ptr()); + return false; + } + + if (!exists) + return false; + + bool same_db= true; + if (LString_fs(DB_WITH_LEN(about)) != LString_fs(new_db)) + { + // Move archives before VTMD so if the operation is interrupted, it could be continued. + if (move_archives(thd, new_db)) + return true; + same_db= false; + } + + TABLE_LIST vtmd_tl; + vtmd_tl.init_one_table( + DB_WITH_LEN(about), + XSTRING_WITH_LEN(vtmd_name), + vtmd_name, + TL_WRITE_ONLY); + vtmd_tl.mdl_request.set_type(MDL_EXCLUSIVE); + + mysql_ha_rm_tables(thd, &vtmd_tl); + if (lock_table_names(thd, &vtmd_tl, 0, thd->variables.lock_wait_timeout, 0)) + return true; + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, about.db, vtmd_name, false); + if (local_da.is_error()) // just safety check + return true; + bool rc= mysql_rename_table(hton, + about.db, vtmd_name, + new_db, vtmd_new_name, + NO_FK_CHECKS); + if (!rc) + { + query_cache_invalidate3(thd, &vtmd_tl, 0); + if (same_db || archive_name || new_alias != LString(TABLE_NAME_WITH_LEN(about))) + { + local_da.finish(); + VTMD_table new_vtmd(new_table); + rc= new_vtmd.update(thd, archive_name); + } + } + return rc; +} + +bool +VTMD_rename::revert_rename(THD *thd, LString new_db) +{ + DBUG_ASSERT(hton); + Local_da local_da(thd, ER_VERS_VTMD_ERROR); + + TABLE_LIST vtmd_tl; + vtmd_tl.init_one_table( + DB_WITH_LEN(about), + XSTRING_WITH_LEN(vtmd_new_name), + vtmd_new_name, + TL_WRITE_ONLY); + vtmd_tl.mdl_request.set_type(MDL_EXCLUSIVE); + mysql_ha_rm_tables(thd, &vtmd_tl); + if (lock_table_names(thd, &vtmd_tl, 0, thd->variables.lock_wait_timeout, 0)) + return true; + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, new_db, vtmd_new_name, false); + + bool rc= mysql_rename_table( + hton, + new_db, vtmd_new_name, + new_db, vtmd_name, + NO_FK_CHECKS); + + if (!rc) + query_cache_invalidate3(thd, &vtmd_tl, 0); + + return rc; +} + +void +VTMD_table::archive_name( + THD* thd, + const char* table_name, + char* new_name, + size_t new_name_size) +{ + const MYSQL_TIME now= thd->query_start_TIME(); + my_snprintf(new_name, new_name_size, "%s_%04d%02d%02d_%02d%02d%02d_%06d", + table_name, now.year, now.month, now.day, now.hour, now.minute, + now.second, now.second_part); +} + +bool +VTMD_table::find_archive_name(THD *thd, String &out) +{ + READ_RECORD info; + int error; + SQL_SELECT *select= NULL; + COND *conds= NULL; + List<TABLE_LIST> dummy; + SELECT_LEX &select_lex= thd->lex->select_lex; + + Local_da local_da(thd, ER_VERS_VTMD_ERROR); + if (open(thd, local_da)) + return true; + + Name_resolution_context &ctx= thd->lex->select_lex.context; + TABLE_LIST *table_list= ctx.table_list; + TABLE_LIST *first_name_resolution_table= ctx.first_name_resolution_table; + table_map map = vtmd.table->map; + ctx.table_list= &vtmd; + ctx.first_name_resolution_table= &vtmd; + vtmd.table->map= 1; + + vtmd.vers_conditions= about.vers_conditions; + if ((error= vers_setup_select(thd, &vtmd, &conds, &select_lex)) || + (error= setup_conds(thd, &vtmd, dummy, &conds))) + goto err; + + select= make_select(vtmd.table, 0, 0, conds, NULL, 0, &error); + if (error) + goto loc_err; + + error= init_read_record(&info, thd, vtmd.table, select, NULL, + 1 /* use_record_cache */, true /* print_error */, + false /* disable_rr_cache */); + if (error) + goto loc_err; + + while (!(error= info.read_record()) && !thd->killed && !thd->is_error()) + { + if (!select || select->skip_record(thd) > 0) + { + vtmd.table->field[FLD_ARCHIVE_NAME]->val_str(&out); + break; + } + } + + if (error < 0) + my_error(ER_NO_SUCH_TABLE, MYF(0), about.db, about.alias); + +loc_err: + end_read_record(&info); +err: + delete select; + ctx.table_list= table_list; + ctx.first_name_resolution_table= first_name_resolution_table; + vtmd.table->map= map; + close_log_table(thd, &open_tables_backup); + DBUG_ASSERT(!error || local_da.is_error()); + return error; +} + +static +bool +get_vtmd_tables(THD *thd, const char *db, + size_t db_length, Dynamic_array<LEX_CSTRING *> &table_names) +{ + LOOKUP_FIELD_VALUES lookup_field_values= { + {db, db_length}, {C_STRING_WITH_LEN("%_vtmd")}, false, true}; + + int res= make_table_name_list(thd, &table_names, thd->lex, &lookup_field_values, + &lookup_field_values.db_value); + + return res; +} + +bool +VTMD_table::get_archive_tables(THD *thd, const char *db, size_t db_length, + Dynamic_array<String> &result) +{ + Dynamic_array<LEX_CSTRING *> vtmd_tables; + if (get_vtmd_tables(thd, db, db_length, vtmd_tables)) + return true; + + Local_da local_da(thd, ER_VERS_VTMD_ERROR); + for (uint i= 0; i < vtmd_tables.elements(); i++) + { + LEX_CSTRING table_name= *vtmd_tables.at(i); + + Open_tables_backup open_tables_backup; + TABLE_LIST table_list; + table_list.init_one_table(db, db_length, LEX_STRING_WITH_LEN(table_name), + table_name.str, TL_READ); + + TABLE *table= open_log_table(thd, &table_list, &open_tables_backup); + if (!table || !table->vers_vtmd()) + { + if (table) + close_log_table(thd, &open_tables_backup); + else + { + if (local_da.is_error() && local_da.sql_errno() == ER_NOT_LOG_TABLE) + local_da.reset_diagnostics_area(); + else + return true; + } + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_VERS_VTMD_ERROR, + "Table `%s.%s` is not a VTMD table", + db, table_name.str); + continue; + } + + READ_RECORD read_record; + int error= 0; + SQL_SELECT *sql_select= make_select(table, 0, 0, NULL, NULL, 0, &error); + if (error) + { + close_log_table(thd, &open_tables_backup); + return true; + } + error= init_read_record(&read_record, thd, table, sql_select, NULL, 1, 1, false); + if (error) + { + delete sql_select; + close_log_table(thd, &open_tables_backup); + return true; + } + + while (!(error= read_record.read_record())) + { + Field *field= table->field[FLD_ARCHIVE_NAME]; + if (field->is_null()) + continue; + + String archive_name; + field->val_str(&archive_name); + archive_name.set_ascii(strmake_root(thd->mem_root, archive_name.c_ptr(), + archive_name.length()), + archive_name.length()); + result.push(archive_name); + } + // check for EOF + if (!thd->is_error()) + error= 0; + + end_read_record(&read_record); + delete sql_select; + close_log_table(thd, &open_tables_backup); + } + + return false; +} + +bool VTMD_table::setup_select(THD* thd) +{ + SString archive_name; + if (find_archive_name(thd, archive_name)) + return true; + + if (archive_name.length() == 0) + return false; + + about.table_name= (char *) thd->memdup(archive_name.c_ptr_safe(), archive_name.length() + 1); + about.table_name_length= archive_name.length(); + DBUG_ASSERT(!about.mdl_request.ticket); + about.mdl_request.init(MDL_key::TABLE, about.db, about.table_name, + about.mdl_request.type, about.mdl_request.duration); + about.vers_force_alias= true; + // Since we modified SELECT_LEX::table_list, we need to invalidate current SP + if (thd->spcont) + { + DBUG_ASSERT(thd->spcont->m_sp); + thd->spcont->m_sp->set_sp_cache_version(ULONG_MAX); + } + return false; +} diff --git a/sql/vtmd.h b/sql/vtmd.h new file mode 100644 index 00000000000..e6f968d7739 --- /dev/null +++ b/sql/vtmd.h @@ -0,0 +1,183 @@ +#ifndef VTMD_INCLUDED +#define VTMD_INCLUDED + +#include "unireg.h" +#include <mysqld_error.h> +#include "my_sys.h" +#include "table.h" + +#include "vers_utils.h" + +class key_buf_t +{ + uchar* buf; + + key_buf_t(const key_buf_t&); // disabled + key_buf_t& operator= (const key_buf_t&); // disabled + +public: + key_buf_t() : buf(NULL) + {} + + ~key_buf_t() + { + if (buf) + my_free(buf); + } + + bool allocate(size_t alloc_size) + { + DBUG_ASSERT(!buf); + buf= static_cast<uchar *>(my_malloc(alloc_size, MYF(0))); + if (!buf) + { + my_message(ER_VERS_VTMD_ERROR, "failed to allocate key buffer", MYF(0)); + return true; + } + return false; + } + + operator uchar* () + { + DBUG_ASSERT(buf); + return reinterpret_cast<uchar *>(buf); + } +}; + +class THD; + +class VTMD_table +{ + Open_tables_backup open_tables_backup; + +protected: + TABLE_LIST vtmd; + TABLE_LIST &about; + SString_t vtmd_name; + +private: + VTMD_table(const VTMD_table&); // prohibit copying references + +public: + enum { + FLD_START= 0, + FLD_END, + FLD_NAME, + FLD_ARCHIVE_NAME, + FLD_COL_RENAMES, + FIELD_COUNT + }; + + enum { + IDX_TRX_END= 0, + IDX_ARCHIVE_NAME + }; + + VTMD_table(TABLE_LIST &_about) : + about(_about) + { + vtmd.table= NULL; + } + + bool create(THD *thd); + bool find_record(ulonglong sys_trx_end, bool &found); + bool open(THD *thd, Local_da &local_da, bool *created= NULL); + bool update(THD *thd, const char* archive_name= NULL); + bool setup_select(THD *thd); + + static void archive_name(THD *thd, const char *table_name, char *new_name, size_t new_name_size); + void archive_name(THD *thd, char *new_name, size_t new_name_size) + { + archive_name(thd, about.table_name, new_name, new_name_size); + } + + bool find_archive_name(THD *thd, String &out); + static bool get_archive_tables(THD *thd, const char *db, size_t db_length, + Dynamic_array<String> &result); +}; + +class VTMD_exists : public VTMD_table +{ +protected: + handlerton *hton; + +public: + bool exists; + +public: + VTMD_exists(TABLE_LIST &_about) : + VTMD_table(_about), + hton(NULL), + exists(false) + {} + + bool check_exists(THD *thd); // returns error status +}; + +class VTMD_rename : public VTMD_exists +{ + SString_t vtmd_new_name; + +public: + VTMD_rename(TABLE_LIST &_about) : + VTMD_exists(_about) + {} + + bool try_rename(THD *thd, LString new_db, LString new_alias, const char* archive_name= NULL); + bool revert_rename(THD *thd, LString new_db); + +private: + bool move_archives(THD *thd, LString &new_db); + bool move_table(THD *thd, SString_fs &table_name, LString &new_db); +}; + +class VTMD_drop : public VTMD_exists +{ + char archive_name_[NAME_CHAR_LEN]; + +public: + VTMD_drop(TABLE_LIST &_about) : + VTMD_exists(_about) + { + *archive_name_= 0; + } + + const char* archive_name(THD *thd) + { + VTMD_table::archive_name(thd, archive_name_, sizeof(archive_name_)); + return archive_name_; + } + + const char* archive_name() const + { + DBUG_ASSERT(*archive_name_); + return archive_name_; + } + + bool update(THD *thd) + { + DBUG_ASSERT(*archive_name_); + return VTMD_exists::update(thd, archive_name_); + } +}; + + +inline +bool +VTMD_exists::check_exists(THD *thd) +{ + if (about.vers_vtmd_name(vtmd_name)) + return true; + + exists= ha_table_exists(thd, about.db, vtmd_name, &hton); + + if (exists && !hton) + { + my_printf_error(ER_VERS_VTMD_ERROR, "`%s.%s` handlerton empty!", MYF(0), + about.db, vtmd_name.ptr()); + return true; + } + return false; +} + +#endif // VTMD_INCLUDED diff --git a/sql/vtq.h b/sql/vtq.h new file mode 100644 index 00000000000..dcea8734b57 --- /dev/null +++ b/sql/vtq.h @@ -0,0 +1,47 @@ +#ifndef VTQ_INCLUDED +#define VTQ_INCLUDED + +/* Copyright (c) 2016, 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-1301, USA */ + + +/** + VTQ stands for 'versioning transaction query': InnoDB system table that holds + transaction IDs, their corresponding times and other transaction-related + data which is used for transaction order resolution. When versioned table + marks its records lifetime with transaction IDs, VTQ is used to get their + actual timestamps. */ + + +enum vtq_field_t +{ + VTQ_ALL = 0, + VTQ_TRX_ID, + VTQ_COMMIT_ID, + VTQ_BEGIN_TS, + VTQ_COMMIT_TS, + VTQ_ISO_LEVEL +}; + +struct vtq_record_t +{ + ulonglong trx_id; + ulonglong commit_id; + timeval begin_ts; + timeval commit_ts; + uchar iso_level; +}; + +#endif /* VTQ_INCLUDED */ diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index a75efb7fb62..8a1db4fff99 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -26,6 +26,9 @@ #include "ha_heap.h" #include "sql_base.h" // enum_tdc_remove_table_type +bool vtq_query_trx_id(THD *thd, void *out, ulonglong in_trx_id, + vtq_field_t field); + static handler *heap_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); @@ -55,6 +58,8 @@ int heap_init(void *p) heap_hton->panic= heap_panic; heap_hton->flags= HTON_CAN_RECREATE; + heap_hton->vers_query_trx_id = vtq_query_trx_id; + return 0; } diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 0a9a1a68458..100ba18665a 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -147,7 +147,8 @@ SET(INNOBASE_SOURCES ut/ut0ut.cc ut/ut0vec.cc ut/ut0wqueue.cc - ut/ut0timer.cc) + ut/ut0timer.cc + vers/vers0vtq.cc) MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE DEFAULT RECOMPILE_FOR_EMBEDDED diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 2b85c764a3b..7342aee2f7e 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -471,7 +471,7 @@ alphabetical position of the cursor is guaranteed to be sensible on return, but it may happen that the cursor is not positioned on the last record of any page, because the structure of the tree may have changed during the time when the cursor had no latches. */ -static +UNIV_INTERN void btr_pcur_move_backward_from_page( /*=============================*/ @@ -607,8 +607,9 @@ btr_pcur_open_on_user_rec_func( } else { ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L)); - /* Not implemented yet */ + if (btr_pcur_is_before_first_on_page(cursor)) { - ut_error; + btr_pcur_move_to_prev_user_rec(cursor, mtr); + } } } diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 77a79e32605..38d4f7fa9ce 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -1877,6 +1877,130 @@ dict_create_or_check_sys_virtual() return(err); } +UNIV_INTERN +dberr_t +dict_create_or_check_vtq_table(void) +/*================================================*/ +{ + trx_t* trx; + my_bool srv_file_per_table_backup; + dberr_t err; + dberr_t sys_vtq_err; + dict_index_t* index; + + ut_a(srv_get_active_thread_type() == SRV_NONE); + + /* Note: The master thread has not been started at this point. */ + + static const int vtq_num_indexes = 4; + sys_vtq_err = dict_check_if_system_table_exists( + "SYS_VTQ", DICT_NUM_FIELDS__SYS_VTQ + 1, vtq_num_indexes); + + if (sys_vtq_err == DB_SUCCESS) { + err = DB_SUCCESS; + goto assign_and_exit; + } + + trx = trx_allocate_for_mysql(); + + trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); + + trx->op_info = "creating VTQ sys table"; + + row_mysql_lock_data_dictionary(trx); + + /* Check which incomplete table definition to drop. */ + + if (sys_vtq_err == DB_CORRUPTION) { + ib::warn() << + "Dropping incompletely created " + "SYS_VTQ table."; + row_drop_table_for_mysql("SYS_VTQ", trx, false, TRUE); + } + + ib::info() << + "Creating VTQ system table."; + + srv_file_per_table_backup = srv_file_per_table; + + /* We always want SYSTEM tables to be created inside the system + tablespace. */ + + srv_file_per_table = 0; + + err = que_eval_sql( + NULL, + "PROCEDURE CREATE_VTQ_SYS_TABLE_PROC () IS\n" + "BEGIN\n" + "CREATE TABLE\n" + "SYS_VTQ(" + "TRX_ID BIGINT UNSIGNED, " + "COMMIT_ID BIGINT UNSIGNED, " + "BEGIN_TS BIGINT UNSIGNED, " + "COMMIT_TS BIGINT UNSIGNED, " + "ISO_LEVEL CHAR(1));\n" + "CREATE UNIQUE CLUSTERED INDEX TRX_ID_IND" + " ON SYS_VTQ (TRX_ID);\n" + "CREATE INDEX COMMIT_ID_IND" + " ON SYS_VTQ (COMMIT_ID);\n" + "CREATE INDEX BEGIN_TS_IND" + " ON SYS_VTQ (BEGIN_TS);\n" + "CREATE INDEX COMMIT_TS_IND" + " ON SYS_VTQ (COMMIT_TS);\n" + "END;\n", + FALSE, trx); + + if (err != DB_SUCCESS) { + ib::error() << "Creation of SYS_VTQ" + " failed: " << ut_strerr(err) << ". Tablespace is" + " full or too many transactions." + " Dropping incompletely created tables."; + + ut_ad(err == DB_OUT_OF_FILE_SPACE + || err == DB_TOO_MANY_CONCURRENT_TRXS); + + row_drop_table_for_mysql("SYS_VTQ", trx, false, TRUE); + + if (err == DB_OUT_OF_FILE_SPACE) { + err = DB_MUST_GET_MORE_FILE_SPACE; + } + } + + trx_commit_for_mysql(trx); + + row_mysql_unlock_data_dictionary(trx); + + trx_free_for_mysql(trx); + + srv_file_per_table = srv_file_per_table_backup; + + if (err == DB_SUCCESS) { + ib::info() << + "VTQ system table created"; + } + + /* Note: The master thread has not been started at this point. */ + /* Confirm and move to the non-LRU part of the table LRU list. */ + sys_vtq_err = dict_check_if_system_table_exists( + "SYS_VTQ", DICT_NUM_FIELDS__SYS_VTQ + 1, vtq_num_indexes); + ut_a(sys_vtq_err == DB_SUCCESS); + +assign_and_exit: + mutex_enter(&dict_sys->mutex); + dict_sys->sys_vtq = dict_table_get_low("SYS_VTQ"); + ut_ad(dict_sys->sys_vtq); + index = dict_table_get_first_index(dict_sys->sys_vtq); + for (int i = 0; i < 3; ++i) { + index = dict_table_get_next_index(index); + ut_ad(index); + } + ut_ad(strcmp(index->name, "COMMIT_TS_IND") == 0); + dict_sys->vtq_commit_ts_ind = index; + mutex_exit(&dict_sys->mutex); + + return(err); +} + /****************************************************************//** Evaluate the given foreign key SQL statement. @return error code or DB_SUCCESS */ diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 0e55e353837..eeffb6bb498 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -50,7 +50,7 @@ Created 4/24/1996 Heikki Tuuri #include <set> /** Following are the InnoDB system tables. The positions in -this array are referenced by enum dict_system_table_id. */ +this array are referenced by enum dict_system_id_t. */ static const char* SYSTEM_TABLE_NAME[] = { "SYS_TABLES", "SYS_INDEXES", @@ -60,7 +60,8 @@ static const char* SYSTEM_TABLE_NAME[] = { "SYS_FOREIGN_COLS", "SYS_TABLESPACES", "SYS_DATAFILES", - "SYS_VIRTUAL" + "SYS_VIRTUAL", + "SYS_VTQ" }; /** Loads a table definition and also all its index definitions. @@ -307,7 +308,10 @@ dict_getnext_system_low( rec_t* rec = NULL; while (!rec || rec_get_deleted_flag(rec, 0)) { - btr_pcur_move_to_next_user_rec(pcur, mtr); + if (pcur->search_mode == PAGE_CUR_L) + btr_pcur_move_to_prev_user_rec(pcur, mtr); + else + btr_pcur_move_to_next_user_rec(pcur, mtr); rec = btr_pcur_get_rec(pcur); @@ -334,7 +338,8 @@ dict_startscan_system( btr_pcur_t* pcur, /*!< out: persistent cursor to the record */ mtr_t* mtr, /*!< in: the mini-transaction */ - dict_system_id_t system_id) /*!< in: which system table to open */ + dict_system_id_t system_id, /*!< in: which system table to open */ + bool from_left) { dict_table_t* system_table; dict_index_t* clust_index; @@ -346,7 +351,7 @@ dict_startscan_system( clust_index = UT_LIST_GET_FIRST(system_table->indexes); - btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, pcur, + btr_pcur_open_at_index_side(from_left, clust_index, BTR_SEARCH_LEAF, pcur, true, 0, mtr); rec = dict_getnext_system_low(pcur, mtr); @@ -810,6 +815,84 @@ err_len: return(NULL); } + +inline +const char* dict_print_error(mem_heap_t* heap, ulint col, ulint len, ulint expected) +{ + return mem_heap_printf(heap, + "incorrect column %lu length in SYS_VTQ; got: %lu, expected: %lu", + col, len, expected); +} + +/********************************************************************//** +This function parses a SYS_VTQ record, extracts necessary +information from the record and returns it to the caller. +@return error message, or NULL on success */ +UNIV_INTERN +const char* +dict_process_sys_vtq( +/*=======================*/ +mem_heap_t* heap, /*!< in/out: heap memory */ +const rec_t* rec, /*!< in: current rec */ +vtq_record_t& out /*!< out: field values */ +) +{ + ulint len, nfld; + const byte *field; + + if (rec_get_deleted_flag(rec, 0)) { + return("delete-marked record in SYS_VTQ"); + } + + if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_VTQ) { + return("wrong number of columns in SYS_VTQ record"); + } + /* TRX_ID */ + field = rec_get_nth_field_old( + rec, (nfld = DICT_FLD__SYS_VTQ__TRX_ID), &len); + + if (len != sizeof(trx_id_t)) + return dict_print_error(heap, nfld, len, sizeof(trx_id_t)); + + out.trx_id = mach_read_from_8(field); + /* COMMIT_ID */ + field = rec_get_nth_field_old( + rec, (nfld = DICT_FLD__SYS_VTQ__COMMIT_ID), &len); + + if (len != sizeof(trx_id_t)) + return dict_print_error(heap, nfld, len, sizeof(trx_id_t)); + + out.commit_id = mach_read_from_8(field); + /* BEGIN_TS */ + field = rec_get_nth_field_old( + rec, (nfld = DICT_FLD__SYS_VTQ__BEGIN_TS), &len); + + if (len != sizeof(ullong)) + return dict_print_error(heap, nfld, len, sizeof(ullong)); + + out.begin_ts.tv_sec = mach_read_from_4(field); + out.begin_ts.tv_usec = mach_read_from_4(field + 4); + /* COMMIT_TS */ + field = rec_get_nth_field_old( + rec, (nfld = DICT_FLD__SYS_VTQ__COMMIT_TS), &len); + + if (len != sizeof(ullong)) + return dict_print_error(heap, nfld, len, sizeof(ullong)); + + out.commit_ts.tv_sec = mach_read_from_4(field); + out.commit_ts.tv_usec = mach_read_from_4(field + 4); + /* ISOLATION_LEVEL */ + field = rec_get_nth_field_old( + rec, (nfld = DICT_FLD__SYS_VTQ__ISOLATION_LEVEL), &len); + + if (len != sizeof(byte)) + return dict_print_error(heap, nfld, len, sizeof(byte)); + + out.iso_level = *field; + + return(NULL); +} + /** Get the first filepath from SYS_DATAFILES for a given space_id. @param[in] space_id Tablespace ID @return First filepath (caller must invoke ut_free() on it) diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index aaed29dc58c..ef7589f6892 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -303,6 +303,16 @@ dict_mem_table_add_col( col = dict_table_get_nth_col(table, i); dict_mem_fill_column_struct(col, i, mtype, prtype, len); + + if (prtype & DATA_VERS_ROW_START) { + ut_ad(table->flags2 & DICT_TF2_VERSIONED + && !(prtype & DATA_VERS_ROW_END)); + table->vers_row_start = i; + } else if (prtype & DATA_VERS_ROW_END) { + ut_ad(table->flags2 & DICT_TF2_VERSIONED + && !(prtype & DATA_VERS_ROW_START)); + table->vers_row_end = i; + } } /** Adds a virtual column definition to a table. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 10d54498feb..09b0aa1996d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -117,6 +117,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include "trx0xa.h" #include "ut0mem.h" #include "row0ext.h" +#include "vers0vtq.h" #define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) @@ -1713,9 +1714,7 @@ thd_start_time_in_secs( /*===================*/ THD* thd) /*!< in: thread handle, or NULL */ { - // FIXME: This function should be added to the server code. - //return(thd_start_time(thd)); - return(ulint(ut_time())); + return(thd_start_time(thd)); } /** Enter InnoDB engine after checking the max number of user threads @@ -3679,7 +3678,7 @@ innobase_init( innobase_hton->flush_logs = innobase_flush_logs; innobase_hton->show_status = innobase_show_status; innobase_hton->flags = - HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS; + HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS | HTON_NATIVE_SYS_VERSIONING; #ifdef WITH_WSREP innobase_hton->abort_transaction=wsrep_abort_transaction; @@ -3694,6 +3693,11 @@ innobase_init( innobase_hton->table_options = innodb_table_option_list; + /* System Versioning */ + innobase_hton->vers_query_trx_id = vtq_query_trx_id; + innobase_hton->vers_query_commit_ts = vtq_query_commit_ts; + innobase_hton->vers_trx_sees = vtq_trx_sees; + innodb_remember_check_sysvar_funcs(); ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -4424,6 +4428,14 @@ innobase_commit_ordered_2( /* Don't do write + flush right now. For group commit to work we want to do the flush later. */ trx->flush_log_later = true; + + /* Notify VTQ on System Versioned tables update */ + if (trx->vtq_notify_on_commit) { + vers_notify_vtq(trx); + trx->vtq_notify_on_commit = false; + } + } else { + DBUG_ASSERT(!trx->vtq_notify_on_commit); } innobase_commit_low(trx); @@ -4547,6 +4559,11 @@ innobase_commit( if (commit_trx || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { + /* Notify VTQ on System Versioned tables update */ + if (trx->vtq_notify_on_commit) { + vers_notify_vtq(trx); + trx->vtq_notify_on_commit = false; + } DBUG_EXECUTE_IF("crash_innodb_before_commit", DBUG_SUICIDE();); @@ -6500,7 +6517,7 @@ no_such_table: } } - info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); + info(HA_STATUS_OPEN | HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); DBUG_RETURN(0); } @@ -8143,6 +8160,7 @@ ha_innobase::write_row( trx_t* trx = thd_to_trx(m_user_thd); TrxInInnoDB trx_in_innodb(trx); + ins_mode_t vers_set_fields; if (trx_in_innodb.is_aborted()) { @@ -8343,8 +8361,14 @@ no_commit: innobase_srv_conc_enter_innodb(m_prebuilt); + vers_set_fields = (table->versioned() && !is_innopart() && + (sql_command != SQLCOM_CREATE_TABLE || table->s->vtmd)) + ? + ROW_INS_VERSIONED : + ROW_INS_NORMAL; + /* Step-5: Execute insert graph that will result in actual insert. */ - error = row_insert_for_mysql((byte*) record, m_prebuilt); + error = row_insert_for_mysql((byte*) record, m_prebuilt, vers_set_fields); DEBUG_SYNC(m_user_thd, "ib_after_row_insert"); @@ -8604,6 +8628,9 @@ calc_row_difference( /* We use upd_buff to convert changed fields */ buf = (byte*) upd_buff; + prebuilt->upd_node->versioned = false; + prebuilt->upd_node->vers_delete = false; + for (i = 0; i < n_fields; i++) { field = table->field[i]; bool is_virtual = innobase_is_v_fld(field); @@ -8842,6 +8869,13 @@ calc_row_difference( } n_changed++; + if (!prebuilt->upd_node->versioned && + DICT_TF2_FLAG_IS_SET(prebuilt->table, DICT_TF2_VERSIONED) && + !(field->flags & VERS_OPTIMIZED_UPDATE_FLAG)) + { + prebuilt->upd_node->versioned = true; + } + /* If an FTS indexed column was changed by this UPDATE then we need to inform the FTS sub-system. @@ -8946,6 +8980,13 @@ calc_row_difference( innodb_table, ufield, &trx->fts_next_doc_id); ++n_changed; + + if (!prebuilt->upd_node->versioned && + DICT_TF2_FLAG_IS_SET(prebuilt->table, DICT_TF2_VERSIONED) && + !(field->flags & VERS_OPTIMIZED_UPDATE_FLAG)) + { + prebuilt->upd_node->versioned = true; + } } else { /* We have a Doc ID column, but none of FTS indexed columns are touched, nor the Doc ID column, so set @@ -9102,6 +9143,8 @@ ha_innobase::update_row( upd_t* uvect = row_get_prebuilt_update_vector(m_prebuilt); ib_uint64_t autoinc; + bool vers_set_fields = false; + bool vers_ins_row = false; /* Build an update vector from the modified fields in the rows (uses m_upd_buf of the handle) */ @@ -9127,7 +9170,26 @@ ha_innobase::update_row( innobase_srv_conc_enter_innodb(m_prebuilt); - error = row_update_for_mysql(m_prebuilt); + if (!table->versioned()) + m_prebuilt->upd_node->versioned = false; + + if (m_prebuilt->upd_node->versioned && !is_innopart()) { + vers_set_fields = true; + if (thd_sql_command(m_user_thd) == SQLCOM_ALTER_TABLE && !table->s->vtmd) + { + m_prebuilt->upd_node->vers_delete = true; + } else { + m_prebuilt->upd_node->vers_delete = false; + vers_ins_row = true; + } + } + + error = row_update_for_mysql(m_prebuilt, vers_set_fields); + + if (error == DB_SUCCESS && vers_ins_row) { + if (trx->id != static_cast<trx_id_t>(table->vers_start_field()->val_int())) + error = row_insert_for_mysql((byte*) old_row, m_prebuilt, ROW_INS_HISTORICAL); + } if (error == DB_SUCCESS && autoinc) { /* A value for an AUTO_INCREMENT column @@ -9242,7 +9304,12 @@ ha_innobase::delete_row( innobase_srv_conc_enter_innodb(m_prebuilt); - error = row_update_for_mysql(m_prebuilt); + bool vers_set_fields = + table->versioned() && + !is_innopart() && + table->vers_end_field()->is_max(); + + error = row_update_for_mysql(m_prebuilt, vers_set_fields); innobase_srv_conc_exit_innodb(m_prebuilt); @@ -11330,8 +11397,17 @@ create_table_info_t::create_table_def() for (i = 0; i < n_cols; i++) { ulint is_virtual; bool is_stored = false; - Field* field = m_form->field[i]; + ulint vers_row_start = 0; + ulint vers_row_end = 0; + + if (m_flags2 & DICT_TF2_VERSIONED) { + if (i == m_form->s->row_start_field) { + vers_row_start = DATA_VERS_ROW_START; + } else if (i == m_form->s->row_end_field) { + vers_row_end = DATA_VERS_ROW_END; + } + } col_type = get_innobase_type_from_mysql_type( &unsigned_type, field); @@ -11422,7 +11498,8 @@ err_col: dtype_form_prtype( (ulint) field->type() | nulls_allowed | unsigned_type - | binary_type | long_true_varchar, + | binary_type | long_true_varchar + | vers_row_start | vers_row_end, charset_no), col_len); } else { @@ -11432,6 +11509,7 @@ err_col: (ulint) field->type() | nulls_allowed | unsigned_type | binary_type | long_true_varchar + | vers_row_start | vers_row_end | is_virtual, charset_no), col_len, i, 0); @@ -12445,6 +12523,10 @@ index_bad: DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", m_flags2 &= ~DICT_TF2_FTS_AUX_HEX_NAME;); + if (m_create_info->options & HA_VERSIONED_TABLE) { + m_flags2 |= DICT_TF2_VERSIONED; + } + DBUG_RETURN(true); } @@ -14323,7 +14405,7 @@ ha_innobase::info_low( set. That way SHOW TABLE STATUS will show the best estimate, while the optimizer never sees the table empty. */ - if (n_rows == 0 && !(flag & HA_STATUS_TIME)) { + if (n_rows == 0 && !(flag & (HA_STATUS_TIME | HA_STATUS_OPEN))) { n_rows++; } @@ -21215,7 +21297,8 @@ i_s_innodb_sys_virtual, i_s_innodb_mutexes, i_s_innodb_sys_semaphore_waits, i_s_innodb_tablespaces_encryption, -i_s_innodb_tablespaces_scrubbing +i_s_innodb_tablespaces_scrubbing, +i_s_innodb_vtq maria_declare_plugin_end; /** @brief Initialize the default value of innodb_commit_concurrency. diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index d7f5d36a680..90a9c0becc4 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -223,6 +223,9 @@ public: ha_rows estimate_rows_upper_bound(); + // JAN: TODO: MySQL 5.7 + ha_rows records_new(); // FIXME: rename to records(), fix main.bug39022 + void update_create_info(HA_CREATE_INFO* create_info); int create( @@ -455,7 +458,7 @@ protected: void reset_template(); protected: - inline void update_thd(THD* thd); + void update_thd(THD* thd); void update_thd(); int general_fetch(uchar* buf, uint direction, uint match_mode); @@ -520,6 +523,11 @@ protected: /** If mysql has locked with external_lock() */ bool m_mysql_has_locked; + + bool is_innopart() + { + return m_share == NULL; + } }; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index a8769820563..b8106122261 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4899,6 +4899,15 @@ new_clustered_failed: field_type |= DATA_UNSIGNED; } + if (altered_table->versioned()) { + if (i == altered_table->s->row_start_field) { + field_type |= DATA_VERS_ROW_START; + } else if (i == + altered_table->s->row_end_field) { + field_type |= DATA_VERS_ROW_END; + } + } + if (dtype_is_string_type(col_type)) { charset_no = (ulint) field->charset()->number; @@ -6987,7 +6996,8 @@ ok_exit: ctx->add_index, ctx->add_key_numbers, ctx->num_to_add_index, altered_table, ctx->add_cols, ctx->col_map, ctx->add_autoinc, ctx->sequence, ctx->skip_pk_sort, - ctx->m_stage, add_v, eval_table); + ctx->m_stage, add_v, eval_table, + ha_alter_info->handler_flags & Alter_inplace_info::ALTER_DROP_HISTORICAL); #ifndef DBUG_OFF oom: @@ -9653,6 +9663,48 @@ foreign_fail: DBUG_RETURN(false); } + +/** Helper class for in-place alter, see handler.h */ +class ha_innopart_inplace_ctx : public inplace_alter_handler_ctx +{ +/* Only used locally in this file, so have everything public for +conveniance. */ +public: + /** Total number of partitions. */ + uint m_tot_parts; + /** Array of inplace contexts for all partitions. */ + inplace_alter_handler_ctx** ctx_array; + /** Array of prebuilt for all partitions. */ + row_prebuilt_t** prebuilt_array; + + ha_innopart_inplace_ctx(THD *thd, uint tot_parts) + : inplace_alter_handler_ctx(), + m_tot_parts(tot_parts), + ctx_array(), + prebuilt_array() + {} + + ~ha_innopart_inplace_ctx() + { + if (ctx_array) { + for (uint i = 0; i < m_tot_parts; i++) { + delete ctx_array[i]; + } + ut_free(ctx_array); + } + if (prebuilt_array) { + /* First entry is the original prebuilt! */ + for (uint i = 1; i < m_tot_parts; i++) { + /* Don't close the tables. */ + prebuilt_array[i]->table = NULL; + row_prebuilt_free(prebuilt_array[i], false); + } + ut_free(prebuilt_array); + } + } +}; + + /** @param thd the session @param start_value the lower bound diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index d1728db68e9..b47ec19261c 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -28,6 +28,8 @@ Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits) #include "ha_prototypes.h" #include <mysql_version.h> #include <field.h> +#include <tztime.h> + #include "univ.i" #include <sql_acl.h> @@ -347,6 +349,51 @@ field_store_ulint( # define I_S_AHI 0 /* Omit the IS_HASHED column */ #endif +/*******************************************************************//** +Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field. +If the value is UINT64_UNDEFINED then the field it set to NULL. +@return 0 on success */ +int +field_store_ullong( +/*==============*/ + Field* field, /*!< in/out: target field for storage */ + ullong n) /*!< in: value to store */ +{ + int ret; + + if (n != UINT64_UNDEFINED) { + ret = field->store(n, 1); + field->set_notnull(); + } else { + ret = 0; /* success */ + field->set_null(); + } + + return(ret); +} + +/*******************************************************************//** +Auxiliary function to store packed timestamp value in MYSQL_TYPE_DATETIME field. +If the value is ULINT_UNDEFINED then the field it set to NULL. +@return 0 on success */ +int +field_store_timeval( +/*==============*/ +Field* field, /*!< in/out: target field for storage */ +timeval t, /*!< in: value to store */ +THD* thd) +{ + int ret; + MYSQL_TIME tmp; + + thd_get_timezone(thd)->gmt_sec_to_TIME(&tmp, t.tv_sec); + tmp.second_part = t.tv_usec; + ret = field->store_time(&tmp); + field->set_notnull(); + + return(ret); +} + /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */ static ST_FIELD_INFO innodb_trx_fields_info[] = { @@ -9582,3 +9629,270 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_semaphore_waits = STRUCT_FLD(version_info, INNODB_VERSION_STR), STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; + + +/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_vtq */ +static ST_FIELD_INFO innodb_vtq_fields_info[] = +{ +#define SYS_VTQ_TRX_ID 0 + { STRUCT_FLD(field_name, "transaction_id"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, + +#define SYS_VTQ_COMMIT_ID 1 + { STRUCT_FLD(field_name, "commit_id"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, + +#define SYS_VTQ_BEGIN_TS 2 + { STRUCT_FLD(field_name, "begin_timestamp"), + STRUCT_FLD(field_length, 6), + STRUCT_FLD(field_type, MYSQL_TYPE_TIMESTAMP), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, + +#define SYS_VTQ_COMMIT_TS 3 + { STRUCT_FLD(field_name, "commit_timestamp"), + STRUCT_FLD(field_length, 6), + STRUCT_FLD(field_type, MYSQL_TYPE_TIMESTAMP), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, + +#define SYS_VTQ_ISO_LEVEL 4 + { STRUCT_FLD(field_name, "isolation_level"), + STRUCT_FLD(field_length, 16), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, + + END_OF_ST_FIELD_INFO +}; + +/******************************************************************//** +Maps a InnoDB trx isolation level code to the MySQL isolation level name +@return MySQL isolation level name */ +static inline +const char* +i_s_isolation_name( +/*=========================*/ + ulint iso) /*!< in: InnoDB isolation level code */ +{ + enum_tx_isolation mysql_iso; + + switch (iso) { + case TRX_ISO_REPEATABLE_READ: + mysql_iso = ISO_REPEATABLE_READ; + break; + case TRX_ISO_READ_COMMITTED: + mysql_iso = ISO_READ_COMMITTED; + break; + case TRX_ISO_SERIALIZABLE: + mysql_iso = ISO_SERIALIZABLE; + break; + case TRX_ISO_READ_UNCOMMITTED: + mysql_iso = ISO_READ_UNCOMMITTED; + break; + default: + ut_error; + return NULL; + } + + return tx_isolation_names[mysql_iso]; +} + + +/**********************************************************************//** +Function to fill INFORMATION_SCHEMA.INNODB_SYS_VTQ with information +collected by scanning SYS_VTQ table. +@return 0 on success */ +static +int +i_s_dict_fill_vtq( +/*========================*/ + THD* thd, /*!< in: thread */ + vtq_record_t& vtq, /*!< in: table fields */ + TABLE* table_to_fill) /*!< in/out: fill this table */ +{ + Field** fields; + const char* iso_level; + + DBUG_ENTER("i_s_dict_fill_vtq"); + fields = table_to_fill->field; + + iso_level = i_s_isolation_name(vtq.iso_level); + + OK(field_store_ullong(fields[SYS_VTQ_TRX_ID], vtq.trx_id)); + OK(field_store_ullong(fields[SYS_VTQ_COMMIT_ID], vtq.commit_id)); + OK(field_store_timeval(fields[SYS_VTQ_BEGIN_TS], vtq.begin_ts, thd)); + OK(field_store_timeval(fields[SYS_VTQ_COMMIT_TS], vtq.commit_ts, thd)); + OK(field_store_string(fields[SYS_VTQ_ISO_LEVEL], iso_level)); + + OK(schema_table_store_record(thd, table_to_fill)); + + DBUG_RETURN(0); +} + +/*******************************************************************//** +Function to populate INFORMATION_SCHEMA.INNODB_SYS_VTQ table. +Loop through each record in SYS_VTQ, and extract the column +information and fill the INFORMATION_SCHEMA.INNODB_SYS_VTQ table. +@return 0 on success */ + +static const int I_S_SYS_VTQ_LIMIT = 10000; // maximum number of records in I_S.INNODB_SYS_VTQ + +static +int +i_s_sys_vtq_fill_table( +/*=========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (not used) */ +{ + btr_pcur_t pcur; + const rec_t* rec; + mem_heap_t* heap; + mtr_t mtr; + int err = 0; + + DBUG_ENTER("i_s_sys_vtq_fill_table"); + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); + + /* deny access to user without PROCESS_ACL privilege */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + heap = mem_heap_create(1000); + mutex_enter(&dict_sys->mutex); + mtr_start(&mtr); + + rec = dict_startscan_system(&pcur, &mtr, SYS_VTQ, false); + + for (int i = 0; rec && i < I_S_SYS_VTQ_LIMIT; ++i) { + const char* err_msg; + vtq_record_t fields; + + /* Extract necessary information from SYS_VTQ row */ + err_msg = dict_process_sys_vtq( + heap, + rec, + fields); + + mtr_commit(&mtr); + mutex_exit(&dict_sys->mutex); + + if (!err_msg) { + err = i_s_dict_fill_vtq( + thd, + fields, + tables->table); + } else { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_CANT_FIND_SYSTEM_REC, "%s", + err_msg); + err = 1; + } + + if (err) + break; + + mem_heap_empty(heap); + + /* Get the next record */ + mutex_enter(&dict_sys->mutex); + mtr_start(&mtr); + rec = dict_getnext_system(&pcur, &mtr); + } + + if (!err) { + mtr_commit(&mtr); + mutex_exit(&dict_sys->mutex); + } + mem_heap_free(heap); + + DBUG_RETURN(err); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.innodb_vtq +@return 0 on success */ +static +int +innodb_vtq_init( +/*===================*/ +void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("innodb_vtq_init"); + + schema = (ST_SCHEMA_TABLE*) p; + + schema->fields_info = innodb_vtq_fields_info; + schema->fill_table = i_s_sys_vtq_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_maria_plugin i_s_innodb_vtq = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_VTQ"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Versioning Transaction Query table"), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, innodb_vtq_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), +}; diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index e07fe49f7fa..0bc798ab031 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -64,6 +64,7 @@ extern struct st_maria_plugin i_s_innodb_sys_virtual; extern struct st_maria_plugin i_s_innodb_tablespaces_encryption; extern struct st_maria_plugin i_s_innodb_tablespaces_scrubbing; extern struct st_maria_plugin i_s_innodb_sys_semaphore_waits; +extern struct st_maria_plugin i_s_innodb_vtq; /** maximum number of buffer page info we would cache. */ #define MAX_BUF_INFO_CACHED 10000 diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index fab934ca0ee..6f89eed2f9d 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -337,6 +337,17 @@ btr_pcur_move_to_next_user_rec( function may release the page latch */ mtr_t* mtr); /*!< in: mtr */ /*********************************************************//** +Moves the persistent cursor to the previous user record in the tree. If no user +records are left, the cursor ends up 'before first in tree'. +@return TRUE if the cursor moved forward, ending on a user record */ +UNIV_INLINE +ibool +btr_pcur_move_to_prev_user_rec( +/*===========================*/ + btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the + function may release the page latch */ + mtr_t* mtr); /*!< in: mtr */ +/*********************************************************//** Moves the persistent cursor to the first record on the next page. Releases the latch on the current page, and bufferunfixes it. Note that there must not be modifications on the current page, @@ -347,6 +358,22 @@ btr_pcur_move_to_next_page( btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the last record of the current page */ mtr_t* mtr); /*!< in: mtr */ +/*********************************************************//** +Moves the persistent cursor backward if it is on the first record +of the page. Releases the latch on the current page, and bufferunfixes +it. Note that to prevent a possible deadlock, the operation first +stores the position of the cursor, releases the leaf latch, acquires +necessary latches and restores the cursor position again before returning. +The alphabetical position of the cursor is guaranteed to be sensible +on return, but it may happen that the cursor is not positioned on the +last record of any page, because the structure of the tree may have +changed while the cursor had no latches. */ +void +btr_pcur_move_backward_from_page( +/*=============================*/ + btr_pcur_t* cursor, /*!< in: persistent cursor, must be on the + first record of the current page */ + mtr_t* mtr); /*!< in: mtr */ #ifdef UNIV_DEBUG /*********************************************************//** Returns the btr cursor component of a persistent cursor. diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic index 4490942a2bb..1de99a2b0eb 100644 --- a/storage/innobase/include/btr0pcur.ic +++ b/storage/innobase/include/btr0pcur.ic @@ -335,6 +335,42 @@ loop: } /*********************************************************//** +Moves the persistent cursor to the previous user record in the tree. If no user +records are left, the cursor ends up 'before first in tree'. +@return TRUE if the cursor moved forward, ending on a user record */ +UNIV_INLINE +ibool +btr_pcur_move_to_prev_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_before_first_on_page(cursor)) { + + if (btr_pcur_is_before_first_in_tree(cursor, mtr)) { + + return(FALSE); + } + + btr_pcur_move_to_prev(cursor, mtr); + } else { + btr_pcur_move_to_prev_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 */ diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index bd2a15fe881..5037bc48bda 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -192,6 +192,8 @@ be less than 256 */ /** Check whether locking is disabled (never). */ #define dict_table_is_locking_disabled(table) false +#define DATA_VERS_ROW_START 0x4000 /* System Versioning row start */ +#define DATA_VERS_ROW_END 0x8000 /* System Versioning row end */ /*-------------------------------------------*/ /* This many bytes we need to store the type information affecting the diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index 25aced44b2e..ccac7c110cc 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -326,6 +326,29 @@ enum dict_fld_sys_datafiles_enum { DICT_NUM_FIELDS__SYS_DATAFILES = 4 }; +/* The columns in SYS_VTQ */ +enum dict_col_sys_vtq_enum +{ + DICT_COL__SYS_VTQ__TRX_ID = 0, + DICT_COL__SYS_VTQ__COMMIT_ID = 1, + DICT_COL__SYS_VTQ__BEGIN_TS = 2, + DICT_COL__SYS_VTQ__COMMIT_TS = 3, + DICT_COL__SYS_VTQ__ISOLATION_LEVEL = 4, + DICT_NUM_COLS__SYS_VTQ = 5 +}; +/* The field numbers in the SYS_VTQ clustered index */ +enum dict_fld_sys_vtq_enum +{ + DICT_FLD__SYS_VTQ__TRX_ID = 0, + DICT_FLD__SYS_VTQ__DB_TRX_ID = 1, + DICT_FLD__SYS_VTQ__DB_ROLL_PTR = 2, + DICT_FLD__SYS_VTQ__COMMIT_ID = 3, + DICT_FLD__SYS_VTQ__BEGIN_TS = 4, + DICT_FLD__SYS_VTQ__COMMIT_TS = 5, + DICT_FLD__SYS_VTQ__ISOLATION_LEVEL = 6, + DICT_NUM_FIELDS__SYS_VTQ = 7 +}; + /* The columns in SYS_VIRTUAL */ enum dict_col_sys_virtual_enum { DICT_COL__SYS_VIRTUAL__TABLE_ID = 0, diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index 86a4bcf23a3..4992687a5b6 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -311,6 +311,10 @@ struct tab_node_t{ storage */ }; +UNIV_INTERN +dberr_t +dict_create_or_check_vtq_table(void); + /* Table create node states */ #define TABLE_BUILD_TABLE_DEF 1 #define TABLE_BUILD_COL_DEF 2 diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index f14487f09d0..ee7df080cb0 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1708,6 +1708,8 @@ struct dict_sys_t{ dict_table_t* sys_columns; /*!< SYS_COLUMNS table */ dict_table_t* sys_indexes; /*!< SYS_INDEXES table */ dict_table_t* sys_fields; /*!< SYS_FIELDS table */ + dict_table_t* sys_vtq; /*!< SYS_VTQ table */ + dict_index_t* vtq_commit_ts_ind; dict_table_t* sys_virtual; /*!< SYS_VIRTUAL table */ /*=============================*/ diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index 22fd27c2484..a32aebc6743 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -31,6 +31,7 @@ Created 4/24/1996 Heikki Tuuri #include "univ.i" #include "dict0types.h" #include "trx0types.h" +#include "trx0vtq.h" #include "ut0byte.h" #include "mem0mem.h" #include "btr0types.h" @@ -52,6 +53,7 @@ enum dict_system_id_t { SYS_TABLESPACES, SYS_DATAFILES, SYS_VIRTUAL, + SYS_VTQ, /* This must be last item. Defines the number of system tables. */ SYS_NUM_SYSTEM_TABLES @@ -181,7 +183,8 @@ dict_startscan_system( btr_pcur_t* pcur, /*!< out: persistent cursor to the record */ mtr_t* mtr, /*!< in: the mini-transaction */ - dict_system_id_t system_id); /*!< in: which system table to open */ + dict_system_id_t system_id, /*!< in: which system table to open */ + bool from_left = true); /********************************************************************//** This function get the next system table record as we scan the table. @return the record if found, NULL if end of scan. */ @@ -314,6 +317,18 @@ dict_process_sys_datafiles( const rec_t* rec, /*!< in: current SYS_DATAFILES rec */ ulint* space, /*!< out: pace id */ const char** path); /*!< out: datafile path */ +/********************************************************************//** +This function parses a SYS_VTQ record, extracts necessary +information from the record and returns it to the caller. +@return error message, or NULL on success */ +UNIV_INTERN +const char* +dict_process_sys_vtq( +/*=======================*/ +mem_heap_t* heap, /*!< in/out: heap memory */ +const rec_t* rec, /*!< in: current rec */ +vtq_record_t& fields /*!< out: field values */ +); /** Update the record for space_id in SYS_TABLESPACES to this filepath. @param[in] space_id Tablespace ID @@ -338,4 +353,9 @@ dict_replace_tablespace_and_filepath( const char* filepath, ulint fsp_flags); + +UNIV_INTERN +dict_table_t* +get_vtq_table(); + #endif diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index ed39ed8a6c6..87564f58db4 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -245,7 +245,7 @@ ROW_FORMAT=REDUNDANT. InnoDB engines do not check these flags for unknown bits in order to protect backward incompatibility. */ /* @{ */ /** Total number of bits in table->flags2. */ -#define DICT_TF2_BITS 7 +#define DICT_TF2_BITS 8 #define DICT_TF2_UNUSED_BIT_MASK (~0U << DICT_TF2_BITS) #define DICT_TF2_BIT_MASK ~DICT_TF2_UNUSED_BIT_MASK @@ -273,6 +273,9 @@ use its own tablespace instead of the system tablespace. */ index tables) of a FTS table are in HEX format. */ #define DICT_TF2_FTS_AUX_HEX_NAME 64U +/** System Versioning bit. */ +#define DICT_TF2_VERSIONED 128U + /* @} */ #define DICT_TF2_FLAG_SET(table, flag) \ @@ -1602,7 +1605,10 @@ struct dict_table_t { /** Virtual column names */ const char* v_col_names; - + unsigned vers_row_start:10; + /*!< System Versioning: row start col index */ + unsigned vers_row_end:10; + /*!< System Versioning: row end col index */ bool is_system_db; /*!< True if the table belongs to a system database (mysql, information_schema or diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h index 763b16820d8..13be7291f00 100644 --- a/storage/innobase/include/que0que.h +++ b/storage/innobase/include/que0que.h @@ -381,9 +381,6 @@ struct que_thr_t{ thrs; /*!< list of thread nodes of the fork node */ UT_LIST_NODE_T(que_thr_t) - trx_thrs; /*!< lists of threads in wait list of - the trx */ - UT_LIST_NODE_T(que_thr_t) queue; /*!< list of runnable thread nodes in the server task queue */ ulint fk_cascade_depth; /*!< maximum cascading call depth diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h index 8cb3a2f16cd..561f6f2d8fe 100644 --- a/storage/innobase/include/row0ins.h +++ b/storage/innobase/include/row0ins.h @@ -95,9 +95,10 @@ row_ins_clust_index_entry_low( dtuple_t* entry, /*!< in/out: index entry to insert */ ulint n_ext, /*!< in: number of externally stored columns */ que_thr_t* thr, /*!< in: query thread or NULL */ - bool dup_chk_only) + bool dup_chk_only, /*!< in: if true, just do duplicate check and return. don't execute actual insert. */ + trx_t* trx = 0) MY_ATTRIBUTE((warn_unused_result)); /***************************************************************//** @@ -123,9 +124,10 @@ row_ins_sec_index_entry_low( trx_id_t trx_id, /*!< in: PAGE_MAX_TRX_ID during row_log_table_apply(), or 0 */ que_thr_t* thr, /*!< in: query thread */ - bool dup_chk_only) + bool dup_chk_only, /*!< in: if true, just do duplicate check and return. don't execute actual insert. */ + trx_t* trx = 0) MY_ATTRIBUTE((warn_unused_result)); /** Sets the values of the dtuple fields in entry from the values of appropriate columns in row. @@ -180,6 +182,11 @@ row_ins_step( /*=========*/ que_thr_t* thr); /*!< in: query thread */ +/***********************************************************//** +Inserts a row to SYS_VTQ table. +@return error state */ +void vers_notify_vtq(trx_t* trx); + /* Insert node structure */ struct ins_node_t{ @@ -228,4 +235,8 @@ struct ins_node_t{ #define INS_NODE_INSERT_ENTRIES 3 /* index entries should be built and inserted */ +#ifndef UNIV_NONINL +#include "row0ins.ic" +#endif + #endif diff --git a/storage/innobase/include/row0ins.ic b/storage/innobase/include/row0ins.ic new file mode 100644 index 00000000000..9f951bda2be --- /dev/null +++ b/storage/innobase/include/row0ins.ic @@ -0,0 +1,78 @@ +/***************************************************************************** + +Copyright (c) 1996, 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, Suite 500, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/**************************************************//** +@file include/row0ins.ic +Insert into a table + +Created 4/20/1996 Heikki Tuuri +*******************************************************/ + + +UNIV_INLINE +void set_tuple_col_8( + dtuple_t* tuple, + int col, + ib_uint64_t data, + mem_heap_t* heap) +{ + static const ulint fsize = sizeof(data); + dfield_t* dfield = dtuple_get_nth_field(tuple, col); + ut_ad(dfield->type.len == fsize); + if (dfield->len == UNIV_SQL_NULL) { + byte* buf = reinterpret_cast<byte*>(mem_heap_alloc(heap, fsize)); + dfield_set_data(dfield, buf, fsize); + } + ut_ad(dfield->len == dfield->type.len && dfield->data); + mach_write_to_8(dfield->data, data); +} + +UNIV_INLINE +void set_tuple_col_8( + dtuple_t* tuple, + int col, + timeval& data, + mem_heap_t* heap) +{ + dfield_t* dfield = dtuple_get_nth_field(tuple, col); + ut_ad(dfield->type.len == 8); + if (dfield->len == UNIV_SQL_NULL) { + byte* buf = reinterpret_cast<byte*>(mem_heap_alloc(heap, 8)); + dfield_set_data(dfield, buf, 8); + } + ut_ad(dfield->len == dfield->type.len && dfield->data); + mach_write_to_4(reinterpret_cast<byte*>(dfield->data), (ulint) data.tv_sec); + mach_write_to_4(reinterpret_cast<byte*>(dfield->data) + 4, (ulint) data.tv_usec); +} + +UNIV_INLINE +void set_tuple_col_1( + dtuple_t* tuple, + int col, + byte data, + mem_heap_t* heap) +{ + dfield_t* dfield = dtuple_get_nth_field(tuple, col); + ut_ad(dfield->type.len == 1); + if (dfield->len == UNIV_SQL_NULL) { + byte* buf = reinterpret_cast<byte*>(mem_heap_alloc(heap, 1)); + dfield_set_data(dfield, buf, 1); + } + ut_ad(dfield->len == dfield->type.len && dfield->data); + *(byte*)(dfield->data) = data; +} diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h index ca620cbef59..85a3e8d2e50 100644 --- a/storage/innobase/include/row0merge.h +++ b/storage/innobase/include/row0merge.h @@ -343,7 +343,8 @@ row_merge_build_indexes( bool skip_pk_sort, ut_stage_alter_t* stage, const dict_add_v_col_t* add_v, - struct TABLE* eval_table) + struct TABLE* eval_table, + bool drop_historical) MY_ATTRIBUTE((warn_unused_result)); /********************************************************************//** diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index a7a55d202e8..9f8be316c1c 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -235,6 +235,15 @@ row_lock_table_for_mysql( (ignored if table==NULL) */ MY_ATTRIBUTE((nonnull(1))); +/* System Versioning: row_insert_for_mysql() modes */ +enum ins_mode_t { + ROW_INS_NORMAL = 0, + // insert versioned row: sys_trx_start = TRX_ID, sys_trx_end = MAX + ROW_INS_VERSIONED, + // insert historical row: sys_trx_end = TRX_ID + ROW_INS_HISTORICAL +}; + /** Does an insert for MySQL. @param[in] mysql_rec row in the MySQL format @param[in,out] prebuilt prebuilt struct in MySQL handle @@ -242,7 +251,8 @@ row_lock_table_for_mysql( dberr_t row_insert_for_mysql( const byte* mysql_rec, - row_prebuilt_t* prebuilt) + row_prebuilt_t* prebuilt, + ins_mode_t ins_mode) MY_ATTRIBUTE((warn_unused_result)); /*********************************************************************//** @@ -266,7 +276,9 @@ row_get_prebuilt_update_vector( @param[in,out] prebuilt prebuilt struct in MySQL handle @return error code or DB_SUCCESS */ dberr_t -row_update_for_mysql(row_prebuilt_t* prebuilt) +row_update_for_mysql( + row_prebuilt_t* prebuilt, + bool vers_set_fields) MY_ATTRIBUTE((warn_unused_result)); /** This can only be used when srv_locks_unsafe_for_binlog is TRUE or this diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 92b5942966b..97c0b0d4202 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -573,6 +573,8 @@ struct upd_node_t{ compilation; speeds up execution: UPD_NODE_NO_ORD_CHANGE and UPD_NODE_NO_SIZE_CHANGE, ORed */ + bool versioned;/* update is versioned */ + bool vers_delete;/* versioned delete */ /*----------------------*/ /* Local storage for this graph node */ ulint state; /*!< node execution state */ diff --git a/storage/innobase/include/sync0policy.h b/storage/innobase/include/sync0policy.h index a91270bde58..21ae18aac82 100644 --- a/storage/innobase/include/sync0policy.h +++ b/storage/innobase/include/sync0policy.h @@ -59,7 +59,11 @@ public: @param[in] id ID of the latch to track */ Context(latch_id_t id) : - latch_t(id) + latch_t(id), + m_mutex(), + m_filename(), + m_line(), + m_thread_id(os_thread_id_t(ULINT_UNDEFINED)) { ut_ad(id != LATCH_ID_NONE); } diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 133f23081a0..f287fea3ec6 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -42,6 +42,7 @@ Created 3/26/1996 Heikki Tuuri #include "que0types.h" #include "mem0mem.h" #include "trx0xa.h" +#include "trx0vtq.h" #include "ut0vec.h" #include "fts0fts.h" #include "srv0srv.h" @@ -836,7 +837,6 @@ typedef enum { TRX_WSREP_ABORT = 1 } trx_abort_t; - /** Represents an instance of rollback segment along with its state variables.*/ struct trx_undo_ptr_t { trx_rseg_t* rseg; /*!< rollback segment assigned to the @@ -1269,6 +1269,10 @@ struct trx_t { os_event_t wsrep_event; /* event waited for in srv_conc_slot */ #endif /* WITH_WSREP */ + /* System Versioning */ + bool vtq_notify_on_commit; + /*!< Notify VTQ for System Versioned update */ + vtq_query_t vtq_query; ulint magic_n; /** @return whether any persistent undo log has been generated */ diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 8092246c7fa..45c3356d8ec 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -146,6 +146,7 @@ typedef ib_id_t undo_no_t; /** Transaction savepoint */ struct trx_savept_t{ undo_no_t least_undo_no; /*!< least undo number to undo */ + bool vtq_notify_on_commit; /*!< Notify VTQ for System Versioned update */ }; /** File objects */ diff --git a/storage/innobase/include/trx0vtq.h b/storage/innobase/include/trx0vtq.h new file mode 100644 index 00000000000..5767dfeb5a0 --- /dev/null +++ b/storage/innobase/include/trx0vtq.h @@ -0,0 +1,40 @@ +#ifndef trx0vtq_h +#define trx0vtq_h + +/* Copyright (c) 2016, 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-1301, USA */ + +#include <vtq.h> +#include "trx0types.h" +#include "mem0mem.h" +#include "rem0types.h" + +class vtq_query_t +{ +public: + timeval prev_query; + bool backwards; + + vtq_record_t result; + + const char * cache_result(mem_heap_t* heap, const rec_t* rec); + const char * cache_result( + mem_heap_t* heap, + const rec_t* rec, + const timeval &_ts_query, + bool _backwards); +}; + +#endif // trx0vtq_h diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 80c0b5476b0..79cb3c2dc9f 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -454,6 +454,8 @@ typedef uint32_t ib_uint32_t; #define UINT64PF "%" UINT64scan #define IB_ID_FMT UINT64PF +typedef ib_uint64_t ullong; + /** Log sequence number (also used for redo log byte arithmetics) */ typedef ib_uint64_t lsn_t; diff --git a/storage/innobase/include/vers0vtq.h b/storage/innobase/include/vers0vtq.h new file mode 100644 index 00000000000..2b486c25271 --- /dev/null +++ b/storage/innobase/include/vers0vtq.h @@ -0,0 +1,52 @@ +/* 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-1301, USA */ + +/** Query VTQ by TRX_ID. +@param[in] thd MySQL thread +@param[out] out field value or whole record returned by query (selected by `field`) +@param[in] in_trx_id query parameter TRX_ID +@param[in] field field to get in `out` or VTQ_ALL for whole record (vtq_record_t) +@return TRUE if record is found, FALSE otherwise */ +bool +vtq_query_trx_id(THD* thd, void *out, ulonglong in_trx_id, vtq_field_t field); + +/** Query VTQ by COMMIT_TS. +@param[in] thd MySQL thread +@param[out] out field value or whole record returned by query (selected by `field`) +@param[in] commit_ts query parameter COMMIT_TS +@param[in] field field to get in `out` or VTQ_ALL for whole record (vtq_record_t) +@param[in] backwards direction of VTQ search +@return TRUE if record is found, FALSE otherwise */ +bool +vtq_query_commit_ts(THD* thd, void *out, const MYSQL_TIME &commit_ts, vtq_field_t field, bool backwards); + +/** Check if transaction TX1 sees transaction TX0. +@param[in] thd MySQL thread +@param[out] result true if TX1 sees TX0 +@param[in] trx_id1 TX1 TRX_ID +@param[in] trx_id0 TX0 TRX_ID +@param[in] commit_id1 TX1 COMMIT_ID +@param[in] iso_level1 TX1 isolation level +@param[in] commit_id0 TX0 COMMIT_ID +@return FALSE if there is no trx_id1 in VTQ, otherwise TRUE */ +bool +vtq_trx_sees( + THD *thd, + bool &result, + ulonglong trx_id1, + ulonglong trx_id0, + ulonglong commit_id1, + uchar iso_level1, + ulonglong commit_id0); diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 3729256c03b..1822523a3fb 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -27,6 +27,11 @@ Created 4/20/1996 Heikki Tuuri #include "ha_prototypes.h" #include "row0ins.h" + +#ifdef UNIV_NONINL +#include "row0ins.ic" +#endif + #include "dict0dict.h" #include "dict0boot.h" #include "trx0rec.h" @@ -429,7 +434,8 @@ row_ins_cascade_ancestor_updates_table( upd_node = static_cast<upd_node_t*>(parent); - if (upd_node->table == table && upd_node->is_delete == FALSE) { + if (upd_node->table == table && upd_node->is_delete == FALSE + && !upd_node->vers_delete) { return(TRUE); } @@ -974,6 +980,8 @@ row_ins_foreign_fill_virtual( innobase_init_vc_templ(index->table); } + bool is_delete = node->is_delete || node->vers_delete; + for (ulint i = 0; i < n_v_fld; i++) { dict_v_col_t* col = dict_table_get_nth_v_col( @@ -1005,14 +1013,14 @@ row_ins_foreign_fill_virtual( upd_field_set_v_field_no(upd_field, i, index); - if (node->is_delete + if (is_delete ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) { dfield_set_null(&upd_field->new_val); } - if (!node->is_delete + if (!is_delete && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) { dfield_t* new_vfield = innobase_get_computed_value( @@ -1105,7 +1113,9 @@ row_ins_foreign_check_on_constraint( node = static_cast<upd_node_t*>(thr->run_node); - if (node->is_delete && 0 == (foreign->type + bool is_delete = node->is_delete || node->vers_delete; + + if (is_delete && 0 == (foreign->type & (DICT_FOREIGN_ON_DELETE_CASCADE | DICT_FOREIGN_ON_DELETE_SET_NULL))) { @@ -1116,7 +1126,7 @@ row_ins_foreign_check_on_constraint( DBUG_RETURN(DB_ROW_IS_REFERENCED); } - if (!node->is_delete && 0 == (foreign->type + if (!is_delete && 0 == (foreign->type & (DICT_FOREIGN_ON_UPDATE_CASCADE | DICT_FOREIGN_ON_UPDATE_SET_NULL))) { @@ -1145,7 +1155,7 @@ row_ins_foreign_check_on_constraint( cascade->foreign = foreign; - if (node->is_delete + if (is_delete && (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)) { cascade->is_delete = TRUE; } else { @@ -1284,7 +1294,7 @@ row_ins_foreign_check_on_constraint( clust_index, tmp_heap); } - if (node->is_delete + if (is_delete ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) { @@ -1364,7 +1374,7 @@ row_ins_foreign_check_on_constraint( } } - if (!node->is_delete + if (!is_delete && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) { /* Build the appropriate update vector which sets changing @@ -1568,6 +1578,69 @@ private: ulint& counter; }; +/*********************************************************************//** +Reads sys_trx_end field from clustered index row. +@return trx_id_t */ +static +trx_id_t +row_ins_get_sys_trx_end( +/*===================================*/ + const rec_t *rec, /*!< in: clustered row */ + ulint *offsets, /*!< in: offsets */ + dict_index_t *index) /*!< in: clustered index */ +{ + ut_a(dict_index_is_clust(index)); + + ulint len; + ulint nfield = dict_col_get_clust_pos( + &index->table->cols[index->table->vers_row_end], index); + const byte *field = rec_get_nth_field(rec, offsets, nfield, &len); + ut_a(len == 8); + return(mach_read_from_8(field)); +} + +/*********************************************************************//** +Performs search at clustered index and returns sys_trx_end if row was found. +@return DB_SUCCESS, DB_NO_REFERENCED_ROW */ +static +dberr_t +row_ins_search_sys_trx_end( +/*=======================*/ + dict_index_t *index, /*!< in: index of record */ + const rec_t *rec, /*!< in: record */ + trx_id_t *end_trx_id) /*!< out: end_trx_id */ +{ + bool found = false; + mem_heap_t *heap = mem_heap_create(256); + dict_index_t *clust_index = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + ulint *offsets = offsets_; + rec_offs_init(offsets_); + + mtr_t mtr; + mtr_start(&mtr); + + rec_t *clust_rec = + row_get_clust_rec(BTR_SEARCH_LEAF, rec, index, &clust_index, &mtr); + if (!clust_rec) + goto not_found; + + offsets = rec_get_offsets(clust_rec, clust_index, offsets, true, + ULINT_UNDEFINED, &heap); + + *end_trx_id = row_ins_get_sys_trx_end(clust_rec, offsets, clust_index); + found = true; +not_found: + mtr_commit(&mtr); + mem_heap_free(heap); + if (!found) { + fprintf(stderr, "InnoDB: foreign constraints: secondary index is out of sync\n"); + ut_ad(false && "secondary index is out of sync"); + return(DB_NO_REFERENCED_ROW); + } + return(DB_SUCCESS); +} + /***************************************************************//** Checks if foreign key constraint fails for an index entry. Sets shared locks which lock either the success or the failure of the constraint. NOTE that @@ -1625,16 +1698,28 @@ row_ins_check_foreign_constraint( /* If any of the foreign key fields in entry is SQL NULL, we suppress the foreign key check: this is compatible with Oracle, for example */ - for (ulint i = 0; i < foreign->n_fields; i++) { - if (dfield_is_null(dtuple_get_nth_field(entry, i))) { + for (ulint i = 0; i < entry->n_fields; i++) { + dfield_t* field = dtuple_get_nth_field(entry, i); + if (i < foreign->n_fields && dfield_is_null(field)) { goto exit_func; } + /* System Versioning: if sys_trx_end != Inf, we + suppress the foreign key check */ + if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_VERSIONED) && + dfield_get_type(field)->prtype & DATA_VERS_ROW_END) + { + byte* data = static_cast<byte*>(dfield_get_data(field)); + ut_ad(data); + trx_id_t end_trx_id = mach_read_from_8(data); + if (end_trx_id != TRX_ID_MAX) + goto exit_func; + } } if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) { upd_node = static_cast<upd_node_t*>(thr->run_node); - if (!(upd_node->is_delete) && upd_node->foreign == foreign) { + if (!(upd_node->is_delete) && !(upd_node->vers_delete) && upd_node->foreign == foreign) { /* If a cascaded update is done as defined by a foreign key constraint, do not check that constraint for the child row. In ON UPDATE CASCADE @@ -1757,6 +1842,23 @@ row_ins_check_foreign_constraint( cmp = cmp_dtuple_rec(entry, rec, offsets); if (cmp == 0) { + if (DICT_TF2_FLAG_IS_SET(check_table, DICT_TF2_VERSIONED)) { + trx_id_t end_trx_id = 0; + + if (dict_index_is_clust(check_index)) { + end_trx_id = + row_ins_get_sys_trx_end( + rec, offsets, check_index); + } else if (row_ins_search_sys_trx_end( + check_index, rec, &end_trx_id) != + DB_SUCCESS) { + break; + } + + if (end_trx_id != TRX_ID_MAX) + continue; + } + if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { /* In delete-marked records, DB_TRX_ID must @@ -2064,7 +2166,8 @@ row_ins_scan_sec_index_for_duplicate( que_thr_t* thr, /*!< in: query thread */ bool s_latch,/*!< in: whether index->lock is being held */ mtr_t* mtr, /*!< in/out: mini-transaction */ - mem_heap_t* offsets_heap) + mem_heap_t* offsets_heap, + trx_t* trx = 0) /*!< in/out: memory heap that can be emptied */ { ulint n_unique; @@ -2077,6 +2180,10 @@ row_ins_scan_sec_index_for_duplicate( DBUG_ENTER("row_ins_scan_sec_index_for_duplicate"); + ut_ad(thr || (trx && flags & BTR_NO_LOCKING_FLAG)); + if (!trx) + trx = thr_get_trx(thr); + ut_ad(s_latch == rw_lock_own_flagged( &index->lock, RW_LOCK_FLAG_S | RW_LOCK_FLAG_SX)); @@ -2108,7 +2215,7 @@ row_ins_scan_sec_index_for_duplicate( : BTR_SEARCH_LEAF, &pcur, mtr); - allow_duplicates = thr_get_trx(thr)->duplicates; + allow_duplicates = trx->duplicates; /* Scan index records and check if there is a duplicate */ @@ -2164,7 +2271,7 @@ row_ins_scan_sec_index_for_duplicate( index, offsets)) { err = DB_DUPLICATE_KEY; - thr_get_trx(thr)->error_info = index; + trx->error_info = index; /* If the duplicate is on hidden FTS_DOC_ID, state so in the error log */ @@ -2551,9 +2658,10 @@ row_ins_clust_index_entry_low( dtuple_t* entry, /*!< in/out: index entry to insert */ ulint n_ext, /*!< in: number of externally stored columns */ que_thr_t* thr, /*!< in: query thread */ - bool dup_chk_only) + bool dup_chk_only, /*!< in: if true, just do duplicate check and return. don't execute actual insert. */ + trx_t* trx) { btr_pcur_t pcur; btr_cur_t* cursor; @@ -2568,11 +2676,15 @@ row_ins_clust_index_entry_low( DBUG_ENTER("row_ins_clust_index_entry_low"); + ut_ad(thr || trx); + if (!trx) + trx = thr_get_trx(thr); + ut_ad(dict_index_is_clust(index)); ut_ad(!dict_index_is_unique(index) || n_uniq == dict_index_get_n_unique(index)); ut_ad(!n_uniq || n_uniq == dict_index_get_n_unique(index)); - ut_ad(!thr_get_trx(thr)->in_rollback); + ut_ad(!trx->in_rollback); mtr_start(&mtr); @@ -2677,7 +2789,10 @@ row_ins_clust_index_entry_low( if (flags == (BTR_CREATE_FLAG | BTR_NO_LOCKING_FLAG - | BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_FLAG)) { + | BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_FLAG) || !thr) { + // thr == 0 for SYS_VTQ table + ut_ad(thr || flags & + (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_FLAG)); /* Set no locks when applying log in online table rebuild. Only check for duplicates. */ err = row_ins_duplicate_error_in_clust_online( @@ -2692,7 +2807,7 @@ row_ins_clust_index_entry_low( /* fall through */ case DB_SUCCESS_LOCKED_REC: case DB_DUPLICATE_KEY: - thr_get_trx(thr)->error_info = cursor->index; + trx->error_info = cursor->index; } } else { /* Note that the following may return also @@ -2782,7 +2897,7 @@ do_insert: LSN_MAX, TRUE);); err = row_ins_index_entry_big_rec( entry, big_rec, offsets, &offsets_heap, index, - thr_get_trx(thr)->mysql_thd); + trx->mysql_thd); dtuple_convert_back_big_rec(index, entry, big_rec); } else { if (err == DB_SUCCESS @@ -2876,9 +2991,10 @@ row_ins_sec_index_entry_low( trx_id_t trx_id, /*!< in: PAGE_MAX_TRX_ID during row_log_table_apply(), or 0 */ que_thr_t* thr, /*!< in: query thread */ - bool dup_chk_only) + bool dup_chk_only, /*!< in: if true, just do duplicate check and return. don't execute actual insert. */ + trx_t* trx) { DBUG_ENTER("row_ins_sec_index_entry_low"); @@ -2892,12 +3008,16 @@ row_ins_sec_index_entry_low( rec_offs_init(offsets_); rtr_info_t rtr_info; + ut_ad(thr || trx); + if (!trx) + trx = thr_get_trx(thr); + ut_ad(!dict_index_is_clust(index)); ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_MODIFY_TREE); cursor.thr = thr; cursor.rtr_info = NULL; - ut_ad(thr_get_trx(thr)->id != 0); + ut_ad(trx && trx->id != 0 || thr_get_trx(thr)->id != 0); mtr_start(&mtr); mtr.set_named_space(index->space); @@ -2933,7 +3053,7 @@ row_ins_sec_index_entry_low( } if (row_log_online_op_try( - index, entry, thr_get_trx(thr)->id)) { + index, entry, trx->id)) { goto func_exit; } } @@ -2942,7 +3062,7 @@ row_ins_sec_index_entry_low( the function will return in both low_match and up_match of the cursor sensible values */ - if (!thr_get_trx(thr)->check_unique_secondary) { + if (!trx->check_unique_secondary) { search_mode |= BTR_IGNORE_SEC_UNIQUE; } @@ -2985,8 +3105,6 @@ row_ins_sec_index_entry_low( } if (err != DB_SUCCESS) { - trx_t* trx = thr_get_trx(thr); - if (err == DB_DECRYPTION_FAILED) { ib_push_warning(trx->mysql_thd, DB_DECRYPTION_FAILED, @@ -3030,7 +3148,7 @@ row_ins_sec_index_entry_low( } err = row_ins_scan_sec_index_for_duplicate( - flags, index, entry, thr, check, &mtr, offsets_heap); + flags, index, entry, thr, check, &mtr, offsets_heap, trx); mtr_commit(&mtr); @@ -3039,7 +3157,7 @@ row_ins_sec_index_entry_low( break; case DB_DUPLICATE_KEY: if (!index->is_committed()) { - ut_ad(!thr_get_trx(thr) + ut_ad(!trx ->dict_operation_lock_mode); mutex_enter(&dict_sys->mutex); dict_set_corrupted_index_cache_only(index); @@ -3082,8 +3200,8 @@ row_ins_sec_index_entry_low( if (!(flags & BTR_NO_LOCKING_FLAG) && dict_index_is_unique(index) - && thr_get_trx(thr)->duplicates - && thr_get_trx(thr)->isolation_level >= TRX_ISO_REPEATABLE_READ) { + && trx->duplicates + && trx->isolation_level >= TRX_ISO_REPEATABLE_READ) { /* When using the REPLACE statement or ON DUPLICATE clause, a gap lock is taken on the position of the to-be-inserted record, @@ -3106,7 +3224,7 @@ row_ins_sec_index_entry_low( switch (err) { case DB_SUCCESS: case DB_SUCCESS_LOCKED_REC: - if (thr_get_trx(thr)->error_state != DB_DUPLICATE_KEY) { + if (trx->error_state != DB_DUPLICATE_KEY) { break; } /* Fall through (skip actual insert) after we have @@ -3116,7 +3234,7 @@ row_ins_sec_index_entry_low( } } - ut_ad(thr_get_trx(thr)->error_state == DB_SUCCESS); + ut_ad(trx->error_state == DB_SUCCESS); if (dup_chk_only) { goto func_exit; @@ -3874,3 +3992,94 @@ error_handling: return(thr); } + +/***********************************************************//** +Inserts a row to SYS_VTQ, low level. +@return DB_SUCCESS if operation successfully completed, else error +code */ +static __attribute__((nonnull, warn_unused_result)) +dberr_t +vers_row_ins_vtq_low(trx_t* trx, mem_heap_t* heap, dtuple_t* tuple) +{ + dberr_t err; + dtuple_t* entry; + ulint n_index = 0; + dict_index_t* index = dict_table_get_first_index(dict_sys->sys_vtq); + static const ulint flags + = (BTR_KEEP_SYS_FLAG + | BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG); + + entry = row_build_index_entry(tuple, NULL, index, heap); + + dfield_t* dfield = dtuple_get_nth_field(entry, DATA_TRX_ID); + ut_ad(dfield->type.len == DATA_TRX_ID_LEN); + dfield_set_data(dfield, mem_heap_alloc(heap, DATA_TRX_ID_LEN), DATA_TRX_ID_LEN); + row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id); + + err = row_ins_clust_index_entry_low( + flags, BTR_MODIFY_TREE, index, index->n_uniq, entry, 0, NULL, false, trx); + + switch (err) { + case DB_SUCCESS: + break; + case DB_SUCCESS_LOCKED_REC: + /* The row had already been copied to the table. */ + fprintf(stderr, "InnoDB: duplicate VTQ record!\n"); + return DB_SUCCESS; + default: + return err; + } + + mem_heap_t* offsets_heap = mem_heap_create(1024); + + do { + if (!(index = dict_table_get_next_index(index))) { + break; + } + + n_index++; + + entry = row_build_index_entry(tuple, NULL, index, heap); + err = row_ins_sec_index_entry_low( + flags, BTR_MODIFY_TREE, + index, offsets_heap, heap, entry, trx->id, NULL, false, trx); + } while (err == DB_SUCCESS); + ut_ad(n_index == 3 || err != DB_SUCCESS); + + mem_heap_free(offsets_heap); + return err; +} + +/***********************************************************//** +Inserts a row to SYS_VTQ table. +@return error state */ +void vers_notify_vtq(trx_t* trx) +{ + dberr_t err; + mem_heap_t* heap = mem_heap_create(1024); + dtuple_t* tuple = dtuple_create(heap, dict_table_get_n_cols(dict_sys->sys_vtq)); + + timeval begin_ts, commit_ts; + begin_ts.tv_sec = trx->start_time; + begin_ts.tv_usec = trx->start_time_micro % 1000000; + + mutex_enter(&trx_sys->mutex); + trx_id_t commit_id = trx_sys_get_new_trx_id(); + ut_usectime((ulint *)&commit_ts.tv_sec, (ulint *)&commit_ts.tv_usec); + mutex_exit(&trx_sys->mutex); + + dict_table_copy_types(tuple, dict_sys->sys_vtq); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__TRX_ID, trx->id, heap); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__COMMIT_ID, commit_id, heap); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__BEGIN_TS, begin_ts, heap); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__COMMIT_TS, commit_ts, heap); + ut_ad(trx->isolation_level < 256); + set_tuple_col_1(tuple, DICT_COL__SYS_VTQ__ISOLATION_LEVEL, trx->isolation_level, heap); + + err = vers_row_ins_vtq_low(trx, heap, tuple); + if (DB_SUCCESS != err) + fprintf(stderr, "InnoDB: failed to insert VTQ record (error %d)\n", err); + + mem_heap_free(heap); +} diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 6a6c65cd70c..393a00f83c3 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1707,7 +1707,8 @@ row_merge_read_clustered_index( ut_stage_alter_t* stage, double pct_cost, row_merge_block_t* crypt_block, - struct TABLE* eval_table) + struct TABLE* eval_table, + bool drop_historical) { dict_index_t* clust_index; /* Clustered index */ mem_heap_t* row_heap; /* Heap memory to create @@ -1741,6 +1742,7 @@ row_merge_read_clustered_index( double curr_progress = 0.0; ib_uint64_t read_rows = 0; ib_uint64_t table_total_rows = 0; + ulonglong historic_auto_decrement = 0xffffffffffffffff; DBUG_ENTER("row_merge_read_clustered_index"); @@ -2238,6 +2240,18 @@ end_of_index: ut_ad(add_autoinc < dict_table_get_n_user_cols(new_table)); + bool historical_row = false; + if (DICT_TF2_FLAG_IS_SET( + new_table, DICT_TF2_VERSIONED)) { + const dfield_t *dfield = dtuple_get_nth_field( + row, new_table->vers_row_end); + const byte *data = static_cast<const byte *>( + dfield_get_data(dfield)); + ut_ad(dfield_get_len(dfield) == 8); + historical_row = + mach_read_from_8(data) != TRX_ID_MAX; + } + const dfield_t* dfield; dfield = dtuple_get_nth_field(row, add_autoinc); @@ -2258,7 +2272,11 @@ end_of_index: goto func_exit; } - ulonglong value = sequence++; + ulonglong value; + if (likely(!historical_row)) + value = sequence++; + else + value = historic_auto_decrement--; switch (dtype_get_mtype(dtype)) { case DATA_INT: { @@ -2286,6 +2304,49 @@ end_of_index: } } + if (DICT_TF2_FLAG_IS_SET(old_table, DICT_TF2_VERSIONED)) { + if (DICT_TF2_FLAG_IS_SET(new_table, + DICT_TF2_VERSIONED) && + !drop_historical) { + dfield_t *end = dtuple_get_nth_field( + row, new_table->vers_row_end); + byte *data = static_cast<byte *>( + dfield_get_data(end)); + ut_ad(data); + if (mach_read_from_8(data) == TRX_ID_MAX) { + dfield_t *start = dtuple_get_nth_field( + row, new_table->vers_row_start); + void *data = dfield_get_data(start); + ut_ad(data); + mach_write_to_8(data, trx->id); + } + } else { + const dict_col_t *col = + &old_table->cols + [old_table->vers_row_end]; + const ulint nfield = dict_col_get_clust_pos( + col, clust_index); + ulint len = 0; + const rec_t *sys_trx_end = rec_get_nth_field( + rec, offsets, nfield, &len); + ut_ad(len == 8); + if (mach_read_from_8(sys_trx_end) != TRX_ID_MAX) + continue; + } + } else if (DICT_TF2_FLAG_IS_SET( + new_table, DICT_TF2_VERSIONED)) { + void *sys_trx_start = mem_heap_alloc(row_heap, 8); + void *sys_trx_end = mem_heap_alloc(row_heap, 8); + mach_write_to_8(sys_trx_start, trx->id); + mach_write_to_8(sys_trx_end, TRX_ID_MAX); + dfield_t *start = dtuple_get_nth_field( + row, new_table->vers_row_start); + dfield_t *end = dtuple_get_nth_field( + row, new_table->vers_row_end); + dfield_set_data(start, sys_trx_start, 8); + dfield_set_data(end, sys_trx_end, 8); + } + write_buffers: /* Build all entries for all the indexes to be created in a single scan of the clustered index. */ @@ -4564,7 +4625,8 @@ row_merge_build_indexes( bool skip_pk_sort, ut_stage_alter_t* stage, const dict_add_v_col_t* add_v, - struct TABLE* eval_table) + struct TABLE* eval_table, + bool drop_historical) { merge_file_t* merge_files; row_merge_block_t* block; @@ -4724,7 +4786,7 @@ row_merge_build_indexes( fts_sort_idx, psort_info, merge_files, key_numbers, n_indexes, add_cols, add_v, col_map, add_autoinc, sequence, block, skip_pk_sort, &tmpfd, stage, - pct_cost, crypt_block, eval_table); + pct_cost, crypt_block, eval_table, drop_historical); stage->end_phase_read_pk(); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 3f7c500c7f5..fb417eb4d59 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1427,7 +1427,8 @@ row_mysql_get_table_status( dberr_t row_insert_for_mysql( const byte* mysql_rec, - row_prebuilt_t* prebuilt) + row_prebuilt_t* prebuilt, + ins_mode_t ins_mode) { trx_savept_t savept; que_thr_t* thr; @@ -1494,6 +1495,27 @@ row_insert_for_mysql( row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec, &blob_heap); + if (ins_mode != ROW_INS_NORMAL) + { + ut_ad(table->vers_row_start != table->vers_row_end); + /* Return back modified fields into mysql_rec, so that + upper logic may benefit from it (f.ex. 'on duplicate key'). */ + const mysql_row_templ_t* t = &prebuilt->mysql_template[table->vers_row_end]; + ut_ad(t->mysql_col_len == 8); + + if (ins_mode == ROW_INS_HISTORICAL) { + set_tuple_col_8(node->row, table->vers_row_end, trx->id, node->entry_sys_heap); + } + else /* ROW_INS_VERSIONED */ { + set_tuple_col_8(node->row, table->vers_row_end, IB_UINT64_MAX, node->entry_sys_heap); + int8store(&mysql_rec[t->mysql_col_offset], IB_UINT64_MAX); + t = &prebuilt->mysql_template[table->vers_row_start]; + ut_ad(t->mysql_col_len == 8); + set_tuple_col_8(node->row, table->vers_row_start, trx->id, node->entry_sys_heap); + int8store(&mysql_rec[t->mysql_col_offset], trx->id); + } + } + savept = trx_savept_take(trx); thr = que_fork_get_first_thr(prebuilt->ins_graph); @@ -1547,6 +1569,10 @@ error_exit: node->duplicate = NULL; + if (DICT_TF2_FLAG_IS_SET(node->table, DICT_TF2_VERSIONED)) { + trx->vtq_notify_on_commit = true; + } + if (dict_table_has_fts_index(table)) { doc_id_t doc_id; @@ -1839,7 +1865,9 @@ public: @param[in,out] prebuilt prebuilt struct in MySQL handle @return error code or DB_SUCCESS */ dberr_t -row_update_for_mysql(row_prebuilt_t* prebuilt) +row_update_for_mysql_using_upd_graph( + row_prebuilt_t* prebuilt, + bool vers_set_fields) { trx_savept_t savept; dberr_t err; @@ -1854,6 +1882,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) upd_cascade_t* new_upd_nodes; upd_cascade_t* processed_cascades; bool got_s_lock = false; + bool vers_delete = prebuilt->upd_node->vers_delete; DBUG_ENTER("row_update_for_mysql"); @@ -1963,6 +1992,49 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) thr->fk_cascade_depth = 0; run_again: + if (vers_set_fields) + { + /* System Versioning: modify update vector to set + sys_trx_start (or sys_trx_end in case of DELETE) + to current trx_id. */ + dict_table_t* table = node->table; + dict_index_t* clust_index = dict_table_get_first_index(table); + upd_t* uvect = node->update; + upd_field_t* ufield; + dict_col_t* col; + unsigned col_idx; + if (node->is_delete || vers_delete) { + ufield = &uvect->fields[0]; + uvect->n_fields = 0; + node->is_delete = false; + node->vers_delete = true; + col_idx = table->vers_row_end; + } else { + ut_ad(uvect->n_fields < table->n_cols); + ufield = &uvect->fields[uvect->n_fields]; + col_idx = table->vers_row_start; + } + col = &table->cols[col_idx]; + UNIV_MEM_INVALID(ufield, sizeof *ufield); + { + ulint field_no = dict_col_get_clust_pos(col, clust_index); + ut_ad(field_no != ULINT_UNDEFINED); + ufield->field_no = field_no; + } + ufield->orig_len = 0; + ufield->exp = NULL; + + static const ulint fsize = sizeof(trx_id_t); + byte* buf = static_cast<byte*>(mem_heap_alloc(node->update->heap, fsize)); + mach_write_to_8(buf, trx->id); + dfield_t* dfield = &ufield->new_val; + dfield_set_data(dfield, buf, fsize); + dict_col_copy_type(col, &dfield->type); + + uvect->n_fields++; + ut_ad(node->in_mysql_interface); // otherwise needs to recalculate node->cmpl_info + } + if (thr->fk_cascade_depth == 1 && trx->dict_operation_lock_mode == 0) { got_s_lock = true; row_mysql_freeze_data_dictionary(trx); @@ -1978,7 +2050,6 @@ run_again: err = trx->error_state; if (err != DB_SUCCESS) { - que_thr_stop_for_mysql(thr); if (err == DB_RECORD_NOT_FOUND) { @@ -2056,6 +2127,9 @@ run_again: node->cascade_upd_nodes = cascade_upd_nodes; cascade_upd_nodes->pop_front(); thr->fk_cascade_depth++; + prebuilt->m_mysql_table = NULL; + vers_set_fields = DICT_TF2_FLAG_IS_SET(node->table, DICT_TF2_VERSIONED) + && (node->is_delete || node->versioned); goto run_again; } @@ -2135,6 +2209,14 @@ run_again: prebuilt->table->stat_modified_counter++; } + if (DICT_TF2_FLAG_IS_SET(node->table, DICT_TF2_VERSIONED) && + (node->versioned || node->vers_delete || + // TODO: imrove this check (check if we touch only + // unversioned fields in foreigh table + node->foreign)) { + trx->vtq_notify_on_commit = true; + } + trx->op_info = ""; que_thr_stop_for_mysql_no_error(thr, trx); @@ -2179,6 +2261,20 @@ error: DBUG_RETURN(err); } +/** Does an update or delete of a row for MySQL. +@param[in] mysql_rec row in the MySQL format +@param[in,out] prebuilt prebuilt struct in MySQL handle +@return error code or DB_SUCCESS */ +dberr_t +row_update_for_mysql( + row_prebuilt_t* prebuilt, + bool vers_set_fields) +{ + ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW); + return (row_update_for_mysql_using_upd_graph( + prebuilt, vers_set_fields)); +} + /** This can only be used when srv_locks_unsafe_for_binlog is TRUE or this session is using a READ COMMITTED or READ UNCOMMITTED isolation level. Before calling this function row_search_for_mysql() must have diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 26ee2849be3..fd40b93173b 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -272,6 +272,7 @@ row_upd_check_references_constraints( if (foreign->referenced_index == index && (node->is_delete + || node->vers_delete || row_upd_changes_first_fields_binary( entry, index, node->update, foreign->n_fields))) { @@ -412,6 +413,7 @@ wsrep_row_upd_check_foreign_constraints( if (foreign->foreign_index == index && (node->is_delete + || node->vers_delete || row_upd_changes_first_fields_binary( entry, index, node->update, foreign->n_fields))) { @@ -491,6 +493,8 @@ upd_node_create( node->common.type = QUE_NODE_UPDATE; node->state = UPD_NODE_UPDATE_CLUSTERED; node->heap = mem_heap_create(128); + node->cmpl_info = 0; + node->versioned = false; node->magic_n = UPD_NODE_MAGIC_N; return(node); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 25a5a964375..383410849af 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2587,6 +2587,10 @@ files_checked: err = dict_create_or_check_sys_tablespace(); if (err == DB_SUCCESS) { err = dict_create_or_check_sys_virtual(); + if (err == DB_SUCCESS) { + /* Create the SYS_VTQ system table */ + err = dict_create_or_check_vtq_table(); + } } } switch (err) { diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 738f713298b..1c1f85068a4 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -180,7 +180,9 @@ trx_purge_graph_build(sess_t* sess) ut_ad(trx->sess == sess); trx->id = 0; - trx->start_time = ut_time(); + ut_usectime((ulong *)&trx->start_time, + (ulong *)&trx->start_time_micro); + trx->start_time_micro += trx->start_time * 1000000; trx->state = TRX_STATE_ACTIVE; trx->op_info = "purge trx"; diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 0d2d6beac90..f929449d96d 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -128,6 +128,7 @@ trx_rollback_to_savepoint_low( } else { trx->lock.que_state = TRX_QUE_RUNNING; MONITOR_INC(MONITOR_TRX_ROLLBACK_SAVEPOINT); + trx->vtq_notify_on_commit = savept->vtq_notify_on_commit; } ut_a(trx->error_state == DB_SUCCESS); @@ -617,6 +618,7 @@ trx_savept_take( trx_savept_t savept; savept.least_undo_no = trx->undo_no; + savept.vtq_notify_on_commit = trx->vtq_notify_on_commit; return(savept); } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 75131847da5..c15d324a0ef 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -145,6 +145,8 @@ trx_init( trx->check_unique_secondary = true; + trx->vtq_notify_on_commit = false; + trx->lock.n_rec_locks = 0; trx->dict_operation = TRX_DICT_OP_NONE; @@ -862,6 +864,16 @@ trx_resurrect_insert( trx->no = TRX_ID_MAX; } + /* trx_start_low() is not called with resurrect, so need to initialize + start time here.*/ + if (trx->state == TRX_STATE_ACTIVE + || trx->state == TRX_STATE_PREPARED) { + + ut_usectime((ulong *)&trx->start_time, + (ulong *)&trx->start_time_micro); + trx->start_time_micro += trx->start_time * 1000000; + } + if (undo->dict_operation) { trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); trx->table_id = undo->table_id; @@ -945,6 +957,15 @@ trx_resurrect_update( trx->no = TRX_ID_MAX; } + /* trx_start_low() is not called with resurrect, so need to initialize + start time here.*/ + if (trx->state == TRX_STATE_ACTIVE + || trx->state == TRX_STATE_PREPARED) { + ut_usectime((ulong *)&trx->start_time, + (ulong *)&trx->start_time_micro); + trx->start_time_micro += trx->start_time * 1000000; + } + if (undo->dict_operation) { trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); trx->table_id = undo->table_id; @@ -1313,13 +1334,14 @@ trx_start_low( } } - if (trx->mysql_thd != NULL) { - trx->start_time = thd_start_time_in_secs(trx->mysql_thd); - trx->start_time_micro = thd_query_start_micro(trx->mysql_thd); + if (trx->mysql_thd != NULL && + (trx->start_time_micro = thd_query_start_micro(trx->mysql_thd))) { + trx->start_time = trx->start_time_micro / 1000000; } else { - trx->start_time = ut_time(); - trx->start_time_micro = 0; + ut_usectime((ulong *)&trx->start_time, + (ulong *)&trx->start_time_micro); + trx->start_time_micro += trx->start_time * 1000000; } ut_a(trx->error_state == DB_SUCCESS); diff --git a/storage/innobase/vers/vers0vtq.cc b/storage/innobase/vers/vers0vtq.cc new file mode 100644 index 00000000000..0e500234008 --- /dev/null +++ b/storage/innobase/vers/vers0vtq.cc @@ -0,0 +1,472 @@ +/* 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-1301, USA */ + +#include <sql_class.h> +#include <tztime.h> + +#include "btr0pcur.h" +#include "dict0load.h" +#include "ha_innodb.h" +#include "row0ins.ic" +#include "row0row.h" +#include "trx0trx.h" +#include "trx0types.h" +#include "trx0vtq.h" + + +/** Field or record selector. +@param[in] thd MySQL thread +@param[in] q VTQ record to get values from +@param[out] out field value or whole record returned +@param[in] field field to get in `out` or VTQ_ALL for whole record (vtq_record_t copied) */ +static +inline +void +vtq_result(THD* thd, vtq_record_t& q, void *out, vtq_field_t field) +{ + ut_ad(field == VTQ_ALL || out); + + switch (field) { + case VTQ_ALL: + if (out) { + *reinterpret_cast<vtq_record_t *>(out) = q; + } + break; + case VTQ_TRX_ID: + *reinterpret_cast<trx_id_t *>(out) = q.trx_id; + break; + case VTQ_COMMIT_ID: + *reinterpret_cast<trx_id_t *>(out) = q.commit_id; + break; + case VTQ_BEGIN_TS: { + MYSQL_TIME* out_ts = reinterpret_cast<MYSQL_TIME *>(out); + thd_get_timezone(thd)->gmt_sec_to_TIME(out_ts, q.begin_ts.tv_sec); + out_ts->second_part = q.begin_ts.tv_usec; + break; + } + case VTQ_COMMIT_TS: { + MYSQL_TIME* out_ts = reinterpret_cast<MYSQL_TIME *>(out); + thd_get_timezone(thd)->gmt_sec_to_TIME(out_ts, q.commit_ts.tv_sec); + out_ts->second_part = q.commit_ts.tv_usec; + break; + } + case VTQ_ISO_LEVEL: + *reinterpret_cast<uint *>(out) = q.iso_level; + break; + default: + ut_error; + } +} + +inline +const char * +vtq_query_t::cache_result(mem_heap_t* heap, const rec_t* rec) +{ + prev_query.tv_sec = 0; + return dict_process_sys_vtq(heap, rec, result); +} + + +/** Query VTQ by TRX_ID. +@param[in] thd MySQL thread +@param[out] out field value or whole record returned by query (selected by `field`) +@param[in] in_trx_id query parameter TRX_ID +@param[in] field field to get in `out` or VTQ_ALL for whole record (vtq_record_t) +@return TRUE if record is found, FALSE otherwise */ +UNIV_INTERN +bool +vtq_query_trx_id(THD* thd, void *out, ulonglong _in_trx_id, vtq_field_t field) +{ + trx_t* trx; + dict_index_t* index; + btr_pcur_t pcur; + dtuple_t* tuple; + dfield_t* dfield; + trx_id_t trx_id_net; + mtr_t mtr; + mem_heap_t* heap; + rec_t* rec; + bool found = false; + + DBUG_ENTER("vtq_query_trx_id"); + + if (_in_trx_id == 0) { + DBUG_RETURN(false); + } + + ut_ad(sizeof(_in_trx_id) == sizeof(trx_id_t)); + trx_id_t in_trx_id = static_cast<trx_id_t>(_in_trx_id); + + trx = thd_to_trx(thd); + ut_a(trx); + + vtq_record_t &cached = trx->vtq_query.result; + + if (cached.trx_id == in_trx_id) { + vtq_result(thd, cached, out, field); + DBUG_RETURN(true); + } + + index = dict_table_get_first_index(dict_sys->sys_vtq); + heap = mem_heap_create(0); + + ut_ad(index); + ut_ad(dict_index_is_clust(index)); + + mach_write_to_8( + reinterpret_cast<byte*>(&trx_id_net), + in_trx_id); + + tuple = dtuple_create(heap, 1); + dfield = dtuple_get_nth_field(tuple, DICT_FLD__SYS_VTQ__TRX_ID); + dfield_set_data(dfield, &trx_id_net, 8); + dict_index_copy_types(tuple, index, 1); + + mtr_start_trx(&mtr, trx); + btr_pcur_open_on_user_rec(index, tuple, PAGE_CUR_GE, + BTR_SEARCH_LEAF, &pcur, &mtr); + + if (!btr_pcur_is_on_user_rec(&pcur)) + goto not_found; + + rec = btr_pcur_get_rec(&pcur); + { + const char *err = trx->vtq_query.cache_result(heap, rec); + if (err) { + fprintf(stderr, "InnoDB: vtq_query_trx_id: get VTQ field failed: %s\n", err); + ut_ad(false && "get VTQ field failed"); + goto not_found; + } + } + + if (cached.trx_id != in_trx_id) + goto not_found; + + vtq_result(thd, cached, out, field); + found = true; + +not_found: + btr_pcur_close(&pcur); + mtr_commit(&mtr); + mem_heap_free(heap); + + DBUG_RETURN(found); +} + +static +inline +void rec_get_timeval(const rec_t* rec, ulint nfield, timeval& out) +{ + ulint len; + const byte* field; + field = rec_get_nth_field_old( + rec, nfield, &len); + + ut_ad(len == sizeof(ullong)); + + out.tv_sec = mach_read_from_4(field); + out.tv_usec = mach_read_from_4(field + 4); +} + +inline +const char * +vtq_query_t::cache_result( + mem_heap_t* heap, + const rec_t* rec, + const timeval& _ts_query, + bool _backwards) +{ + prev_query = _ts_query; + backwards = _backwards; + return dict_process_sys_vtq(heap, rec, result); +} + +static +inline +bool +operator== (const timeval &a, const timeval &b) +{ + return a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec; +} + +static +inline +bool +operator!= (const timeval &a, const timeval &b) +{ + return !(a == b); +} + +static +inline +bool +operator> (const timeval &a, const timeval &b) +{ + return a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec); +} + +static +inline +bool +operator< (const timeval &a, const timeval &b) +{ + return b > a; +} + +static +trx_id_t +read_trx_id(const rec_t *rec) { + ulong len = 0; + const rec_t *field = rec_get_nth_field_old(rec, 1, &len); + DBUG_ASSERT(len == 8); + return mach_read_from_8(field); +} + +/** Find a row with given commit_ts but MAX()/MIN() trx_id +@param[in] mtr mini-transaction handler +@param[in, out] pcur btree cursor which may be changed by this function +@param[in] backwards search direction +@param[in] commit_ts target timestamp for records +@param[in] rec record buffer for pcur +*/ +static +void +find_best_match( + mtr_t &mtr, + btr_pcur_t &pcur, + bool backwards, + timeval commit_ts, + const rec_t *rec) +{ + btr_pcur_t best; + btr_pcur_init(&best); + btr_pcur_copy_stored_position(&best, &pcur); + trx_id_t best_trx_id = read_trx_id(rec); + + while (true) { + if (backwards ? !btr_pcur_move_to_prev_user_rec(&pcur, &mtr) + : !btr_pcur_move_to_next_user_rec(&pcur, &mtr)) + break; + + timeval tv; + rec = btr_pcur_get_rec(&pcur); + rec_get_timeval(rec, 0, tv); + if (tv != commit_ts) + break; + + trx_id_t trx_id = read_trx_id(rec); + if (backwards ? trx_id < best_trx_id : trx_id > best_trx_id) { + best_trx_id = trx_id; + btr_pcur_copy_stored_position(&best, &pcur); + } + } + + btr_pcur_copy_stored_position(&pcur, &best); + btr_pcur_free(&best); +} + +/** Query VTQ by COMMIT_TS. +@param[in] thd MySQL thread +@param[out] out field value or whole record returned by query (selected by `field`) +@param[in] commit_ts query parameter COMMIT_TS +@param[in] field field to get in `out` or VTQ_ALL for whole record (vtq_record_t) +@param[in] backwards direction of VTQ search +@return TRUE if record is found, FALSE otherwise */ +UNIV_INTERN +bool +vtq_query_commit_ts( + THD* thd, + void *out, + const MYSQL_TIME &_commit_ts, + vtq_field_t field, + bool backwards) +{ + trx_t* trx; + btr_pcur_t pcur; + dtuple_t* tuple; + page_cur_mode_t mode; + mtr_t mtr; + mem_heap_t* heap; + uint err; + timeval commit_ts; + timeval rec_ts = { 0, 0 }; + const rec_t *rec, *clust_rec; + dict_index_t* index = dict_sys->vtq_commit_ts_ind; + dict_index_t* clust_index; + bool found = false; + + DBUG_ENTER("vtq_query_commit_ts"); + + mode = backwards ? PAGE_CUR_LE : PAGE_CUR_GE; + + trx = thd_to_trx(thd); + ut_a(trx); + + vtq_record_t &cached = trx->vtq_query.result; + timeval &prev_query = trx->vtq_query.prev_query; + bool prev_bwds = trx->vtq_query.backwards; + + commit_ts.tv_usec = _commit_ts.second_part; + commit_ts.tv_sec = thd_get_timezone(thd)->TIME_to_gmt_sec(&_commit_ts, &err); + if (err) { + if (err == ER_WARN_DATA_OUT_OF_RANGE) { + if (_commit_ts.year <= TIMESTAMP_MIN_YEAR) { + commit_ts.tv_usec = 0; + commit_ts.tv_sec = 1; + } else { + ut_ad(_commit_ts.year >= TIMESTAMP_MAX_YEAR); + commit_ts.tv_usec = TIME_MAX_SECOND_PART; + commit_ts.tv_sec = MY_TIME_T_MAX; + } + } else { + DBUG_RETURN(false); + } + } else if (cached.commit_ts == commit_ts || + (prev_query.tv_sec && prev_bwds == backwards && ( + (!backwards && (commit_ts < prev_query) && commit_ts > cached.commit_ts) || + (backwards && (commit_ts > prev_query) && commit_ts < cached.commit_ts)))) + { + vtq_result(thd, cached, out, field); + DBUG_RETURN(true); + } + + heap = mem_heap_create(0); + + tuple = dtuple_create(heap, 1); + dict_index_copy_types(tuple, index, 1); + dtuple_get_nth_field(tuple, 0)->len = UNIV_SQL_NULL; + set_tuple_col_8(tuple, 0, commit_ts, heap); + + mtr_start_trx(&mtr, trx); + btr_pcur_open_on_user_rec(index, tuple, mode, + BTR_SEARCH_LEAF, &pcur, &mtr); + + if (btr_pcur_is_on_user_rec(&pcur)) { + rec = btr_pcur_get_rec(&pcur); + rec_get_timeval(rec, 0, rec_ts); + + if (rec_ts == commit_ts) { + find_best_match(mtr, pcur, backwards, commit_ts, rec); + goto found; + } + } else { + rec_ts = commit_ts; + } + + if (mode == PAGE_CUR_GE) { + btr_pcur_move_to_prev_user_rec(&pcur, &mtr); + } else { + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + } + + if (!btr_pcur_is_on_user_rec(&pcur)) + goto not_found; + + rec = btr_pcur_get_rec(&pcur); +found: + clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index, &clust_index, &mtr); + if (!clust_rec) { + fprintf(stderr, "InnoDB: vtq_query_commit_ts: secondary index is out of sync\n"); + ut_ad(false && "secondary index is out of sync"); + goto not_found; + } + + { + const char *err = + trx->vtq_query.cache_result( + heap, + clust_rec, + rec_ts, + backwards); + if (err) { + fprintf(stderr, "InnoDB: vtq_query_commit_ts: get VTQ field failed: %s\n", err); + ut_ad(false && "get VTQ field failed"); + goto not_found; + } + } + vtq_result(thd, cached, out, field); + found = true; + +not_found: + btr_pcur_close(&pcur); + mtr_commit(&mtr); + mem_heap_free(heap); + + DBUG_RETURN(found); +} + +/** Check if transaction TX1 sees transaction TX0. +@param[in] thd MySQL thread +@param[out] result true if TX1 sees TX0 +@param[in] trx_id1 TX1 TRX_ID +@param[in] trx_id0 TX0 TRX_ID +@param[in] commit_id1 TX1 COMMIT_ID +@param[in] iso_level1 TX1 isolation level +@param[in] commit_id0 TX0 COMMIT_ID +@return FALSE if there is no trx_id1 in VTQ, otherwise TRUE */ +bool +vtq_trx_sees( + THD *thd, + bool &result, + ulonglong trx_id1, + ulonglong trx_id0, + ulonglong commit_id1, + uchar iso_level1, + ulonglong commit_id0) +{ + DBUG_ENTER("vtq_trx_sees"); + + if (trx_id1 == trx_id0) { + result = false; + DBUG_RETURN(true); + } + + if (trx_id1 == ULONGLONG_MAX || trx_id0 == 0) { + result = true; + DBUG_RETURN(true); + } + + static const char* msg_cant_find = "InnoDB: vtq_trx_sees: can't find COMMIT_ID%c by TRX_ID: %llu\n"; + if (!commit_id1) { + if (!vtq_query_trx_id(thd, NULL, trx_id1, VTQ_ALL)) { + fprintf(stderr, msg_cant_find, '1', trx_id1); + DBUG_RETURN(false); + } + trx_t* trx = thd_to_trx(thd); + ut_ad(trx); + commit_id1 = trx->vtq_query.result.commit_id; + iso_level1 = trx->vtq_query.result.iso_level; + } + + if (!commit_id0) { + if (!vtq_query_trx_id(thd, &commit_id0, trx_id0, VTQ_COMMIT_ID)) { + fprintf(stderr, msg_cant_find, '0', trx_id0); + DBUG_RETURN(false); + } + } + + // Trivial case: TX1 started after TX0 committed + if (trx_id1 > commit_id0 + // Concurrent transactions: TX1 committed after TX0 and TX1 is read (un)committed + || (commit_id1 > commit_id0 && iso_level1 < TRX_ISO_REPEATABLE_READ)) + { + result = true; + } else { + // All other cases: TX1 does not see TX0 + result = false; + } + + DBUG_RETURN(true); +} diff --git a/storage/tokudb/mysql-test/tokudb/disabled.def b/storage/tokudb/mysql-test/tokudb/disabled.def index ddefceb432e..0a62e8b136c 100644 --- a/storage/tokudb/mysql-test/tokudb/disabled.def +++ b/storage/tokudb/mysql-test/tokudb/disabled.def @@ -29,3 +29,11 @@ cluster_key_part: engine options on partitioned tables i_s_tokudb_lock_waits_released: unstable, race conditions i_s_tokudb_locks_released: unstable, race conditions row_format: n/a + +rows-32m-rand-insert: versioning branch +rows-32m-seq-insert: versioning branch +background_job_manager: versioning branch +i_s_tokudb_lock_waits_timeout: versioning branch +i_s_tokudb_locks: versioning branch +i_s_tokudb_trx: versioning branch +card_auto_analyze_lots: versioning branch
\ No newline at end of file diff --git a/storage/tokudb/mysql-test/tokudb/r/tokudb_support_xa.result b/storage/tokudb/mysql-test/tokudb/r/tokudb_support_xa.result index 120e8de7c7f..fd32fa031c7 100644 --- a/storage/tokudb/mysql-test/tokudb/r/tokudb_support_xa.result +++ b/storage/tokudb/mysql-test/tokudb/r/tokudb_support_xa.result @@ -43,7 +43,7 @@ SET @@session.tokudb_support_xa = "T"; ERROR 42000: Variable 'tokudb_support_xa' can't be set to the value of 'T' SET @@session.tokudb_support_xa = "Y"; ERROR 42000: Variable 'tokudb_support_xa' can't be set to the value of 'Y' -SET @@session.tokudb_support_xa = OF; +SET @@session.tokudb_support_xa = OFF; SELECT @@session.tokudb_support_xa; @@session.tokudb_support_xa 0 diff --git a/storage/tokudb/mysql-test/tokudb/t/tokudb_support_xa.test b/storage/tokudb/mysql-test/tokudb/t/tokudb_support_xa.test index f0ad03b91ee..fa1efde7cf7 100644 --- a/storage/tokudb/mysql-test/tokudb/t/tokudb_support_xa.test +++ b/storage/tokudb/mysql-test/tokudb/t/tokudb_support_xa.test @@ -39,7 +39,7 @@ SET @@session.tokudb_support_xa = 1.6; SET @@session.tokudb_support_xa = "T"; --Error ER_WRONG_VALUE_FOR_VAR SET @@session.tokudb_support_xa = "Y"; -SET @@session.tokudb_support_xa = OF; +SET @@session.tokudb_support_xa = OFF; SELECT @@session.tokudb_support_xa; # for global diff --git a/storage/tokudb/mysql-test/tokudb_bugs/disabled.def b/storage/tokudb/mysql-test/tokudb_bugs/disabled.def index d0d1a47e006..a9d35d5f751 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/disabled.def +++ b/storage/tokudb/mysql-test/tokudb_bugs/disabled.def @@ -1,2 +1,9 @@ 5585: times out, too many huge insert...selects db233: different execution path in mariadb, debug_sync point is not hit + +db397_insert_trigger: versioning branch +db397_delete_trigger: versioning branch +db397_update_trigger: versioning branch +db938: versioning branch +tokudb718: versioning branch +db945: versioning branch
\ No newline at end of file diff --git a/storage/tokudb/mysql-test/tokudb_parts/disabled.def b/storage/tokudb/mysql-test/tokudb_parts/disabled.def index 3252a463176..41fe1df15c0 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/disabled.def +++ b/storage/tokudb/mysql-test/tokudb_parts/disabled.def @@ -7,3 +7,15 @@ partition_max_sub_parts_key_list_tokudb: 5.6 test not merged yet partition_max_sub_parts_key_range_tokudb: 5.6 test not merged yet partition_max_sub_parts_list_tokudb: 5.6 test not merged yet partition_max_sub_parts_range_tokudb: 5.6 test not merged yet + +partition_alter1_1_2_tokudb: versioning branch +partition_alter1_1_tokudb: versioning branch +partition_alter1_2_tokudb: versioning branch +partition_alter2_1_1_tokudb: versioning branch +partition_alter2_1_2_tokudb: versioning branch +partition_alter2_2_1_tokudb: versioning branch +partition_alter2_2_2_tokudb: versioning branch +partition_alter4_tokudb: versioning branch +partition_basic_tokudb: versioning branch +partition_debug_tokudb: versioning branch +part_supported_sql_func_tokudb: versioning branch
\ No newline at end of file diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_syntax_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_syntax_tokudb.result index 1a4bf02cc7c..b16da084995 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_syntax_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_syntax_tokudb.result @@ -510,7 +510,7 @@ f_charbig VARCHAR(1000) ) PARTITION BY RANGE(f_int1) ( PARTITION part1 VALUES LESS THAN (1000) (SUBPARTITION subpart11)); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: It is only possible to mix RANGE/LIST/SYSTEM_TIME partitioning with HASH/KEY partitioning for subpartitioning #------------------------------------------------------------------------ # 2.2 Every partition must have the same number of subpartitions. # This is a limitation of MySQL 5.1, which could be removed in |