From aa8b8e3ab1ec2cdaca3c51f651f7f8d8a928bbdf Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 31 Oct 2016 15:01:19 +0100 Subject: [PATCH 001/148] Raise version number after cloning 5.5.54 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4f1ecb3a197..bc0b19220b6 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=54 +MYSQL_VERSION_PATCH=55 MYSQL_VERSION_EXTRA= From b8ec8196c3df6c1de6fdc547a2b208093babfb01 Mon Sep 17 00:00:00 2001 From: Shipra Jain Date: Sat, 5 Nov 2016 16:52:05 +0100 Subject: [PATCH 002/148] Bug#24918325: backport bug11756699 in this patch --- mysql-test/r/log_tables-big.result | 2 ++ mysql-test/t/disabled.def | 1 - mysql-test/t/log_tables-big.test | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/log_tables-big.result b/mysql-test/r/log_tables-big.result index 9b81127c825..42df9e8fe16 100644 --- a/mysql-test/r/log_tables-big.result +++ b/mysql-test/r/log_tables-big.result @@ -1,3 +1,4 @@ +set @@global.log_output = 'TABLE'; set session long_query_time=10; select get_lock('bug27638', 1); get_lock('bug27638', 1) @@ -27,3 +28,4 @@ OK select get_lock('bug27638', 101) select release_lock('bug27638'); release_lock('bug27638') 1 +set @@global.log_output=default; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 81600642c15..ef973912b63 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -13,5 +13,4 @@ lowercase_table3 : Bug#11762269 2010-06-30 alik main.lowercase_table3 on read_many_rows_innodb : Bug#11748886 2010-11-15 mattiasj report already exists sum_distinct-big : Bug#11764126 2010-11-15 mattiasj was not tested archive-big : Bug#11817185 2011-03-10 Anitha Disabled since this leads to timeout on Solaris Sparc -log_tables-big : Bug#11756699 2010-11-15 mattiasj report already exists mysql_embedded : Bug#12561297 2011-05-14 Anitha Dependent on PB2 changes - eventum#41836 diff --git a/mysql-test/t/log_tables-big.test b/mysql-test/t/log_tables-big.test index 8c956fa6f55..4a10ea12edf 100644 --- a/mysql-test/t/log_tables-big.test +++ b/mysql-test/t/log_tables-big.test @@ -7,6 +7,8 @@ # check that CSV engine was compiled in --source include/have_csv.inc +set @@global.log_output = 'TABLE'; + connect (con1,localhost,root,,); connect (con2,localhost,root,,); @@ -33,3 +35,5 @@ connection default; disconnect con1; disconnect con2; + +set @@global.log_output=default; From 2f2103d540f86e326b22cef39183e8e0985da138 Mon Sep 17 00:00:00 2001 From: Shipra Jain Date: Wed, 9 Nov 2016 19:27:35 +0100 Subject: [PATCH 003/148] Bug#22874167 : fix for MAIN.LOG_TABLES-BIG UNSTABLE ON LOADED HOSTS --- mysql-test/r/log_tables-big.result | 12 ++++++------ mysql-test/t/log_tables-big.test | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/log_tables-big.result b/mysql-test/r/log_tables-big.result index 42df9e8fe16..1e189a7726f 100644 --- a/mysql-test/r/log_tables-big.result +++ b/mysql-test/r/log_tables-big.result @@ -4,25 +4,25 @@ select get_lock('bug27638', 1); get_lock('bug27638', 1) 1 set session long_query_time=1; -truncate table mysql.slow_log; select get_lock('bug27638', 2); get_lock('bug27638', 2) 0 -select if (query_time between '00:00:01' and '00:00:10', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log; +select if (query_time >= '00:00:01', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log +where sql_text = 'select get_lock(\'bug27638\', 2)'; qt sql_text OK select get_lock('bug27638', 2) -truncate table mysql.slow_log; select get_lock('bug27638', 60); get_lock('bug27638', 60) 0 -select if (query_time between '00:00:59' and '00:01:10', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log; +select if (query_time >= '00:00:59', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log +where sql_text = 'select get_lock(\'bug27638\', 60)'; qt sql_text OK select get_lock('bug27638', 60) -truncate table mysql.slow_log; select get_lock('bug27638', 101); get_lock('bug27638', 101) 0 -select if (query_time between '00:01:40' and '00:01:50', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log; +select if (query_time >= '00:01:40', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log +where sql_text = 'select get_lock(\'bug27638\', 101)'; qt sql_text OK select get_lock('bug27638', 101) select release_lock('bug27638'); diff --git a/mysql-test/t/log_tables-big.test b/mysql-test/t/log_tables-big.test index 4a10ea12edf..8936a163d73 100644 --- a/mysql-test/t/log_tables-big.test +++ b/mysql-test/t/log_tables-big.test @@ -20,15 +20,15 @@ set session long_query_time=10; select get_lock('bug27638', 1); connection con2; set session long_query_time=1; -truncate table mysql.slow_log; select get_lock('bug27638', 2); -select if (query_time between '00:00:01' and '00:00:10', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log; -truncate table mysql.slow_log; +select if (query_time >= '00:00:01', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log + where sql_text = 'select get_lock(\'bug27638\', 2)'; select get_lock('bug27638', 60); -select if (query_time between '00:00:59' and '00:01:10', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log; -truncate table mysql.slow_log; +select if (query_time >= '00:00:59', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log + where sql_text = 'select get_lock(\'bug27638\', 60)'; select get_lock('bug27638', 101); -select if (query_time between '00:01:40' and '00:01:50', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log; +select if (query_time >= '00:01:40', 'OK', 'WRONG') as qt, sql_text from mysql.slow_log + where sql_text = 'select get_lock(\'bug27638\', 101)'; connection con1; select release_lock('bug27638'); connection default; From a63185e8638365d401732803ba93b6b149d33c65 Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Thu, 10 Nov 2016 15:11:57 +0530 Subject: [PATCH 004/148] BUG#24437124: POSSIBLE BUFFER OVERFLOW ON CREATE TABLE ANALYSIS: ========= 'CREATE TABLE' query with a large value for 'CONNECTION' string reports an incorrect error. The length of connection string is stored in .frm in two bytes (max value= 65535). When the string length exceeds the max value, the length is truncated to fit the two bytes limit. Further processing leads to reading only a part of the string as the length stored is incorrect. The remaining part of the string is treated as engine type and hence results in an error. FIX: ==== We are now restricting the connection string length to 1024. An appropriate error is reported if the length crosses this limit. NOTE: ===== The 'PASSWORD' table option is documented as unused and processed within a dead code. Hence it will not cause similar issue with large strings. --- include/mysql_com.h | 3 ++- sql/sql_table.cc | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index f2345be6fd6..5cd40915743 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #define USERNAME_CHAR_LENGTH 16 #define NAME_LEN (NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN) #define USERNAME_LENGTH (USERNAME_CHAR_LENGTH*SYSTEM_CHARSET_MBMAXLEN) +#define CONNECT_STRING_MAXLEN 1024 #define MYSQL_AUTODETECT_CHARSET_NAME "auto" diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 49f05c6116e..58bcf5ca1d4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2851,6 +2851,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, uint total_uneven_bit_length= 0; DBUG_ENTER("mysql_prepare_create_table"); + LEX_STRING* connect_string = &create_info->connect_string; + if (connect_string->length != 0 && + connect_string->length > CONNECT_STRING_MAXLEN && + (system_charset_info->cset->charpos(system_charset_info, + connect_string->str, + (connect_string->str + + connect_string->length), + CONNECT_STRING_MAXLEN) + < connect_string->length)) + { + my_error(ER_WRONG_STRING_LENGTH, MYF(0), + connect_string->str, "CONNECTION", CONNECT_STRING_MAXLEN); + DBUG_RETURN(TRUE); + } + select_field_pos= alter_info->create_list.elements - select_field_count; null_fields=blob_columns=0; create_info->varchar= 0; From cdd57aa719c14f4c2e23ad37674db5b8ca18fe9e Mon Sep 17 00:00:00 2001 From: Terje Rosten Date: Wed, 16 Nov 2016 13:41:27 +0100 Subject: [PATCH 005/148] Bug#25088048 ADDITIONAL ISSUES IN MYSQLD_SAFE Don't read --ledir option from config file. Ignore current working for finding location of mysqld Remove use of chown/chmod in scripts. Be helpful only when basedir is /var/log or /var/lib. Removed unused systemd files for SLES. Set explicit basedir in scripts. --- packaging/rpm-oel/mysql-systemd-start | 4 +- packaging/rpm-oel/mysql.init | 24 +++++----- packaging/rpm-oel/mysqld.service | 2 +- packaging/rpm-sles/CMakeLists.txt | 3 +- packaging/rpm-sles/mysql-systemd-start | 66 -------------------------- packaging/rpm-sles/mysql.conf | 1 - packaging/rpm-sles/mysql.init | 13 ++--- packaging/rpm-sles/mysqld.service | 48 ------------------- scripts/mysqld_safe.sh | 18 ++++++- 9 files changed, 41 insertions(+), 138 deletions(-) delete mode 100644 packaging/rpm-sles/mysql-systemd-start delete mode 100644 packaging/rpm-sles/mysql.conf delete mode 100644 packaging/rpm-sles/mysqld.service diff --git a/packaging/rpm-oel/mysql-systemd-start b/packaging/rpm-oel/mysql-systemd-start index 231a76087ac..af6e906efe1 100644 --- a/packaging/rpm-oel/mysql-systemd-start +++ b/packaging/rpm-oel/mysql-systemd-start @@ -22,7 +22,9 @@ install_db () { datadir=$(get_option mysqld datadir "/var/lib/mysql") # Restore log, dir, perms and SELinux contexts - [ -d "$datadir" ] || install -d -m 0755 -omysql -gmysql "$datadir" || exit 1 + if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + install -d -m 0755 -omysql -gmysql "$datadir" || exit 1 + fi log=/var/log/mysqld.log [ -e $log ] || touch $log chmod 0640 $log diff --git a/packaging/rpm-oel/mysql.init b/packaging/rpm-oel/mysql.init index 75ae672801b..50d1bba017d 100644 --- a/packaging/rpm-oel/mysql.init +++ b/packaging/rpm-oel/mysql.init @@ -70,18 +70,19 @@ start(){ ret=0 else # prepare for start - touch "$errlogfile" - chown mysql:mysql "$errlogfile" - chmod 0640 "$errlogfile" + if [ ! -e "$errlogfile" -a ! -h "$errlogfile" -a "x$(dirname "$errlogfile")" = "x/var/log" ]; then + install /dev/null -m0640 -omysql -gmysql "$errlogfile" + fi [ -x /sbin/restorecon ] && /sbin/restorecon "$errlogfile" if [ ! -d "$datadir/mysql" ] ; then # First, make sure $datadir is there with correct permissions - if [ ! -e "$datadir" -a ! -h "$datadir" ] - then - mkdir -p "$datadir" || exit 1 + if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + install -d -m0755 -omysql -gmysql "$datadir" || exit 1 + fi + if [ ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + chown mysql:mysql "$datadir" + chmod 0755 "$datadir" fi - chown mysql:mysql "$datadir" - chmod 0755 "$datadir" if [ -x /sbin/restorecon ]; then /sbin/restorecon "$datadir" for dir in /var/lib/mysql-files ; do @@ -94,13 +95,14 @@ start(){ # Now create the database action $"Initializing MySQL database: " /usr/bin/mysql_install_db --rpm --datadir="$datadir" --user=mysql ret=$? - chown -R mysql:mysql "$datadir" if [ $ret -ne 0 ] ; then return $ret fi fi - chown mysql:mysql "$datadir" - chmod 0755 "$datadir" + if [ ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + chown mysql:mysql "$datadir" + chmod 0755 "$datadir" + fi # Pass all the options determined above, to ensure consistent behavior. # In many cases mysqld_safe would arrive at the same conclusions anyway # but we need to be sure. (An exception is that we don't force the diff --git a/packaging/rpm-oel/mysqld.service b/packaging/rpm-oel/mysqld.service index 78ef3bffe60..871f191c017 100644 --- a/packaging/rpm-oel/mysqld.service +++ b/packaging/rpm-oel/mysqld.service @@ -34,7 +34,7 @@ PermissionsStartOnly=true ExecStartPre=/usr/bin/mysql-systemd-start pre # Start main service -ExecStart=/usr/bin/mysqld_safe +ExecStart=/usr/bin/mysqld_safe --basedir=/usr # Don't signal startup success before a ping works ExecStartPost=/usr/bin/mysql-systemd-start post diff --git a/packaging/rpm-sles/CMakeLists.txt b/packaging/rpm-sles/CMakeLists.txt index b5ffaa15565..98aa4f4d222 100644 --- a/packaging/rpm-sles/CMakeLists.txt +++ b/packaging/rpm-sles/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,6 @@ IF(UNIX) # Left in current directory, to be taken during build CONFIGURE_FILE(mysql.spec.in ${CMAKE_CURRENT_BINARY_DIR}/${SPECFILENAME} @ONLY) FOREACH(fedfile my.cnf my_config.h mysql.init - mysqld.service mysql-systemd-start mysql.conf filter-requires.sh filter-provides.sh) CONFIGURE_FILE(${fedfile} ${CMAKE_CURRENT_BINARY_DIR}/${fedfile} COPYONLY) ENDFOREACH() diff --git a/packaging/rpm-sles/mysql-systemd-start b/packaging/rpm-sles/mysql-systemd-start deleted file mode 100644 index 28472249eda..00000000000 --- a/packaging/rpm-sles/mysql-systemd-start +++ /dev/null @@ -1,66 +0,0 @@ -#! /bin/bash -# -# Scripts to run by MySQL systemd service -# -# Needed argument: pre | post -# -# pre mode : try to run mysql_install_db and fix perms and SELinux contexts -# post mode : ping server until answer is received -# - -install_db () { - # Note: something different than datadir=/var/lib/mysql requires SELinux policy changes (in enforcing mode) - datadir=$(/usr/bin/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p' | tail -n 1) - - # Restore log, dir, perms and SELinux contexts - [ -d "$datadir" ] || install -d -m 0755 -omysql -gmysql "$datadir" || exit 1 - log=/var/log/mysqld.log - [ -e $log ] || touch $log - chmod 0640 $log - chown mysql:mysql $log || exit 1 - if [ -x /usr/sbin/restorecon ]; then - /usr/sbin/restorecon "$datadir" - /usr/sbin/restorecon $log - fi - - # If special mysql dir is in place, skip db install - [ -d "$datadir/mysql" ] && exit 0 - - # Create initial db - /usr/bin/mysql_install_db --rpm --datadir="$datadir" --user=mysql - - # Create a file to trigger execution of mysql_secure_installation - # after server has started - touch "$datadir"/.phase_two_required - - exit 0 -} - -pinger () { - # Wait for ping to answer to signal startup completed, - # might take a while in case of e.g. crash recovery - # MySQL systemd service will timeout script if no answer - ret=1 - while /bin/true ; do - sleep 1 - mysqladmin ping >/dev/null 2>&1 && ret=0 && break - done - - # If server has been started successfully and file created in - # install_db step is present we run mysql_secure_installation - if [ $ret -eq 0 -a -e "$datadir"/.phase_two_required -a -x /usr/bin/mysql_secure_installation ] ; then - /usr/bin/mysql_secure_installation --use-default --defaults-file=/etc/my.cnf - rm -f "$datadir"/.phase_two_required - fi - - exit 0 -} - -# main -case $1 in - "pre") install_db ;; - "post") pinger ;; -esac - -exit 0 - diff --git a/packaging/rpm-sles/mysql.conf b/packaging/rpm-sles/mysql.conf deleted file mode 100644 index 74cd5f836e7..00000000000 --- a/packaging/rpm-sles/mysql.conf +++ /dev/null @@ -1 +0,0 @@ -d /var/run/mysqld 0755 mysql mysql - diff --git a/packaging/rpm-sles/mysql.init b/packaging/rpm-sles/mysql.init index dda0bebba56..25762d9bee2 100644 --- a/packaging/rpm-sles/mysql.init +++ b/packaging/rpm-sles/mysql.init @@ -49,7 +49,6 @@ get_option () { datadir=$(get_option mysqld datadir "/var/lib/mysql") socket=$(get_option mysqld socket "$datadir/mysql.sock") pidfile=$(get_option mysqld_safe pid-file "/var/run/mysql/mysqld.pid") -logfile=$(get_option mysqld_safe log-error "/var/log/mysql/mysqld.log") install_db () { # Note: something different than datadir=/var/lib/mysql requires @@ -58,14 +57,16 @@ install_db () { logfile=$(get_option mysqld_safe log-error "/var/log/mysql/mysqld.log") # Restore log, dir, perms and SELinux contexts - [ -d "$datadir" ] || install -d -m 0755 -omysql -gmysql "$datadir" || return 1 + if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + install -d -m 0755 -omysql -gmysql "$datadir" || return 1 + fi - [ -e $logfile ] || touch $logfile || return 1 - chmod 0640 $logfile - chown mysql:mysql $logfile || return 1 + if [ ! -e "$logfile" -a ! -h "$logfile" -a "x$(dirname "$logfile")" = "x/var/log/mysql" ]; then + install /dev/null -omysql -gmysql "$logfile" || return 1 + fi if [ -x /usr/sbin/restorecon ]; then /usr/sbin/restorecon "$datadir" - /usr/sbin/restorecon $logfile + /usr/sbin/restorecon "$logfile" fi # If special mysql dir is in place, skip db install diff --git a/packaging/rpm-sles/mysqld.service b/packaging/rpm-sles/mysqld.service deleted file mode 100644 index 78ef3bffe60..00000000000 --- a/packaging/rpm-sles/mysqld.service +++ /dev/null @@ -1,48 +0,0 @@ -# -# Simple MySQL systemd service file -# -# systemd supports lots of fancy features, look here (and linked docs) for a full list: -# http://www.freedesktop.org/software/systemd/man/systemd.exec.html -# -# Note: this file ( /usr/lib/systemd/system/mysql.service ) -# will be overwritten on package upgrade, please copy the file to -# -# /etc/systemd/system/mysql.service -# -# to make needed changes. -# -# systemd-delta can be used to check differences between the two mysql.service files. -# - -[Unit] -Description=MySQL Community Server -After=network.target -After=syslog.target - -[Install] -WantedBy=multi-user.target -Alias=mysql.service - -[Service] -User=mysql -Group=mysql - -# Execute pre and post scripts as root -PermissionsStartOnly=true - -# Needed to create system tables etc. -ExecStartPre=/usr/bin/mysql-systemd-start pre - -# Start main service -ExecStart=/usr/bin/mysqld_safe - -# Don't signal startup success before a ping works -ExecStartPost=/usr/bin/mysql-systemd-start post - -# Give up if ping don't get an answer -TimeoutSec=600 - -Restart=always -PrivateTmp=false - - diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 4b103817ab6..a5c87a44e65 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -218,7 +218,13 @@ parse_arguments() { # mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])! --core-file-size=*) core_file_size="$val" ;; - --ledir=*) ledir="$val" ;; + --ledir=*) + if [ -z "$pick_args" ]; then + log_error "--ledir option can only be used as command line option, found in config file" + exit 1 + fi + ledir="$val" + ;; --malloc-lib=*) set_malloc_lib "$val" ;; --mysqld=*) if [ -z "$pick_args" ]; then @@ -394,7 +400,15 @@ else relpkgdata='@pkgdatadir@' fi -MY_PWD=`pwd` +case "$0" in + /*) + MY_PWD='@prefix@' + ;; + *) + MY_PWD=`dirname $0` + MY_PWD=`dirname $MY_PWD` + ;; +esac # Check for the directories we would expect from a binary release install if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION" then From e541c414816e904124ba7ab3075c3851da0addda Mon Sep 17 00:00:00 2001 From: Dyre Tjeldvoll Date: Thu, 24 Nov 2016 09:57:54 +0100 Subject: [PATCH 006/148] Bug#25092566: CREATE TABLE WITH DATA DIRECTORY CLAUSE DOES NOT REQUIRE SPECIAL PRIVILEGES Require FILE privilege when creating tables using external data directory or index directory. --- mysql-test/r/partition_symlink.result | 2 ++ mysql-test/t/partition_symlink.test | 2 ++ sql/partition_info.cc | 26 +++++++++++++++++++++++++- sql/partition_info.h | 13 ++++++++++++- sql/sql_parse.cc | 19 ++++++++++++++++++- 5 files changed, 59 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/partition_symlink.result b/mysql-test/r/partition_symlink.result index f26a1642a52..91cc78f1361 100644 --- a/mysql-test/r/partition_symlink.result +++ b/mysql-test/r/partition_symlink.result @@ -4,6 +4,8 @@ DROP DATABASE IF EXISTS mysqltest2; # test.t1 have partitions in mysqltest2-directory! # user root: CREATE USER mysqltest_1@localhost; +# Need FILE permission to use external datadir or indexdir. +GRANT FILE ON *.* TO mysqltest_1@localhost; CREATE DATABASE mysqltest2; USE mysqltest2; CREATE TABLE t1 (a INT) ENGINE = MyISAM; diff --git a/mysql-test/t/partition_symlink.test b/mysql-test/t/partition_symlink.test index 5fdde8e0abc..9e57d616213 100644 --- a/mysql-test/t/partition_symlink.test +++ b/mysql-test/t/partition_symlink.test @@ -32,6 +32,8 @@ DROP DATABASE IF EXISTS mysqltest2; -- echo # test.t1 have partitions in mysqltest2-directory! -- echo # user root: CREATE USER mysqltest_1@localhost; +-- echo # Need FILE permission to use external datadir or indexdir. + GRANT FILE ON *.* TO mysqltest_1@localhost; CREATE DATABASE mysqltest2; USE mysqltest2; CREATE TABLE t1 (a INT) ENGINE = MyISAM; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index a0d09557b81..cd17e3366cf 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2550,6 +2550,30 @@ void partition_info::print_debug(const char *str, uint *value) DBUG_PRINT("info", ("parser: %s", str)); DBUG_VOID_RETURN; } + +bool has_external_data_or_index_dir(partition_info &pi) +{ + List_iterator part_it(pi.partitions); + for (partition_element *part= part_it++; part; part= part_it++) + { + if (part->data_file_name != NULL || part->index_file_name != NULL) + { + return true; + } + List_iterator subpart_it(part->subpartitions); + for (const partition_element *subpart= subpart_it++; + subpart; + subpart= subpart_it++) + { + if (subpart->data_file_name != NULL || subpart->index_file_name != NULL) + { + return true; + } + } + } + return false; +} + #else /* WITH_PARTITION_STORAGE_ENGINE */ /* For builds without partitioning we need to define these functions diff --git a/sql/partition_info.h b/sql/partition_info.h index 7bfbf8a1b1a..7ff6abeebd2 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -1,7 +1,7 @@ #ifndef PARTITION_INFO_INCLUDED #define PARTITION_INFO_INCLUDED -/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -349,4 +349,15 @@ void init_all_partitions_iterator(partition_info *part_info, part_iter->get_next= get_next_partition_id_range; } +/** + Predicate which returns true if any partition or subpartition uses + an external data directory or external index directory. + + @param pi partitioning information + @retval true if any partition or subpartition has an external + data directory or external index directory. + @retval false otherwise + */ +bool has_external_data_or_index_dir(partition_info &pi); + #endif /* PARTITION_INFO_INCLUDED */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ac3901997f3..18cb758c9b5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -35,6 +35,9 @@ #include "sql_insert.h" // mysql_insert #include "sql_update.h" // mysql_update, mysql_multi_update #include "sql_partition.h" // struct partition_info +#ifdef WITH_PARTITION_STORAGE_ENGINE +#include "partition_info.h" // has_external_data_or_index_dir +#endif /* WITH_PARTITION_STORAGE_ENGINE */ #include "sql_db.h" // mysql_change_db, mysql_create_db, // mysql_rm_db, mysql_upgrade_db, // mysql_alter_db, @@ -2413,7 +2416,6 @@ case SQLCOM_PREPARE: 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. */ @@ -2421,6 +2423,15 @@ case SQLCOM_PREPARE: goto end_with_restore_list; } + if (((lex->create_info.used_fields & HA_CREATE_USED_DATADIR) != 0 || + (lex->create_info.used_fields & HA_CREATE_USED_INDEXDIR) != 0) && + check_access(thd, FILE_ACL, NULL, NULL, NULL, FALSE, FALSE)) + { + res= 1; + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "FILE"); + goto end_with_restore_list; + } + if ((res= create_table_precheck(thd, select_tables, create_table))) goto end_with_restore_list; @@ -2458,6 +2469,12 @@ case SQLCOM_PREPARE: #ifdef WITH_PARTITION_STORAGE_ENGINE { partition_info *part_info= thd->lex->part_info; + if (part_info != NULL && has_external_data_or_index_dir(*part_info) && + check_access(thd, FILE_ACL, NULL, NULL, NULL, FALSE, FALSE)) + { + res= -1; + goto end_with_restore_list; + } if (part_info && !(part_info= thd->lex->part_info->get_clone(true))) { res= -1; From 07fb5cffb035c622927c59188f0f062595eb2847 Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Sat, 26 Nov 2016 20:41:48 +0530 Subject: [PATCH 008/148] Followup fix for Bug#25088048 - ADDITIONAL ISSUES IN MYSQLD_SAFE - Removed mysql.conf, mysqld.service and mysql-systemd-start from sles spec file --- packaging/rpm-sles/mysql.spec.in | 43 -------------------------------- 1 file changed, 43 deletions(-) diff --git a/packaging/rpm-sles/mysql.spec.in b/packaging/rpm-sles/mysql.spec.in index 6652cdcccb6..1b5f1806321 100644 --- a/packaging/rpm-sles/mysql.spec.in +++ b/packaging/rpm-sles/mysql.spec.in @@ -24,7 +24,6 @@ # Regression tests may take a long time, override the default to skip them %{!?runselftest:%global runselftest 0} -%{!?with_systemd: %global systemd 0} %{!?with_debuginfo: %global nodebuginfo 1} %{!?product_suffix: %global product_suffix community} %{!?feature_set: %global feature_set community} @@ -69,9 +68,6 @@ Source0: https://cdn.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/%{src URL: http://www.mysql.com/ Packager: MySQL Release Engineering Vendor: %{mysql_vendor} -Source1: mysql-systemd-start -Source2: mysqld.service -Source3: mysql.conf Source4: my_config.h Source90: filter-provides.sh Source91: filter-requires.sh @@ -81,9 +77,6 @@ BuildRequires: libaio-devel BuildRequires: ncurses-devel BuildRequires: openssl-devel BuildRequires: zlib-devel -%if 0%{?systemd} -BuildRequires: systemd -%endif BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) %if 0%{?rhel} > 6 @@ -141,15 +134,9 @@ Obsoletes: mariadb-server Obsoletes: mariadb-galera-server Provides: mysql = %{version}-%{release} Provides: mysql-tools = %{version}-%{release} -%if 0%{?systemd} -Requires(post): systemd -Requires(preun): systemd -Requires(postun): systemd -%else PreReq: insserv PreReq: sed PreReq: pwdutils -%endif Conflicts: otherproviders(mysql) Conflicts: otherproviders(mysql-debug) Conflicts: otherproviders(mysql-tools) @@ -435,13 +422,7 @@ make DESTDIR=%{buildroot} install install -D -m 0644 $MBD/release/support-files/mysql-log-rotate %{buildroot}%{_sysconfdir}/logrotate.d/mysql install -D -m 0644 $MBD/release/packaging/rpm-sles/my.cnf %{buildroot}%{_sysconfdir}/my.cnf install -d %{buildroot}%{_sysconfdir}/my.cnf.d -%if 0%{?systemd} -install -D -m 0755 %{SOURCE1} %{buildroot}%{_bindir}/mysql-systemd-start -install -D -m 0644 %{SOURCE2} %{buildroot}%{_unitdir}/mysqld.service -%else install -D -m 0755 $MBD/release/packaging/rpm-sles/mysql.init %{buildroot}%{_sysconfdir}/init.d/mysql -%endif -install -D -m 0644 %{SOURCE3} %{buildroot}%{_prefix}/lib/tmpfiles.d/mysql.conf # Make library links install -d -m 0755 %{buildroot}%{_sysconfdir}/ld.so.conf.d @@ -461,9 +442,6 @@ rm -rf %{buildroot}%{_datadir}/mysql/mysql.server rm -rf %{buildroot}%{_datadir}/mysql/mysqld_multi.server rm -f %{buildroot}%{_datadir}/mysql/{ndb-config-2-node,config*}.ini rm -f %{buildroot}%{_datadir}/mysql/my-*.cnf -%if 0%{?systemd} -rm -rf %{buildroot}%{_sysconfdir}/init.d/mysql -%endif rm -rf %{buildroot}%{_bindir}/mysql_embedded rm -rf %{buildroot}%{_bindir}/mysql_setpermission rm -rf %{buildroot}%{_mandir}/man1/mysql_setpermission.1* @@ -496,31 +474,18 @@ datadir=$(/usr/bin/my_print_defaults server mysqld | grep '^--datadir=' | sed -n /bin/chmod 0755 "$datadir" /bin/touch /var/log/mysql/mysqld.log /bin/chown mysql:mysql /var/log/mysql/mysqld.log >/dev/null 2>&1 || : -%if 0%{?systemd} -%systemd_post mysqld.service -/sbin/service mysqld enable >/dev/null 2>&1 || : -%else /sbin/insserv /etc/init.d/mysql -%endif %preun server -%if 0%{?systemd} -%systemd_preun mysqld.service -%else if [ "$1" -eq 0 ]; then /usr/sbin/rcmysql stop >/dev/null 2>&1 || : /sbin/insserv /etc/init.d fi -%endif %postun server -%if 0%{?systemd} -%systemd_postun_with_restart mysqld.service -%else if [ $1 -ge 1 ]; then /usr/sbin/rcmysql condrestart >/dev/null 2>&1 || : fi -%endif %post libs -p /sbin/ldconfig @@ -596,9 +561,6 @@ fi %attr(755, root, root) %{_bindir}/replace %attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/resolveip -%if 0%{?systemd} -%attr(755, root, root) %{_bindir}/mysql-systemd-start -%endif %attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld-debug %attr(755, root, root) %{_sbindir}/rcmysql @@ -629,12 +591,7 @@ fi %attr(644, root, root) %{_datadir}/mysql/mysql_test_data_timezone.sql %attr(644, root, root) %{_datadir}/mysql/mysql-log-rotate %attr(644, root, root) %{_datadir}/mysql/magic -%attr(644, root, root) %{_prefix}/lib/tmpfiles.d/mysql.conf -%if 0%{?systemd} -%attr(644, root, root) %{_unitdir}/mysqld.service -%else %attr(755, root, root) %{_sysconfdir}/init.d/mysql -%endif %attr(644, root, root) %config(noreplace,missingok) %{_sysconfdir}/logrotate.d/mysql %dir %attr(755, mysql, mysql) /var/lib/mysql %dir %attr(755, mysql, mysql) /var/run/mysql From 3a37745ca048e7b1faf726a15929ae944d7e25ed Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Mon, 28 Nov 2016 11:55:36 +0530 Subject: [PATCH 009/148] --- sql/sp.cc | 4 +- sql/sql_acl.cc | 501 ++++++++++++++++++++++++++++++++++++++++++++++++- sql/sql_acl.h | 99 +++++++++- sql/table.cc | 40 ++-- 4 files changed, 618 insertions(+), 26 deletions(-) diff --git a/sql/sp.cc b/sql/sp.cc index a514ca10a68..56a439481f5 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -372,7 +372,7 @@ void Proc_table_intact::report_error(uint code, const char *fmt, ...) my_vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - if (code) + if (code == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED) my_message(code, buf, MYF(0)); else my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "proc"); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 99394878a55..b48b8562679 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -168,9 +168,411 @@ TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { } }; +static const +TABLE_FIELD_TYPE mysql_user_table_fields[MYSQL_USER_FIELD_COUNT] = { + { + { C_STRING_WITH_LEN("Host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("User") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Password") }, + { C_STRING_WITH_LEN("char(41)") }, + { C_STRING_WITH_LEN("latin1") } + }, + { + { C_STRING_WITH_LEN("Select_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Insert_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Update_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Delete_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Create_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Drop_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Reload_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Shutdown_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Process_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("File_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Grant_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("References_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Index_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Alter_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Show_db_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Super_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Create_tmp_table_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Lock_tables_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Execute_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Repl_slave_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Repl_client_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Create_view_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Show_view_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Create_routine_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Alter_routine_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Create_user_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Event_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Trigger_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Create_tablespace_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("ssl_type") }, + { C_STRING_WITH_LEN("enum('','ANY','X509','SPECIFIED')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("ssl_cipher") }, + { C_STRING_WITH_LEN("blob") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("x509_issuer") }, + { C_STRING_WITH_LEN("blob") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("x509_subject") }, + { C_STRING_WITH_LEN("blob") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_questions") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_updates") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_connections") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_user_connections") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("plugin") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("authentication_string") }, + { C_STRING_WITH_LEN("text") }, + {NULL, 0} + } +}; + +static const +TABLE_FIELD_TYPE mysql_proxies_priv_table_fields[MYSQL_PROXIES_PRIV_FIELD_COUNT] = { + { + { C_STRING_WITH_LEN("Host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("User") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Proxied_host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Proxied_user") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("With_grant") }, + { C_STRING_WITH_LEN("tinyint(1)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Grantor") }, + { C_STRING_WITH_LEN("char(77)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + } +}; + +static const +TABLE_FIELD_TYPE mysql_procs_priv_table_fields[MYSQL_PROCS_PRIV_FIELD_COUNT] = { + { + { C_STRING_WITH_LEN("Host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Db") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("User") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Routine_name") }, + { C_STRING_WITH_LEN("char(64)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Routine_type") }, + { C_STRING_WITH_LEN("enum('FUNCTION','PROCEDURE')") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Grantor") }, + { C_STRING_WITH_LEN("char(77)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Proc_priv") }, + { C_STRING_WITH_LEN("set('Execute','Alter Routine','Grant')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + } +}; + +static const +TABLE_FIELD_TYPE mysql_columns_priv_table_fields[MYSQL_COLUMNS_PRIV_FIELD_COUNT] = { + { + { C_STRING_WITH_LEN("Host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Db") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("User") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Table_name") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Column_name") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Column_priv") }, + { C_STRING_WITH_LEN("set('Select','Insert','Update','References')") }, + { C_STRING_WITH_LEN("utf8") } + } +}; + +static const +TABLE_FIELD_TYPE mysql_tables_priv_table_fields[MYSQL_TABLES_PRIV_FIELD_COUNT] = { + { + { C_STRING_WITH_LEN("Host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Db") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("User") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Table_name") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Grantor") }, + { C_STRING_WITH_LEN("char(77)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Table_priv") }, + { C_STRING_WITH_LEN("set('Select','Insert','Update','Delete','Create'," + "'Drop','Grant','References','Index','Alter'," + "'Create View','Show view','Trigger')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Column_priv") }, + { C_STRING_WITH_LEN("set('Select','Insert','Update','References')") }, + { C_STRING_WITH_LEN("utf8") } + } +}; + + const TABLE_FIELD_DEF mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields}; +const TABLE_FIELD_DEF + mysql_user_table_def= {MYSQL_USER_FIELD_COUNT, mysql_user_table_fields}; + +const TABLE_FIELD_DEF + mysql_proxies_priv_table_def= {MYSQL_PROXIES_PRIV_FIELD_COUNT, + mysql_proxies_priv_table_fields}; + +const TABLE_FIELD_DEF + mysql_procs_priv_table_def= {MYSQL_PROCS_PRIV_FIELD_COUNT, + mysql_procs_priv_table_fields}; + +const TABLE_FIELD_DEF + mysql_columns_priv_table_def= {MYSQL_COLUMNS_PRIV_FIELD_COUNT, + mysql_columns_priv_table_fields}; + +const TABLE_FIELD_DEF + mysql_tables_priv_table_def= {MYSQL_TABLES_PRIV_FIELD_COUNT, + mysql_tables_priv_table_fields}; + static LEX_STRING native_password_plugin_name= { C_STRING_WITH_LEN("mysql_native_password") }; @@ -519,6 +921,36 @@ static uchar* acl_entry_get_key(acl_entry *entry, size_t *length, return (uchar*) entry->key; } +/** + Class to validate the flawlessness of ACL table + before performing ACL operations. +*/ +class Acl_table_intact : public Table_check_intact +{ +protected: + void report_error(uint code, const char *fmt, ...) + { + va_list args; + va_start(args, fmt); + error_log_print(ERROR_LEVEL, fmt, args); + va_end(args); + if (code) + { + va_start(args, fmt); + if (code == ER_CANNOT_LOAD_FROM_TABLE) + { + char *table_name; + va_arg(args, char *); + table_name= va_arg(args, char *); + my_error(code, MYF(0), table_name); + } + else + my_printv_error(code, ER(code), MYF(0), args); + va_end(args); + } + } +}; + #define IP_ADDR_STRLEN (3 + 1 + 3 + 1 + 3 + 1 + 3) #define ACL_KEY_LENGTH (IP_ADDR_STRLEN + 1 + NAME_LEN + \ 1 + USERNAME_LENGTH + 1) @@ -548,6 +980,7 @@ static bool update_user_table(THD *thd, TABLE *table, static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); static inline void get_grantor(THD *thd, char* grantor); + /* Enumeration of various ACL's and Hashes used in handle_grant_struct() */ @@ -1871,6 +2304,7 @@ bool change_password(THD *thd, const char *host, const char *user, { TABLE_LIST tables; TABLE *table; + Acl_table_intact table_intact; /* Buffer should be extended when password length is extended. */ char buff[512]; ulong query_length; @@ -1907,6 +2341,9 @@ bool change_password(THD *thd, const char *host, const char *user, if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) DBUG_RETURN(1); + if (table_intact.check(table, &mysql_user_table_def)) + DBUG_RETURN(1); + /* This statement will be replicated as a statement, even when using row-based replication. The flag will be reset at the end of the @@ -2267,10 +2704,14 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, char what= (revoke_grant) ? 'N' : 'Y'; uchar user_key[MAX_KEY_LENGTH]; LEX *lex= thd->lex; + Acl_table_intact table_intact; DBUG_ENTER("replace_user_table"); mysql_mutex_assert_owner(&acl_cache->lock); + if (table_intact.check(table, &mysql_user_table_def)) + goto end; + if (combo.password.str && combo.password.str[0]) { if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH && @@ -2530,6 +2971,7 @@ static int replace_db_table(TABLE *table, const char *db, int error; char what= (revoke_grant) ? 'N' : 'Y'; uchar user_key[MAX_KEY_LENGTH]; + Acl_table_intact table_intact; DBUG_ENTER("replace_db_table"); if (!initialized) @@ -2538,6 +2980,9 @@ static int replace_db_table(TABLE *table, const char *db, DBUG_RETURN(-1); } + if (table_intact.check(table, &mysql_db_table_def)) + DBUG_RETURN(-1); + /* Check if there is such a user in user table in memory? */ if (!find_acl_user(combo.host.str,combo.user.str, FALSE)) { @@ -2678,6 +3123,7 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, uchar user_key[MAX_KEY_LENGTH]; ACL_PROXY_USER new_grant; char grantor[USER_HOST_BUFF_SIZE]; + Acl_table_intact table_intact; DBUG_ENTER("replace_proxies_priv_table"); @@ -2687,6 +3133,9 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, DBUG_RETURN(-1); } + if (table_intact.check(table, &mysql_proxies_priv_table_def)) + DBUG_RETURN(-1); + /* Check if there is such a user in user table in memory? */ if (!find_acl_user(user->host.str,user->user.str, FALSE)) { @@ -3090,9 +3539,13 @@ static int replace_column_table(GRANT_TABLE *g_t, int result=0; uchar key[MAX_KEY_LENGTH]; uint key_prefix_length; - KEY_PART_INFO *key_part= table->key_info->key_part; + KEY_PART_INFO *key_part; + Acl_table_intact table_intact; DBUG_ENTER("replace_column_table"); + if (table_intact.check(table, &mysql_columns_priv_table_def)) + DBUG_RETURN(-1); + table->use_all_columns(); table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); @@ -3104,6 +3557,7 @@ static int replace_column_table(GRANT_TABLE *g_t, system_charset_info); /* Get length of 4 first key parts */ + key_part= table->key_info->key_part; key_prefix_length= (key_part[0].store_length + key_part[1].store_length + key_part[2].store_length + key_part[3].store_length); key_copy(key, table->record[0], table->key_info, key_prefix_length); @@ -3305,8 +3759,12 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, int error=0; ulong store_table_rights, store_col_rights; uchar user_key[MAX_KEY_LENGTH]; + Acl_table_intact table_intact; DBUG_ENTER("replace_table_table"); + if (table_intact.check(table, &mysql_tables_priv_table_def)) + DBUG_RETURN(-1); + get_grantor(thd, grantor); /* The following should always succeed as new users are created before @@ -3429,6 +3887,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, int old_row_exists= 1; int error=0; ulong store_proc_rights; + Acl_table_intact table_intact; DBUG_ENTER("replace_routine_table"); if (!initialized) @@ -3437,6 +3896,9 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, DBUG_RETURN(-1); } + if (table_intact.check(table, &mysql_procs_priv_table_def)) + DBUG_RETURN(-1); + get_grantor(thd, grantor); /* New users are created before this function is called. @@ -6366,9 +6828,16 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, int result= 0; int found; int ret; + Acl_table_intact table_intact; DBUG_ENTER("handle_grant_data"); /* Handle user table. */ + if (table_intact.check(tables[0].table, &mysql_user_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ @@ -6393,6 +6862,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle db table. */ + if (table_intact.check(tables[1].table, &mysql_db_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 1, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ @@ -6417,6 +6892,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle stored routines table. */ + if (table_intact.check(tables[4].table, &mysql_procs_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 4, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch in-memory array. */ @@ -6457,6 +6938,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle tables table. */ + if (table_intact.check(tables[2].table, &mysql_tables_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 2, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch columns and in-memory array. */ @@ -6473,6 +6960,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle columns table. */ + if (table_intact.check(tables[3].table, &mysql_columns_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 3, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ @@ -6493,6 +6986,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, /* Handle proxies_priv table. */ if (tables[5].table) { + if (table_intact.check(tables[5].table, &mysql_proxies_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 5, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 050649d39bc..8718c6feae9 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -1,7 +1,7 @@ #ifndef SQL_ACL_INCLUDED #define SQL_ACL_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -143,6 +143,53 @@ (((A) & ALTER_PROC_ACL) >> 23) | \ (((A) & GRANT_ACL) >> 8)) +enum mysql_user_table_field +{ + MYSQL_USER_FIELD_HOST = 0, + MYSQL_USER_FIELD_USER, + MYSQL_USER_FIELD_PASSWORD, + MYSQL_USER_FIELD_SELECT_PRIV, + MYSQL_USER_FIELD_INSERT_PRIV, + MYSQL_USER_FIELD_UPDATE_PRIV, + MYSQL_USER_FIELD_DELETE_PRIV, + MYSQL_USER_FIELD_CREATE_PRIV, + MYSQL_USER_FIELD_DROP_PRIV, + MYSQL_USER_FIELD_RELOAD_PRIV, + MYSQL_USER_FIELD_SHUTDOWN_PRIV, + MYSQL_USER_FIELD_PROCESS_PRIV, + MYSQL_USER_FIELD_FILE_PRIV, + MYSQL_USER_FIELD_GRANT_PRIV, + MYSQL_USER_FIELD_REFERENCES_PRIV, + MYSQL_USER_FIELD_INDEX_PRIV, + MYSQL_USER_FIELD_ALTER_PRIV, + MYSQL_USER_FIELD_SHOW_DB_PRIV, + MYSQL_USER_FIELD_SUPER_PRIV, + MYSQL_USER_FIELD_CREATE_TMP_TABLE_PRIV, + MYSQL_USER_FIELD_LOCK_TABLES_PRIV, + MYSQL_USER_FIELD_EXECUTE_PRIV, + MYSQL_USER_FIELD_REPL_SLAVE_PRIV, + MYSQL_USER_FIELD_REPL_CLIENT_PRIV, + MYSQL_USER_FIELD_CREATE_VIEW_PRIV, + MYSQL_USER_FIELD_SHOW_VIEW_PRIV, + MYSQL_USER_FIELD_CREATE_ROUTINE_PRIV, + MYSQL_USER_FIELD_ALTER_ROUTINE_PRIV, + MYSQL_USER_FIELD_CREATE_USER_PRIV, + MYSQL_USER_FIELD_EVENT_PRIV, + MYSQL_USER_FIELD_TRIGGER_PRIV, + MYSQL_USER_FIELD_CREATE_TABLESPACE_PRIV, + MYSQL_USER_FIELD_SSL_TYPE, + MYSQL_USER_FIELD_SSL_CIPHER, + MYSQL_USER_FIELD_X509_ISSUER, + MYSQL_USER_FIELD_X509_SUBJECT, + MYSQL_USER_FIELD_MAX_QUESTIONS, + MYSQL_USER_FIELD_MAX_UPDATES, + MYSQL_USER_FIELD_MAX_CONNECTIONS, + MYSQL_USER_FIELD_MAX_USER_CONNECTIONS, + MYSQL_USER_FIELD_PLUGIN, + MYSQL_USER_FIELD_AUTHENTICATION_STRING, + MYSQL_USER_FIELD_COUNT +}; + enum mysql_db_table_field { MYSQL_DB_FIELD_HOST = 0, @@ -170,6 +217,56 @@ enum mysql_db_table_field MYSQL_DB_FIELD_COUNT }; +enum mysql_proxies_priv_table_feild +{ + MYSQL_PROXIES_PRIV_FIELD_HOST = 0, + MYSQL_PROXIES_PRIV_FIELD_USER, + MYSQL_PROXIES_PRIV_FIELD_PROXIED_HOST, + MYSQL_PROXIES_PRIV_FIELD_PROXIED_USER, + MYSQL_PROXIES_PRIV_FIELD_WITH_GRANT, + MYSQL_PROXIES_PRIV_FIELD_GRANTOR, + MYSQL_PROXIES_PRIV_FIELD_TIMESTAMP, + MYSQL_PROXIES_PRIV_FIELD_COUNT +}; + +enum mysql_procs_priv_table_field +{ + MYSQL_PROCS_PRIV_FIELD_HOST = 0, + MYSQL_PROCS_PRIV_FIELD_DB, + MYSQL_PROCS_PRIV_FIELD_USER, + MYSQL_PROCS_PRIV_FIELD_ROUTINE_NAME, + MYSQL_PROCS_PRIV_FIELD_ROUTINE_TYPE, + MYSQL_PROCS_PRIV_FIELD_GRANTOR, + MYSQL_PROCS_PRIV_FIELD_PROC_PRIV, + MYSQL_PROCS_PRIV_FIELD_TIMESTAMP, + MYSQL_PROCS_PRIV_FIELD_COUNT +}; + +enum mysql_columns_priv_table_field +{ + MYSQL_COLUMNS_PRIV_FIELD_HOST = 0, + MYSQL_COLUMNS_PRIV_FIELD_DB, + MYSQL_COLUMNS_PRIV_FIELD_USER, + MYSQL_COLUMNS_PRIV_FIELD_TABLE_NAME, + MYSQL_COLUMNS_PRIV_FIELD_COLUMN_NAME, + MYSQL_COLUMNS_PRIV_FIELD_TIMESTAMP, + MYSQL_COLUMNS_PRIV_FIELD_COLUMN_PRIV, + MYSQL_COLUMNS_PRIV_FIELD_COUNT +}; + +enum mysql_tables_priv_table_field +{ + MYSQL_TABLES_PRIV_FIELD_HOST = 0, + MYSQL_TABLES_PRIV_FIELD_DB, + MYSQL_TABLES_PRIV_FIELD_USER, + MYSQL_TABLES_PRIV_FIELD_TABLE_NAME, + MYSQL_TABLES_PRIV_FIELD_GRANTOR, + MYSQL_TABLES_PRIV_FIELD_TIMESTAMP, + MYSQL_TABLES_PRIV_FIELD_TABLE_PRIV, + MYSQL_TABLES_PRIV_FIELD_COLUMN_PRIV, + MYSQL_TABLES_PRIV_FIELD_COUNT +}; + extern const TABLE_FIELD_DEF mysql_db_table_def; extern bool mysql_user_table_is_in_short_password_format; diff --git a/sql/table.cc b/sql/table.cc index 750b870da75..5bc3ccdbf39 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2998,11 +2998,7 @@ bool check_column_name(const char *name) and type) @retval FALSE OK - @retval TRUE There was an error. An error message is output - to the error log. We do not push an error - message into the error stack because this - function is currently only called at start up, - and such errors never reach the user. + @retval TRUE There was an error. */ bool @@ -3091,28 +3087,28 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) if (strncmp(sql_type.c_ptr_safe(), field_def->type.str, field_def->type.length - 1)) { - report_error(0, "Incorrect definition of table %s.%s: " - "expected column '%s' at position %d to have type " - "%s, found type %s.", table->s->db.str, table->alias, - field_def->name.str, i, field_def->type.str, + report_error(ER_CANNOT_LOAD_FROM_TABLE, "Incorrect definition of " + "table %s.%s: expected column '%s' at position %d to " + "have type %s, found type %s.", table->s->db.str, + table->alias, field_def->name.str, i, field_def->type.str, sql_type.c_ptr_safe()); error= TRUE; } else if (field_def->cset.str && !field->has_charset()) { - report_error(0, "Incorrect definition of table %s.%s: " - "expected the type of column '%s' at position %d " - "to have character set '%s' but the type has no " - "character set.", table->s->db.str, table->alias, + report_error(ER_CANNOT_LOAD_FROM_TABLE, "Incorrect definition of " + "table %s.%s: expected the type of column '%s' at " + "position %d to have character set '%s' but the type " + "has no character set.", table->s->db.str, table->alias, field_def->name.str, i, field_def->cset.str); error= TRUE; } else if (field_def->cset.str && strcmp(field->charset()->csname, field_def->cset.str)) { - report_error(0, "Incorrect definition of table %s.%s: " - "expected the type of column '%s' at position %d " - "to have character set '%s' but found " + report_error(ER_CANNOT_LOAD_FROM_TABLE, "Incorrect definition of " + "table %s.%s: expected the type of column '%s' at " + "position %d to have character set '%s' but found " "character set '%s'.", table->s->db.str, table->alias, field_def->name.str, i, field_def->cset.str, field->charset()->csname); @@ -3121,11 +3117,11 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) } else { - report_error(0, "Incorrect definition of table %s.%s: " - "expected column '%s' at position %d to have type %s " - " but the column is not found.", - table->s->db.str, table->alias, - field_def->name.str, i, field_def->type.str); + report_error(ER_CANNOT_LOAD_FROM_TABLE, "Incorrect definition of " + "table %s.%s: expected column '%s' at position %d to " + "have type %s but the column is not found.", + table->s->db.str, table->alias, field_def->name.str, i, + field_def->type.str); error= TRUE; } } From ab5932f851da38d05bd1e401467ed197bdc2836d Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Mon, 28 Nov 2016 16:38:03 +0530 Subject: [PATCH 011/148] Bug#25159791 BASEDIR: COMMAND NOT FOUND ERROR WHILE STARTING SERVER WITH INIT SCRIPTS --- packaging/rpm-oel/mysql-systemd-start | 2 +- packaging/rpm-oel/mysql.init | 6 +++--- packaging/rpm-sles/mysql.init | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packaging/rpm-oel/mysql-systemd-start b/packaging/rpm-oel/mysql-systemd-start index af6e906efe1..c744bdceeb4 100644 --- a/packaging/rpm-oel/mysql-systemd-start +++ b/packaging/rpm-oel/mysql-systemd-start @@ -22,7 +22,7 @@ install_db () { datadir=$(get_option mysqld datadir "/var/lib/mysql") # Restore log, dir, perms and SELinux contexts - if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then install -d -m 0755 -omysql -gmysql "$datadir" || exit 1 fi log=/var/log/mysqld.log diff --git a/packaging/rpm-oel/mysql.init b/packaging/rpm-oel/mysql.init index 50d1bba017d..c3bbb277b91 100644 --- a/packaging/rpm-oel/mysql.init +++ b/packaging/rpm-oel/mysql.init @@ -76,10 +76,10 @@ start(){ [ -x /sbin/restorecon ] && /sbin/restorecon "$errlogfile" if [ ! -d "$datadir/mysql" ] ; then # First, make sure $datadir is there with correct permissions - if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then install -d -m0755 -omysql -gmysql "$datadir" || exit 1 fi - if [ ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + if [ ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then chown mysql:mysql "$datadir" chmod 0755 "$datadir" fi @@ -99,7 +99,7 @@ start(){ return $ret fi fi - if [ ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + if [ ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then chown mysql:mysql "$datadir" chmod 0755 "$datadir" fi diff --git a/packaging/rpm-sles/mysql.init b/packaging/rpm-sles/mysql.init index 25762d9bee2..62f2a62e1b9 100644 --- a/packaging/rpm-sles/mysql.init +++ b/packaging/rpm-sles/mysql.init @@ -57,7 +57,7 @@ install_db () { logfile=$(get_option mysqld_safe log-error "/var/log/mysql/mysqld.log") # Restore log, dir, perms and SELinux contexts - if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(basedir "$datadir")" = "x/var/lib" ]; then + if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then install -d -m 0755 -omysql -gmysql "$datadir" || return 1 fi From 8f297058512e6744b8d9f0bafe35689c702fce67 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Tue, 29 Nov 2016 11:19:30 +0530 Subject: [PATCH 012/148] Bug#24449090 - BUFFER OVERFLOW IN FUNCTION DUPL DESCRIPTION =========== Performing a pattern match of a Regex resulting into a very large string, leads to crash due to failed realloc(). ANALYSIS ======== dupl() calls enlarge(). It in turn calls realloc() for pointer p->strip. This eventually fails due to OOM. However we are still using the same pointer in memcpy() causing a SEGFAULT! FIX === 1) In dupl(), checking for error code (which would be set if realloc fails) immediately after call to enlarge(). Returning now with this error code. 2) Handling the same in the caller functions. --- regex/regcomp.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/regex/regcomp.c b/regex/regcomp.c index b1074a1d79c..e7feb9301e6 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -3,7 +3,7 @@ This file was modified by Oracle on 2015-05-18 for 32-bit compatibility. - Modifications copyright (c) 2015, Oracle and/or its affiliates. All rights + Modifications copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ #include @@ -551,6 +551,8 @@ int starordinary; /* is a leading * an ordinary character? */ assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); assert(OP(p->strip[p->pend[i]]) == ORPAREN); (void) dupl(p, p->pbegin[i]+1, p->pend[i]); + if (p->error != 0) + break; /* purecov: inspected */ EMIT(O_BACK, i); } else SETERROR(REG_ESUBREG); @@ -1031,6 +1033,8 @@ int to; /* to this number of times (maybe RE_INFINITY) */ AHEAD(THERE()); /* ...so fix it */ ASTERN(O_CH, THERETHERE()); copy = dupl(p, start+1, finish+1); + if (p->error != 0) + return; /* purecov: inspected */ assert(copy == finish+4); repeat(p, copy, 1, to-1); break; @@ -1040,10 +1044,14 @@ int to; /* to this number of times (maybe RE_INFINITY) */ break; case REP(N, N): /* as xx{m-1,n-1} */ copy = dupl(p, start, finish); + if (p->error != 0) + return; repeat(p, copy, from-1, to-1); break; case REP(N, INF): /* as xx{n-1,INF} */ copy = dupl(p, start, finish); + if (p->error != 0) + return; /* purecov: inspected */ repeat(p, copy, from-1, to); break; default: /* "can't happen" */ @@ -1366,6 +1374,9 @@ sopno finish; /* to this less one */ if (len == 0) return(ret); enlarge(p, p->ssize + len); /* this many unexpected additions */ + if (p->error != 0) + return(p->error); + assert(p->ssize >= p->slen + len); (void) memcpy((char *)(p->strip + p->slen), (char *)(p->strip + start), (size_t)len*sizeof(sop)); @@ -1482,6 +1493,14 @@ register sopno size; if (p->ssize >= size) return; + DBUG_EXECUTE_IF("bug24449090_simulate_oom", + { + p->strip= NULL; + p->ssize= 0; + SETERROR(REG_ESPACE); + return; + }); + sp = (sop *)realloc(p->strip, size*sizeof(sop)); if (sp == NULL) { SETERROR(REG_ESPACE); From 52b0c8146b1ae84a6c3fa1a20aa41736df485a46 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Tue, 29 Nov 2016 11:26:25 +0530 Subject: [PATCH 013/148] Bug#24449076 - INTEGER OVERFLOW IN FUNCTION DOINSERT DESCRIPTION =========== Performing a pattern match of a Regex resulting into a very large string, leads to crash due to integer wraparound. ANALYSIS ======== doinsert() - The length calculated here (to copy the number of bytes) comes out to be too large to be stored in the "int" variable 'length'. We need to ensure that the variable can accommodate large lengths. FIX === 'length' in doinsert() is now defined as of type "size_t" instead of "int" --- regex/regcomp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regex/regcomp.c b/regex/regcomp.c index e7feb9301e6..7c450db07b7 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -1449,7 +1449,7 @@ sopno pos; } } { - int length=(HERE()-pos-1)*sizeof(sop); + size_t length=(HERE()-pos-1)*sizeof(sop); bmove_upp((uchar *) &p->strip[pos+1]+length, (uchar *) &p->strip[pos]+length, length); From 68b88afb0c7b65e36d27ebca05bd2e354840f2cf Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Sun, 4 Dec 2016 18:44:51 +0530 Subject: [PATCH 014/148] Bug#24449090 - BUFFER OVERFLOW IN FUNCTION DUPL Post-push fix for memory leak in the code inside DBUG_EXECUTE_IF("bug24449090_simulate_oom",...); --- regex/regcomp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/regex/regcomp.c b/regex/regcomp.c index 7c450db07b7..13275237d2a 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -1495,6 +1495,7 @@ register sopno size; DBUG_EXECUTE_IF("bug24449090_simulate_oom", { + free(p->strip); p->strip= NULL; p->ssize= 0; SETERROR(REG_ESPACE); From 6786caed623a051a364a73549181806c9d6ca757 Mon Sep 17 00:00:00 2001 From: Pavan Naik Date: Mon, 5 Dec 2016 10:17:40 +0530 Subject: [PATCH 015/148] BUG#25147154 : MTR TRIES TO COPY CONTENTS FROM /TMP/DATA Description : ============= When a MTR test run is started, it initializes the server and creates the datadir under '$MYSQL_TEST_DIR/var'('/tmp/var' or '/dev/shm/var' if --mem option is used) location and then copies it to the datadir location of server(s). If $parallel == 1, datadir location of the server is '$MYSQL_TEST_DIR/var/data'. If $parallel > 1, datadir location of any server is '$MYSQL_TEST_DIR/var//data'. This is the reason MTR searches for the initialized datadir in 2 locations('$opt_vardir' and '$opt_vardir/..') from the current vardir location.. But this can cause few problems. If a directory with the name 'data' already exists under '$MYSQL_TEST_DIR' and if the MTR run is started with parallel value 1, then 1. copytree($install_db, '$opt_vardir/..') command will fail if the user doesn't have the access permission to '$MYSQL_TEST_DIR/data' directory. 2. Unnecessary contents from '$MYSQL_TEST_DIR/data' directory will be copied to server datadir location and this might affect the server startup. Fix : ===== Depending on the $parallel value decide whether the path for the initialize datadir is "$opt_vardir"(i.e $parallel = 1) or "$opt_vardir/.."(i.e $parallel > 1). Reviewed-by: Deepa Dixit Reviewed-by: Srikanth B R RB: 14773 --- mysql-test/mysql-test-run.pl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 3eb70c1bdb9..86d37a56835 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -5388,16 +5388,14 @@ sub start_servers($) { my $mysqld_basedir= $mysqld->value('basedir'); if ( $basedir eq $mysqld_basedir ) { - if (! $opt_start_dirty) # If dirty, keep possibly grown system db + if (!$opt_start_dirty) # If dirty, keep possibly grown system db { - # Copy datadir from installed system db - for my $path ( "$opt_vardir", "$opt_vardir/..") { - my $install_db= "$path/install.db"; - copytree($install_db, $datadir) - if -d $install_db; - } - mtr_error("Failed to copy system db to '$datadir'") - unless -d $datadir; + # Copy datadir from installed system db + my $path= ($opt_parallel == 1) ? "$opt_vardir" : "$opt_vardir/.."; + my $install_db= "$path/install.db"; + copytree($install_db, $datadir) if -d $install_db; + mtr_error("Failed to copy system db to '$datadir'") + unless -d $datadir; } } else From 6722699551c8a63a4a7d5d76d116c049fabbbe51 Mon Sep 17 00:00:00 2001 From: Terje Rosten Date: Fri, 2 Dec 2016 13:33:44 +0100 Subject: [PATCH 016/148] Bug#22240513 REMOVE GITIGNORE / BZRIGNORE FROM OFFICIAL RELEASE Add .gitattributes to let git archive ignore .gitignore. --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..596615322fb --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +.gitattributes export-ignore +.gitignore export-ignore From dafbdc788a1fe551990c736daaf2a39998f4cbc0 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 5 Dec 2016 15:36:23 +0200 Subject: [PATCH 017/148] Bug #25111907: XML TEST FAILS WITH UNDEFINED BEHAVIOR The XML parser position stack for each level is with a fixed depth. So a bounds check was done to ensure that this depth is not exceeded. But it was off by one (i.e. the size of the array was a valid index). Fixed by decreasing the allowable depth by one to match the maximum number of elements in the position stack. --- sql/item_xmlfunc.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 2c8aab83ed9..31cd4fdd170 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2695,9 +2695,9 @@ int xml_enter(MY_XML_PARSER *st,const char *attr, size_t len) node.parent= data->parent; // Set parent for the new node to old parent data->parent= numnodes; // Remember current node as new parent - DBUG_ASSERT(data->level <= MAX_LEVEL); + DBUG_ASSERT(data->level < MAX_LEVEL); data->pos[data->level]= numnodes; - if (data->level < MAX_LEVEL) + if (data->level < MAX_LEVEL - 1) node.level= data->level++; else return MY_XML_ERROR; From 9ccd55466d1384865768663dd6bf2b04e11ba774 Mon Sep 17 00:00:00 2001 From: Terje Rosten Date: Tue, 6 Dec 2016 08:35:26 +0100 Subject: [PATCH 018/148] BUG#13788154 INIT.D MYSQL SCRIPT CREATED BY MYSQL SOLARIS PACKAGE FAILS TO RUN DUE TO USE OF PIDOF pidof is Linuxism, prefer pgrep on other UNIX systems. --- support-files/CMakeLists.txt | 7 ++++++- support-files/mysql.server.sh | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index 6aef51a5c16..924f08dfc83 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -48,6 +48,11 @@ FOREACH(inifile my-huge my-innodb-heavy-4G my-large my-medium my-small) ENDFOREACH() IF(UNIX) + IF(CMAKE_SYSTEM_NAME MATCHES "Linux") + SET (PIDOF "pidof") + ELSE() + SET (PIDOF "pgrep -d' ' -f") + ENDIF() SET(prefix ${CMAKE_INSTALL_PREFIX}) FOREACH(script mysqld_multi.server mysql-log-rotate binary-configure config.medium.ini config.small.ini config.huge.ini ndb-config-2-node.ini) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 909d33f8770..cb13d2f10ba 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -359,7 +359,7 @@ case "$mode" in fi else # Try to find appropriate mysqld process - mysqld_pid=`pidof $libexecdir/mysqld` + mysqld_pid=`@PIDOF@ $libexecdir/mysqld` # test if multiple pids exist pid_count=`echo $mysqld_pid | wc -w` From 30a59a8d78f10f738aef124fe6736851275192bd Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Tue, 13 Dec 2016 16:41:05 +0530 Subject: [PATCH 019/148] Bug #24595937: INCORRECT BEHAVIOR WHEN LOADING DATA TO VIEW Issue: ------ While using the LOAD statement to insert data into an updateable view, the check to verify whether a column is actually updatable is missing. Solution for 5.5 and 5.6: ------------------------- For a view whose column-list in specified in the LOAD command, this check is not performed. This fix adds the check. This is a partial backport of Bug#21097485. Solution for 5.7 and trunk: --------------------------- For a view whose column-list is specified in the LOAD command, this check is already performed. This fix adds the same check when no column-list is specified. --- mysql-test/r/loaddata.result | 2 +- mysql-test/t/loaddata.test | 2 +- sql/sql_load.cc | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 2d67d24bedd..6942ec6b332 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -316,7 +316,7 @@ FIELDS ESCAPED BY '\\' TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' (c0, c2); -ERROR HY000: Invalid column reference (v2.c0) in LOAD DATA +ERROR HY000: Column 'c0' is not updatable LOAD DATA INFILE '../../std_data/bug35469.dat' INTO TABLE v3 FIELDS ESCAPED BY '\\' diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index aa7be52484e..db21058daea 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -292,7 +292,7 @@ SELECT * FROM v2; DELETE FROM t1; --echo ---error ER_LOAD_DATA_INVALID_COLUMN +--error ER_NONUPDATEABLE_COLUMN LOAD DATA INFILE '../../std_data/bug35469.dat' INTO TABLE v2 FIELDS ESCAPED BY '\\' TERMINATED BY ',' diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c084e5e3839..c28c7cdb2db 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -296,6 +296,24 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); + + /* + Special updatability test is needed because fields_vars may contain + a mix of column references and user variables. + */ + Item *item; + List_iterator it(fields_vars); + while ((item= it++)) + { + if ((item->type() == Item::FIELD_ITEM || + item->type() == Item::REF_ITEM) && + item->filed_for_view_update() == NULL) + { + my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name); + DBUG_RETURN(true); + } + } + /* Check whenever TIMESTAMP field with auto-set feature specified explicitly. From 1079066b22815b9c46a6689c93469c3af1fd88ff Mon Sep 17 00:00:00 2001 From: Terje Rosten Date: Mon, 19 Dec 2016 10:15:54 +0100 Subject: [PATCH 020/148] Bug#13344753 MYSQL_SECURE_INSTALLATION SCRIPT DOES NOT CHECK USER INPUT Loop until valid answer is given. Variants of y,yes and n,no and blank (meaning default) are considered valid. --- scripts/mysql_secure_installation.sh | 67 ++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index c92cb1262df..236525c12cd 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -33,6 +33,20 @@ set_echo_compat() { esac } +validate_reply () { + ret=0 + if [ -z "$1" ]; then + reply=y + return $ret + fi + case $1 in + y|Y|yes|Yes|YES) reply=y ;; + n|N|no|No|NO) reply=n ;; + *) ret=1 ;; + esac + return $ret +} + prepare() { touch $config $command chmod 600 $config $command @@ -258,15 +272,18 @@ echo "Setting the root password ensures that nobody can log into the MySQL" echo "root user without the proper authorisation." echo -if [ $hadpass -eq 0 ]; then - echo $echo_n "Set root password? [Y/n] $echo_c" -else - echo "You already have a root password set, so you can safely answer 'n'." - echo - echo $echo_n "Change the root password? [Y/n] $echo_c" -fi +while true ; do + if [ $hadpass -eq 0 ]; then + echo $echo_n "Set root password? [Y/n] $echo_c" + else + echo "You already have a root password set, so you can safely answer 'n'." + echo + echo $echo_n "Change the root password? [Y/n] $echo_c" + fi + read reply + validate_reply $reply && break +done -read reply if [ "$reply" = "n" ]; then echo " ... skipping." else @@ -290,9 +307,11 @@ echo "go a bit smoother. You should remove them before moving into a" echo "production environment." echo -echo $echo_n "Remove anonymous users? [Y/n] $echo_c" - -read reply +while true ; do + echo $echo_n "Remove anonymous users? [Y/n] $echo_c" + read reply + validate_reply $reply && break +done if [ "$reply" = "n" ]; then echo " ... skipping." else @@ -308,9 +327,11 @@ echo echo "Normally, root should only be allowed to connect from 'localhost'. This" echo "ensures that someone cannot guess at the root password from the network." echo - -echo $echo_n "Disallow root login remotely? [Y/n] $echo_c" -read reply +while true ; do + echo $echo_n "Disallow root login remotely? [Y/n] $echo_c" + read reply + validate_reply $reply && break +done if [ "$reply" = "n" ]; then echo " ... skipping." else @@ -328,8 +349,12 @@ echo "access. This is also intended only for testing, and should be removed" echo "before moving into a production environment." echo -echo $echo_n "Remove test database and access to it? [Y/n] $echo_c" -read reply +while true ; do + echo $echo_n "Remove test database and access to it? [Y/n] $echo_c" + read reply + validate_reply $reply && break +done + if [ "$reply" = "n" ]; then echo " ... skipping." else @@ -346,8 +371,12 @@ echo "Reloading the privilege tables will ensure that all changes made so far" echo "will take effect immediately." echo -echo $echo_n "Reload privilege tables now? [Y/n] $echo_c" -read reply +while true ; do + echo $echo_n "Reload privilege tables now? [Y/n] $echo_c" + read reply + validate_reply $reply && break +done + if [ "$reply" = "n" ]; then echo " ... skipping." else From e00810b934fd495009c1b8d47446714bdbc0b249 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Thu, 22 Dec 2016 14:56:02 +0530 Subject: [PATCH 021/148] Bug#11751149 - TRYING TO START MYSQL WHILE ANOTHER INSTANCE IS STARTING: CONFUSING ERROR DESCRIPTION =========== When mysql server processes transactions but has not yet committed and shuts down abnormally (due to crash, external killing etc.), a recovery is due from Storage engine side which takes place the next time mysql server (either through mysqld or mysqld_safe) is run. While the 1st server is in mid of recovery, if another instance of mysqld_safe is made to run, it may result into 2nd instance killing the 1st one after a moment. ANALYSIS ======== In the "while true" loop, we've a check (which is done after the server stops) for the existence of pid file to enquire if it was a normal shutdown or not. If the file is absent, it means that the graceful exit of server had removed this file. However if the file is present, the scripts makes a plain assumption that this file is leftover of the "current" server. It misses to consider that it could be a valid pid file belonging to another running mysql server. We need to add more checks in the latter case. The script should extract the PID from this existing file and check if its running or not. If yes, it means an older instance of mysql server is running and hence the script should abort. FIX === Checking the status of process (alive or not) by adding a @CHECK_PID@ in such a case. Aborting if its alive. Detailed logic is as follows: - The mysqld_safe script would quit at start only as soon as it finds that there is an active PID i.e. a mysql server is already running. - The PID file creation takes place after InnoDb recovery, which means in rare case (when PID file isn't created yet) it may happen that more than 1 server can come up but even in that case others will have to wait till the 1st server has released the acquired InnoDb lock. In this case all these servers will either TIMEOUT waiting for InnoDb lock or after this they would find that the 1st server is already running (by reading $pid_file) and would abort. - Our core fix is that we now check the status of mysql server process (alive or not) after the server stops running within the loop of "run -> shutdown/kill/abort -> run ... ", so that only the script who owns the mysql server would be able to bring it down if required. NOTE ==== Removed the deletion of pid file and socket file from entry of the loop, as it may result in 2nd instance deleting these files created by 1st instance in RACE condition. Compensated this by deleting these files at end of the loop Reverted the changes made in patch to Bug#16776528. So after this patch is pushed, the concept of mysqld_safe.pid would go altogether. This was required as the script was deleting other instance's mysqld_safe.pid allowing multiple mysqld_safe instances to run in parallel. This patch would fix Bug#16776528 as well as the resources would be guarded anyway by InnoDb lock + our planned 5.7 patch. --- scripts/mysqld_safe.sh | 44 ++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index a5c87a44e65..5148ecfc888 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -790,14 +790,23 @@ then fi if [ ! -h "$pid_file" ]; then rm -f "$pid_file" - fi - if test -f "$pid_file" - then - log_error "Fatal error: Can't remove the pid file: -$pid_file -Please remove it manually and start $0 again; + if test -f "$pid_file"; then + log_error "Fatal error: Can't remove the pid file: +$pid_file. +Please remove the file manually and start $0 again; mysqld daemon not started" - exit 1 + exit 1 + fi + fi + if [ ! -h "$safe_mysql_unix_port" ]; then + rm -f "$safe_mysql_unix_port" + if test -f "$safe_mysql_unix_port"; then + log_error "Fatal error: Can't remove the socket file: +$safe_mysql_unix_port. +Please remove the file manually and start $0 again; +mysqld daemon not started" + exit 1 + fi fi fi @@ -841,14 +850,6 @@ have_sleep=1 while true do - # Some extra safety - if [ ! -h "$safe_mysql_unix_port" ]; then - rm -f "$safe_mysql_unix_port" - fi - if [ ! -h "$pid_file" ]; then - rm -f "$pid_file" - fi - start_time=`date +%M%S` eval_log_error "$cmd" @@ -884,6 +885,13 @@ do if test ! -f "$pid_file" # This is removed if normal shutdown then break + else # self's mysqld crashed or other's mysqld running + PID=`cat "$pid_file"` + if @CHECK_PID@ + then # true when above pid belongs to a running mysqld process + log_error "A mysqld process with pid=$PID is already running. Aborting!!" + exit 1 + fi fi @@ -941,6 +949,12 @@ do I=`expr $I + 1` done fi + if [ ! -h "$pid_file" ]; then + rm -f "$pid_file" + fi + if [ ! -h "$safe_mysql_unix_port" ]; then + rm -f "$safe_mysql_unix_port" + fi log_notice "mysqld restarted" done From e7a3ccf6b1b1b41e0fa191d26e9e775517c6deee Mon Sep 17 00:00:00 2001 From: Horst Hunger Date: Tue, 3 Jan 2017 09:06:19 +0100 Subject: [PATCH 022/148] Bug#25335897: Modified the year of the date value from 2017 to 2037 in first event. --- mysql-test/r/events_2.result | 4 ++-- mysql-test/t/events_2.test | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/events_2.result b/mysql-test/r/events_2.result index 66ec00d7357..31a501d48a6 100644 --- a/mysql-test/r/events_2.result +++ b/mysql-test/r/events_2.result @@ -1,10 +1,10 @@ drop database if exists events_test; create database events_test; use events_test; -create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; +create event e_26 on schedule at '2037-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion -events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP +events_test e_26 set @a = 5 root@localhost 2037-01-01 00:00:00 DROP drop event e_26; create event e_26 on schedule at NULL disable do set @a = 5; ERROR HY000: Incorrect AT value: 'NULL' diff --git a/mysql-test/t/events_2.test b/mysql-test/t/events_2.test index 3d609654b21..d90ec100e42 100644 --- a/mysql-test/t/events_2.test +++ b/mysql-test/t/events_2.test @@ -13,7 +13,7 @@ use events_test; # mysql.event intact checking end # -create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; +create event e_26 on schedule at '2037-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; drop event e_26; --error ER_WRONG_VALUE From 69bbf9efebf8df4af9cd049b052ef1474660257d Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Fri, 6 Jan 2017 18:15:13 +0530 Subject: [PATCH 023/148] Updated copyright year in user visible text --- README | 2 +- include/welcome_copyright_notice.h | 4 ++-- packaging/WiX/custom_ui.wxs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README b/README index 72cc70bbd16..2a3230ac685 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ For the avoidance of doubt, this particular copy of the software is released under the version 2 of the GNU General Public License. MySQL is brought to you by Oracle. -Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. License information can be found in the COPYING file. diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h index 7b6c28c2f56..0c17b5e650c 100644 --- a/include/welcome_copyright_notice.h +++ b/include/welcome_copyright_notice.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2017, 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 @@ -16,7 +16,7 @@ #ifndef _welcome_copyright_notice_h_ #define _welcome_copyright_notice_h_ -#define COPYRIGHT_NOTICE_CURRENT_YEAR "2016" +#define COPYRIGHT_NOTICE_CURRENT_YEAR "2017" /* This define specifies copyright notice which is displayed by every MySQL diff --git a/packaging/WiX/custom_ui.wxs b/packaging/WiX/custom_ui.wxs index e96ab0fe505..9475de92722 100644 --- a/packaging/WiX/custom_ui.wxs +++ b/packaging/WiX/custom_ui.wxs @@ -2,7 +2,7 @@ xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> + + + + + + + + + + + + + + + + + From 2abc313c3794f2a38e2485ded041a6cca0ad1172 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 9 Mar 2017 12:34:06 +0300 Subject: [PATCH 038/148] Use correct function name in DEBUG_ENTER --- sql/sql_prepare.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6727b2a0182..094677e150d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1988,7 +1988,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt, THD *thd= stmt->thd; LEX *lex= stmt->lex; SQL_HANDLER *ha_table; - DBUG_ENTER("mysql_test_select"); + DBUG_ENTER("mysql_test_handler_read"); lex->select_lex.context.resolve_in_select_list= TRUE; From 060b1eadf4913f7066484ea34ec62feead1bca44 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 10 Mar 2017 01:19:50 +0400 Subject: [PATCH 039/148] BUG#25575605: SETTING --SSL-MODE=REQUIRED SENDS CREDENTIALS BEFORE VERIFYING SSL CONNECTION MYSQL_OPT_SSL_MODE option introduced. It is set in case of --ssl-mode=REQUIRED and permits only SSL connection. (cherry picked from commit 3b2d28578c526f347f5cfe763681eff365731f99) --- client/client_priv.h | 34 +++++++++++++----- client/mysql.cc | 6 ++-- client/mysql_upgrade.c | 6 ++-- client/mysqladmin.cc | 6 ++-- client/mysqlcheck.c | 4 +-- client/mysqldump.c | 4 +-- client/mysqlimport.c | 4 +-- client/mysqlshow.c | 4 +-- client/mysqlslap.c | 5 +-- client/mysqltest.cc | 6 ++-- include/mysql.h | 9 +++-- include/mysql.h.pp | 6 +++- include/sql_common.h | 3 +- include/sslopt-case.h | 4 +-- include/sslopt-vars.h | 6 ++-- mysql-test/r/ssl_mode.result | 6 ++-- mysql-test/r/ssl_mode_no_ssl.result | 22 ++++++------ sql-common/client.c | 54 +++++++++++++++++++++++++++-- 18 files changed, 134 insertions(+), 55 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index e53ced7e790..fb83ce9cc8b 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2017, 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 @@ -115,13 +115,15 @@ enum options_client /** Wrapper for mysql_real_connect() that checks if SSL connection is establised. - The function calls mysql_real_connect() first, then if given ssl_required==TRUE - argument (i.e. --ssl-mode=REQUIRED option used) checks current SSL chiper to - ensure that SSL is used for current connection. - Otherwise it returns NULL and sets errno to CR_SSL_CONNECTION_ERROR. + The function calls mysql_real_connect() first. Then, if the ssl_required + argument is TRUE (i.e., the --ssl-mode=REQUIRED option was specified), it + checks the current SSL cipher to ensure that SSL is used for the current + connection. Otherwise, it returns NULL and sets errno to + CR_SSL_CONNECTION_ERROR. - All clients (except mysqlbinlog which disregards SSL options) use this function - instead of mysql_real_connect() to handle --ssl-mode=REQUIRED option. + All clients (except mysqlbinlog, which disregards SSL options) use this + function instead of mysql_real_connect() to handle the --ssl-mode=REQUIRED + option. */ MYSQL *mysql_connect_ssl_check(MYSQL *mysql_arg, const char *host, const char *user, const char *passwd, @@ -129,8 +131,22 @@ MYSQL *mysql_connect_ssl_check(MYSQL *mysql_arg, const char *host, const char *unix_socket, ulong client_flag, my_bool ssl_required __attribute__((unused))) { - MYSQL *mysql= mysql_real_connect(mysql_arg, host, user, passwd, db, port, - unix_socket, client_flag); + MYSQL *mysql; + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + enum mysql_ssl_mode opt_ssl_mode= SSL_MODE_REQUIRED; + if (ssl_required && + mysql_options(mysql_arg, MYSQL_OPT_SSL_MODE, (char *) &opt_ssl_mode)) + { + NET *net= &mysql_arg->net; + net->last_errno= CR_SSL_CONNECTION_ERROR; + strmov(net->last_error, "Client library doesn't support MYSQL_SSL_REQUIRED option"); + strmov(net->sqlstate, "HY000"); + return NULL; + } +#endif + mysql= mysql_real_connect(mysql_arg, host, user, passwd, db, port, + unix_socket, client_flag); #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) if (mysql && /* connection established. */ ssl_required && /* --ssl-mode=REQUIRED. */ diff --git a/client/mysql.cc b/client/mysql.cc index cdc2ab0d6e0..2269563814c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, 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 @@ -1318,7 +1318,7 @@ sig_handler handle_sigint(int sig) kill_mysql= mysql_init(kill_mysql); if (!mysql_connect_ssl_check(kill_mysql, current_host, current_user, opt_password, "", opt_mysql_port, opt_mysql_unix_port, 0, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); goto err; @@ -4461,7 +4461,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, if (!mysql_connect_ssl_check(&mysql, host, user, password, database, opt_mysql_port, opt_mysql_unix_port, connect_flag | CLIENT_MULTI_STATEMENTS, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { if (!silent || (mysql_errno(&mysql) != CR_CONN_HOST_ERROR && diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 507df6f7843..be0af089027 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2006, 2017, 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 @@ -387,9 +387,11 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...) va_end(args); +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) /* If given --ssl-mode=REQUIRED propagate it to the tool. */ - if (opt_ssl_required) + if (opt_ssl_mode == SSL_MODE_REQUIRED) dynstr_append(&ds_cmdline, "--ssl-mode=REQUIRED"); +#endif #ifdef __WIN__ dynstr_append(&ds_cmdline, "\""); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index c03b37ab165..ae9db85b917 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, 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 @@ -519,8 +519,8 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) for (;;) { if (mysql_connect_ssl_check(mysql, host, user, opt_password, NullS, - tcp_port, unix_port, - CLIENT_REMEMBER_OPTIONS, opt_ssl_required)) + tcp_port, unix_port, CLIENT_REMEMBER_OPTIONS, + opt_ssl_mode == SSL_MODE_REQUIRED)) { mysql->reconnect= 1; if (info) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 55b941e7f1a..7822460e341 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2017, 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 @@ -907,7 +907,7 @@ static int dbConnect(char *host, char *user, char *passwd) if (!(sock = mysql_connect_ssl_check(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0, - opt_ssl_required))) + opt_ssl_mode == SSL_MODE_REQUIRED))) { DBerror(&mysql_connection, "when trying to connect"); return 1; diff --git a/client/mysqldump.c b/client/mysqldump.c index 00265def489..fcd29e26fe3 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, 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 @@ -1501,7 +1501,7 @@ static int connect_to_db(char *host, char *user,char *passwd) if (!(mysql= mysql_connect_ssl_check(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0, - opt_ssl_required))) + opt_ssl_mode == SSL_MODE_REQUIRED))) { DB_error(&mysql_connection, "when trying to connect"); DBUG_RETURN(1); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 5841c0b855a..bab43356bc7 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, 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 @@ -463,7 +463,7 @@ static MYSQL *db_connect(char *host, char *database, mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (!(mysql_connect_ssl_check(mysql, host, user, passwd, database, opt_mysql_port, opt_mysql_unix_port, - 0, opt_ssl_required))) + 0, opt_ssl_mode == SSL_MODE_REQUIRED))) { ignore_errors=0; /* NO RETURN FROM db_error */ db_error(mysql); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index d0390ec443b..bd7a37f93b4 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, 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 @@ -142,7 +142,7 @@ int main(int argc, char **argv) if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password, (first_argument_uses_wildcards) ? "" : argv[0], opt_mysql_port, opt_mysql_unix_port, - 0, opt_ssl_required))) + 0, opt_ssl_mode == SSL_MODE_REQUIRED))) { fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); exit(1); diff --git a/client/mysqlslap.c b/client/mysqlslap.c index eb2b577948c..aa312339e87 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2017, 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 @@ -357,7 +357,8 @@ int main(int argc, char **argv) { if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password, NULL, opt_mysql_port, opt_mysql_unix_port, - connect_flags, opt_ssl_required))) + connect_flags, + opt_ssl_mode == SSL_MODE_REQUIRED))) { fprintf(stderr,"%s: Error when connecting to server: %s\n", my_progname,mysql_error(&mysql)); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 79d448cf811..e5f9b11fe76 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, 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 @@ -5283,7 +5283,7 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, host, port, sock, user, name, failed_attempts); while(!mysql_connect_ssl_check(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { /* Connect failed @@ -5385,7 +5385,7 @@ int connect_n_handle_errors(struct st_command *command, while (!mysql_connect_ssl_check(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS, - opt_ssl_required)) + opt_ssl_mode == SSL_MODE_REQUIRED)) { /* If we have used up all our connections check whether this diff --git a/include/mysql.h b/include/mysql.h index da29cb342cc..7ebf2f725a2 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, 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 @@ -167,7 +167,7 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN + MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE }; /** @@ -224,6 +224,11 @@ enum mysql_protocol_type MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY }; +enum mysql_ssl_mode +{ + SSL_MODE_REQUIRED= 3 +}; + typedef struct character_set { unsigned int number; /* character set number */ diff --git a/include/mysql.h.pp b/include/mysql.h.pp index c2c5ba35044..0f292d921ee 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -263,7 +263,7 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN + MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE }; struct st_mysql_options_extention; struct st_mysql_options { @@ -307,6 +307,10 @@ enum mysql_protocol_type MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY }; +enum mysql_ssl_mode +{ + SSL_MODE_REQUIRED= 3 +}; typedef struct character_set { unsigned int number; diff --git a/include/sql_common.h b/include/sql_common.h index a2ea3ac45e7..05bbb5a4f53 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -1,7 +1,7 @@ #ifndef SQL_COMMON_INCLUDED #define SQL_COMMON_INCLUDED -/* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2003, 2017, 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 @@ -32,6 +32,7 @@ struct st_mysql_options_extention { char *plugin_dir; char *default_auth; my_bool enable_cleartext_plugin; + unsigned int ssl_mode; }; typedef struct st_mysql_methods diff --git a/include/sslopt-case.h b/include/sslopt-case.h index 57702b3b352..0fddafc4fa9 100644 --- a/include/sslopt-case.h +++ b/include/sslopt-case.h @@ -1,7 +1,7 @@ #ifndef SSLOPT_CASE_INCLUDED #define SSLOPT_CASE_INCLUDED -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, 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 @@ -38,7 +38,7 @@ exit(1); } else - opt_ssl_required= 1; + opt_ssl_mode= SSL_MODE_REQUIRED; break; #endif /* MYSQL_CLIENT */ #endif diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index 6c9bd4296ef..a037538f693 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -1,7 +1,7 @@ #ifndef SSLOPT_VARS_INCLUDED #define SSLOPT_VARS_INCLUDED -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, 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 @@ -31,11 +31,11 @@ SSL_STATIC char *opt_ssl_key = 0; #ifdef MYSQL_CLIENT SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; -SSL_STATIC my_bool opt_ssl_required= 0; +SSL_STATIC uint opt_ssl_mode= 0; #endif /* MYSQL_CLIENT */ #else /* HAVE_OPENSSL */ -#define opt_ssl_required 0 +#define opt_ssl_mode 0 #endif /* HAVE_OPENSSL */ #endif /* SSLOPT_VARS_INCLUDED */ diff --git a/mysql-test/r/ssl_mode.result b/mysql-test/r/ssl_mode.result index 38fc4e1dca2..c02a50bdcbd 100644 --- a/mysql-test/r/ssl_mode.result +++ b/mysql-test/r/ssl_mode.result @@ -37,8 +37,8 @@ DROP TABLE t1; # mysql Unknown value to --ssl-mode: ''. Use --ssl-mode=REQUIRED Unknown value to --ssl-mode: 'DERIUQER'. Use --ssl-mode=REQUIRED -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL +ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL +ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL End of tests diff --git a/mysql-test/r/ssl_mode_no_ssl.result b/mysql-test/r/ssl_mode_no_ssl.result index 409b7a0fa1b..831bb3b71ab 100644 --- a/mysql-test/r/ssl_mode_no_ssl.result +++ b/mysql-test/r/ssl_mode_no_ssl.result @@ -1,22 +1,22 @@ # negative client tests # mysql -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections -ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL +ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL # mysqldump -mysqldump: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect +mysqldump: Got error: 2026: SSL connection error: Server doesn't support SSL when trying to connect # mysqladmin -mysqladmin: error: '--ssl-mode=REQUIRED option forbids non SSL connections' +mysqladmin: error: 'SSL connection error: Server doesn't support SSL' # mysqlcheck -mysqlcheck: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect +mysqlcheck: Got error: 2026: SSL connection error: Server doesn't support SSL when trying to connect # mysqlimport -mysqlimport: Error: 2026 --ssl-mode=REQUIRED option forbids non SSL connections +mysqlimport: Error: 2026 SSL connection error: Server doesn't support SSL # mysqlshow -mysqlshow: --ssl-mode=REQUIRED option forbids non SSL connections +mysqlshow: SSL connection error: Server doesn't support SSL # mysqlslap -mysqlslap: Error when connecting to server: --ssl-mode=REQUIRED option forbids non SSL connections +mysqlslap: Error when connecting to server: SSL connection error: Server doesn't support SSL # mysqltest -mysqltest: Could not open connection 'default': 2026 --ssl-mode=REQUIRED option forbids non SSL connections +mysqltest: Could not open connection 'default': 2026 SSL connection error: Server doesn't support SSL End of tests diff --git a/sql-common/client.c b/sql-common/client.c index 3a6e205d384..759d95117cb 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1137,7 +1137,7 @@ static const char *default_options[]= "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", "multi-results", "multi-statements", "multi-queries", "secure-auth", "report-data-truncation", "plugin-dir", "default-auth", - "enable-cleartext-plugin", + "enable-cleartext-plugin", "ssl-mode", NullS }; enum option_id { @@ -1149,7 +1149,7 @@ enum option_id { OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name, OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth, OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth, - OPT_enable_cleartext_plugin, + OPT_enable_cleartext_plugin, OPT_ssl_mode, OPT_keep_this_one_last }; @@ -1338,12 +1338,26 @@ void mysql_read_default_options(struct st_mysql_options *options, my_free(options->ssl_cipher); options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME)); break; + case OPT_ssl_mode: + if (opt_arg && + !my_strcasecmp(&my_charset_latin1, opt_arg, "required")) + { + ENSURE_EXTENSIONS_PRESENT(options); + options->extension->ssl_mode= SSL_MODE_REQUIRED; + } + else + { + fprintf(stderr, "Unknown option to ssl-mode: %s\n", opt_arg); + exit(1); + } + break; #else case OPT_ssl_key: case OPT_ssl_cert: case OPT_ssl_ca: case OPT_ssl_capath: case OPT_ssl_cipher: + case OPT_ssl_mode: break; #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ case OPT_character_sets_dir: @@ -1850,6 +1864,10 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) mysql->options.ssl_capath = 0; mysql->options.ssl_cipher= 0; mysql->options.use_ssl = FALSE; + if (mysql->options.extension) + { + mysql->options.extension->ssl_mode= 0; + } mysql->connector_fd = 0; DBUG_VOID_RETURN; } @@ -2596,6 +2614,31 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, end= buff+5; } #ifdef HAVE_OPENSSL + /* + If SSL connection is required we'll: + 1. check if the server supports SSL; + 2. check if the client is properly configured; + 3. try to use SSL no matter the other options given. + */ + if (mysql->options.extension && + mysql->options.extension->ssl_mode == SSL_MODE_REQUIRED) + { + if (!(mysql->server_capabilities & CLIENT_SSL)) + { + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), + "Server doesn't support SSL"); + goto error; + } + if (!mysql->options.use_ssl) + { + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), + "Client is not configured to use SSL"); + goto error; + } + mysql->client_flag|= CLIENT_SSL; + } if (mysql->client_flag & CLIENT_SSL) { /* Do the SSL layering. */ @@ -4242,6 +4285,13 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) mysql->options.extension->enable_cleartext_plugin= (*(my_bool*) arg) ? TRUE : FALSE; break; + case MYSQL_OPT_SSL_MODE: + if (*(uint *) arg == SSL_MODE_REQUIRED) + { + ENSURE_EXTENSIONS_PRESENT(&mysql->options); + mysql->options.extension->ssl_mode= SSL_MODE_REQUIRED; + } + break; default: DBUG_RETURN(1); } From 5bc538dd8548e669480c91b7510ef914c442d1f0 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 11 Mar 2017 19:35:03 +0100 Subject: [PATCH 040/148] Commit the 2 last commits merged from 10.1 --- storage/connect/ha_connect.cc | 4 +- storage/connect/myconn.cpp | 37 +- storage/connect/myutil.cpp | 13 +- storage/connect/tabmul.cpp | 638 ++++++++++++++++++++-------------- storage/connect/tabmul.h | 58 +++- 5 files changed, 457 insertions(+), 293 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 930e7604fbd..2cd581c5c64 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -172,7 +172,7 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.05.0003 February 27, 2017"; + char version[]= "Version 1.05.0003 March 7, 2017"; #if defined(__WIN__) char compver[]= "Version 1.05.0003 " __DATE__ " " __TIME__; char slash= '\\'; @@ -509,7 +509,7 @@ ha_create_table_option connect_table_option_list[]= HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("BLOCK_SIZE", elements, 0, 0, INT_MAX32, 1), //HA_TOPTION_NUMBER("ESTIMATE", estimate, 0, 0, INT_MAX32, 1), - HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 2, 1), + HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 3, 1), HA_TOPTION_NUMBER("HEADER", header, 0, 0, 3, 1), HA_TOPTION_NUMBER("QUOTED", quoted, (ulonglong) -1, 0, 3, 1), HA_TOPTION_NUMBER("ENDING", ending, (ulonglong) -1, 0, INT_MAX32, 1), diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index d05254a32a6..f7cd245df59 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -135,10 +135,12 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db, FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM, FLD_NO, FLD_DEFAULT, FLD_EXTRA, FLD_CHARSET}; - unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0}; - char *fld, *colname, *chset, *fmt, v, buf[128], uns[16], zero[16]; + //unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0}; + unsigned int length[] = {0, 4, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0}; + char *fld, *colname, *chset, *fmt, v, buf[128], uns[16], zero[16]; int i, n, nf, ncol = sizeof(buftyp) / sizeof(int); int len, type, prec, rc, k = 0; + bool b; PQRYRES qrp; PCOLRES crp; MYSQLC myc; @@ -157,7 +159,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db, /* Do an evaluation of the result size. */ /********************************************************************/ STRING cmd(g, 64, "SHOW FULL COLUMNS FROM "); - bool b = cmd.Append((PSZ)table); + b = cmd.Append((PSZ)table); b |= cmd.Append(" FROM "); b |= cmd.Append((PSZ)(db ? db : PlgGetUser(g)->DBName)); @@ -232,11 +234,31 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db, fld = myc.GetCharField(1); prec = 0; len = 0; - v = (chset && !strcmp(chset, "binary")) ? 'B' : 0; +// v = (chset && !strcmp(chset, "binary")) ? 'B' : 0; + v = 0; *uns = 0; *zero = 0; + b = false; - switch ((nf = sscanf(fld, "%[^(](%d,%d", buf, &len, &prec))) { + if (!strnicmp(fld, "enum", 4)) { + char *p2, *p1 = fld + 6; // to skip enum(' + + while (true) { + p2 = strchr(p1, '\''); + len = MY_MAX(len, p2 - p1); + if (*++p2 != ',') break; + p1 = p2 + 2; + } // endwhile + + v = (len > 255) ? 'V' : 0; + strcpy(buf, "enum"); + b = true; + } else if (!strnicmp(fld, "set", 3)) { + len = (int)strlen(fld) - 2; + v = 'V'; + strcpy(buf, "set"); + b = true; + } else switch ((nf = sscanf(fld, "%[^(](%d,%d", buf, &len, &prec))) { case 3: nf = sscanf(fld, "%[^(](%d,%d) %s %s", buf, &len, &prec, uns, zero); break; @@ -271,7 +293,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db, colname, len); PushWarning(g, thd); v = 'V'; - } else + } else len = MY_MIN(len, 4096); } // endif type @@ -286,6 +308,9 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db, default: crp->Nulls[i] = v; break; } // endswitch nf + if (b) // enum or set + nf = sscanf(fld, "%s ", buf); // get values + crp = crp->Next; // Type_Name crp->Kdata->SetValue(buf, i); diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp index d4416e188c8..5fcc914f632 100644 --- a/storage/connect/myutil.cpp +++ b/storage/connect/myutil.cpp @@ -42,7 +42,8 @@ int MYSQLtoPLG(char *typname, char *var) type = TYPE_INT; else if (!stricmp(typname, "smallint")) type = TYPE_SHORT; - else if (!stricmp(typname, "char") || !stricmp(typname, "varchar")) + else if (!stricmp(typname, "char") || !stricmp(typname, "varchar") || + !stricmp(typname, "enum") || !stricmp(typname, "set")) type = TYPE_STRING; else if (!stricmp(typname, "double") || !stricmp(typname, "float") || !stricmp(typname, "real")) @@ -87,10 +88,12 @@ int MYSQLtoPLG(char *typname, char *var) else if (!stricmp(typname, "year")) *var = 'Y'; - } else if (type == TYPE_STRING && !stricmp(typname, "varchar")) - // This is to make the difference between CHAR and VARCHAR - *var = 'V'; - else if (type == TYPE_ERROR && xconv == TPC_SKIP) + } else if (type == TYPE_STRING) { + if (!stricmp(typname, "varchar")) + // This is to make the difference between CHAR and VARCHAR + *var = 'V'; + + } else if (type == TYPE_ERROR && xconv == TPC_SKIP) *var = 'K'; else *var = 0; diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp index 8f1e6f3819d..4128fea6afc 100644 --- a/storage/connect/tabmul.cpp +++ b/storage/connect/tabmul.cpp @@ -1,7 +1,7 @@ /************* TabMul C++ Program Source Code File (.CPP) **************/ /* PROGRAM NAME: TABMUL */ /* ------------- */ -/* Version 1.8 */ +/* Version 1.9 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -44,6 +44,11 @@ #define __MFC_COMPAT__ // To define min/max as macro #endif //#include +#if defined(PATHMATCHSPEC) +#include "Shlwapi.h" +//using namespace std; +#pragma comment(lib,"shlwapi.lib") +#endif // PATHMATCHSPEC #else #if defined(UNIX) #include @@ -124,9 +129,10 @@ bool TDBMUL::InitFileNames(PGLOBAL g) { #define PFNZ 4096 #define FNSZ (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT) - char *pfn[PFNZ]; - char *filename; - int rc, n = 0; + PTDBDIR dirp; + PSZ pfn[PFNZ]; + PSZ filename; + int rc, n = 0; if (trace) htrc("in InitFileName: fn[]=%d\n", FNSZ); @@ -141,115 +147,39 @@ bool TDBMUL::InitFileNames(PGLOBAL g) if (trace) htrc("InitFileName: fn='%s'\n", filename); - if (Mul == 1) { + if (Mul != 2) { /*******************************************************************/ /* To_File is a multiple name with special characters */ /*******************************************************************/ + if (Mul == 1) + dirp = new(g) TDBDIR(PlugDup(g, filename)); + else // Mul == 3 (Subdir) + dirp = new(g) TDBSDR(PlugDup(g, filename)); + + if (dirp->OpenDB(g)) + return true; + + if (trace && Mul == 3) { + int nf = ((PTDBSDR)dirp)->FindInDir(g); + htrc("Number of files = %d\n", nf); + } // endif trace + + while (true) + if ((rc = dirp->ReadDB(g)) == RC_OK) { #if defined(__WIN__) - char drive[_MAX_DRIVE], direc[_MAX_DIR]; - WIN32_FIND_DATA FileData; - HANDLE hSearch; - - _splitpath(filename, drive, direc, NULL, NULL); - - // Start searching files in the target directory. - hSearch = FindFirstFile(filename, &FileData); - - if (hSearch == INVALID_HANDLE_VALUE) { - rc = GetLastError(); - - if (rc != ERROR_FILE_NOT_FOUND) { - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), 0, - (LPTSTR)&filename, sizeof(filename), NULL); - sprintf(g->Message, MSG(BAD_FILE_HANDLE), filename); - return true; - } // endif rc - - goto suite; - } // endif hSearch - - while (n < PFNZ) { - if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName); - pfn[n++] = PlugDup(g, filename); - } // endif dwFileAttributes - - if (!FindNextFile(hSearch, &FileData)) { - rc = GetLastError(); - - if (rc != ERROR_NO_MORE_FILES) { - sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc); - FindClose(hSearch); - return true; - } // endif rc - - break; - } // endif FindNextFile - - } // endwhile n - - // Close the search handle. - if (!FindClose(hSearch)) { - strcpy(g->Message, MSG(SRCH_CLOSE_ERR)); - return true; - } // endif FindClose - + strcat(strcpy(filename, dirp->Drive), dirp->Direc); #else // !__WIN__ - struct stat fileinfo; - char fn[FN_REFLEN], direc[FN_REFLEN], pattern[FN_HEADLEN], ftype[FN_EXTLEN]; - DIR *dir; - struct dirent *entry; - - _splitpath(filename, NULL, direc, pattern, ftype); - strcat(pattern, ftype); - - if (trace) - htrc("direc=%s pattern=%s ftype=%s\n", direc, pattern, ftype); - - // Start searching files in the target directory. - if (!(dir = opendir(direc))) { - sprintf(g->Message, MSG(BAD_DIRECTORY), direc, strerror(errno)); - - if (trace) - htrc("%s\n", g->Message); - - return true; - } // endif dir - - if (trace) - htrc("dir opened: reading files\n"); - - while ((entry = readdir(dir)) && n < PFNZ) { - strcat(strcpy(fn, direc), entry->d_name); - - if (trace) - htrc("%s read\n", fn); - - if (lstat(fn, &fileinfo) < 0) { - sprintf(g->Message, "%s: %s", fn, strerror(errno)); - return true; - } else if (!S_ISREG(fileinfo.st_mode)) - continue; // Not a regular file (should test for links) - - /*******************************************************************/ - /* Test whether the file name matches the table name filter. */ - /*******************************************************************/ - if (fnmatch(pattern, entry->d_name, 0)) - continue; // Not a match - - strcat(strcpy(filename, direc), entry->d_name); - pfn[n++] = PlugDup(g, filename); - - if (trace) - htrc("Adding pfn[%d] %s\n", n, filename); - - } // endwhile readdir - - // Close the dir handle. - closedir(dir); + strcpy(filename, dirp->Direc); #endif // !__WIN__ + strcat(strcat(filename, dirp->Fname), dirp->Ftype); + pfn[n++] = PlugDup(g, filename); + } else + break; + + dirp->CloseDB(g); + + if (rc == RC_FX) + return true; } else { /*******************************************************************/ @@ -297,10 +227,6 @@ bool TDBMUL::InitFileNames(PGLOBAL g) } // endif Mul -#if defined(__WIN__) - suite: -#endif - if (n) { Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*)); @@ -581,7 +507,95 @@ void TDBMUL::CloseDB(PGLOBAL g) } // end of CloseDB -/* --------------------------- Class DIRDEF -------------------------- */ +#if 0 +/* ------------------------- Class TDBMSD ---------------------------- */ + + // Method +PTDB TDBMSD::Clone(PTABS t) +{ + PTDBMSD tp; + PGLOBAL g = t->G; // Is this really useful ??? + + tp = new(g) TDBMSD(this); + tp->Tdbp = Tdbp->Clone(t); + tp->Columns = tp->Tdbp->GetColumns(); + return tp; +} // end of Clone + +PTDB TDBMSD::Duplicate(PGLOBAL g) +{ + PTDBMSD tmup = new(g) TDBMSD(this); + + tmup->Tdbp = Tdbp->Duplicate(g); + return tmup; +} // end of Duplicate + +/***********************************************************************/ +/* Initializes the table filename list. */ +/* Note: tables created by concatenating the file components without */ +/* specifying the LRECL value (that should be restricted to _MAX_PATH)*/ +/* have a LRECL that is the sum of the lengths of all components. */ +/* This is why we use a big filename array to take care of that. */ +/***********************************************************************/ +bool TDBMSD::InitFileNames(PGLOBAL g) +{ +#define PFNZ 4096 +#define FNSZ (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT) + PTDBSDR dirp; + PSZ pfn[PFNZ]; + PSZ filename; + int rc, n = 0; + + if (trace) + htrc("in InitFileName: fn[]=%d\n", FNSZ); + + filename = (char*)PlugSubAlloc(g, NULL, FNSZ); + + // The sub table may need to refer to the Table original block + Tdbp->SetTable(To_Table); // Was not set at construction + + PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath()); + + if (trace) + htrc("InitFileName: fn='%s'\n", filename); + + dirp = new(g) TDBSDR(filename); + + if (dirp->OpenDB(g)) + return true; + + while (true) + if ((rc = dirp->ReadDB(g)) == RC_OK) { +#if defined(__WIN__) + strcat(strcpy(filename, dirp->Drive), dirp->Direc); +#else // !__WIN__ + strcpy(filename, dirp->Direc); +#endif // !__WIN__ + strcat(strcat(filename, dirp->Fname), dirp->Ftype); + pfn[n++] = PlugDup(g, filename); + } else + break; + + if (rc == RC_FX) + return true; + + if (n) { + Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*)); + + for (int i = 0; i < n; i++) + Filenames[i] = pfn[i]; + + } else { + Filenames = (char**)PlugSubAlloc(g, NULL, sizeof(char*)); + Filenames[0] = NULL; + } // endif n + + NumFiles = n; + return false; +} // end of InitFileNames +#endif // 0 + + /* --------------------------- Class DIRDEF -------------------------- */ /***********************************************************************/ /* DefineAM: define specific AM block values from XDB file. */ @@ -616,57 +630,38 @@ PTDB DIRDEF::GetTable(PGLOBAL g, MODE) /***********************************************************************/ /* TABDIR constructors. */ /***********************************************************************/ +void TDBDIR::Init(void) +{ + iFile = 0; +#if defined(__WIN__) + Dvalp = NULL; + memset(&FileData, 0, sizeof(_finddata_t)); + hSearch = INVALID_HANDLE_VALUE; + *Drive = '\0'; +#else // !__WIN__ + memset(&Fileinfo, 0, sizeof(struct stat)); + Entry = NULL; + Dir = NULL; + Done = false; + *Pattern = '\0'; +#endif // !__WIN__ + *Fpath = '\0'; + *Direc = '\0'; + *Fname = '\0'; + *Ftype = '\0'; +} // end of Init + TDBDIR::TDBDIR(PDIRDEF tdp) : TDBASE(tdp) - { +{ To_File = tdp->Fn; - iFile = 0; -#if defined(__WIN__) - memset(&FileData, 0, sizeof(_finddata_t)); - Hsearch = -1; - *Drive = '\0'; -#else // !__WIN__ - memset(&Fileinfo, 0, sizeof(struct stat)); - Entry = NULL; - Dir = NULL; - Done = false; - *Pattern = '\0'; -#endif // !__WIN__ - *Fpath = '\0'; - *Direc = '\0'; - *Fname = '\0'; - *Ftype = '\0'; - } // end of TDBDIR standard constructor + Init(); +} // end of TDBDIR standard constructor -TDBDIR::TDBDIR(PTDBDIR tdbp) : TDBASE(tdbp) - { - To_File = tdbp->To_File; - iFile = tdbp->iFile; -#if defined(__WIN__) - FileData = tdbp->FileData; - Hsearch = tdbp->Hsearch; - strcpy(Drive, tdbp->Drive); -#else // !__WIN__ - Fileinfo = tdbp->Fileinfo; - Entry = tdbp->Entry; - Dir = tdbp->Dir; - Done = tdbp->Done; - strcpy(Pattern, tdbp->Pattern); -#endif // !__WIN__ - strcpy(Direc, tdbp->Direc); - strcpy(Fname, tdbp->Fname); - strcpy(Ftype, tdbp->Ftype); - } // end of TDBDIR copy constructor - -// Method -PTDB TDBDIR::Clone(PTABS t) - { - PTDB tp; - PGLOBAL g = t->G; // Is this really useful ??? - - tp = new(g) TDBDIR(this); - tp->SetColumns(Columns); - return tp; - } // end of Clone +TDBDIR::TDBDIR(PSZ fpat) : TDBASE((PTABDEF)NULL) +{ + To_File = fpat; + Init(); +} // end of TDBDIR constructor /***********************************************************************/ /* Initialize/get the components of the search file pattern. */ @@ -674,18 +669,19 @@ PTDB TDBDIR::Clone(PTABS t) char* TDBDIR::Path(PGLOBAL g) { PCATLG cat = PlgGetCatalog(g); + PTABDEF defp = (PTABDEF)To_Def; #if defined(__WIN__) if (!*Drive) { - PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath()); + PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL); _splitpath(Fpath, Drive, Direc, Fname, Ftype); } else - _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull ??? + _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull for TDBSDR return Fpath; #else // !__WIN__ if (!Done) { - PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath()); + PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL); _splitpath(Fpath, NULL, Direc, Fname, Ftype); strcat(strcpy(Pattern, Fname), Ftype); Done = true; @@ -709,23 +705,48 @@ PCOL TDBDIR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) int TDBDIR::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { - int n = -1; + int rc, n = -1; #if defined(__WIN__) - int h; // Start searching files in the target directory. - h = _findfirst(Path(g), &FileData); + hSearch = FindFirstFile(Path(g), &FileData); - if (h != -1) { - for (n = 1;; n++) - if (_findnext(h, &FileData)) - break; + if (hSearch == INVALID_HANDLE_VALUE) { + rc = GetLastError(); - // Close the search handle. - _findclose(h); - } else - n = 0; + if (rc != ERROR_FILE_NOT_FOUND) { + char buf[512]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL); + sprintf(g->Message, MSG(BAD_FILE_HANDLE), buf); + return -1; + } // endif rc + + return 0; + } // endif hSearch + + while (true) { + if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + n++; + + if (!FindNextFile(hSearch, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc); + FindClose(hSearch); + return -1; + } // endif rc + + break; + } // endif Next + + } // endwhile + + // Close the search handle. + FindClose(hSearch); #else // !__WIN__ Path(g); @@ -791,30 +812,30 @@ int TDBDIR::ReadDB(PGLOBAL g) int rc = RC_OK; #if defined(__WIN__) - if (Hsearch == -1) { + if (hSearch == INVALID_HANDLE_VALUE) { /*******************************************************************/ /* Start searching files in the target directory. The use of the */ /* Path function is required when called from TDBSDR. */ /*******************************************************************/ - Hsearch = _findfirst(Path(g), &FileData); + hSearch = FindFirstFile(Path(g), &FileData); - if (Hsearch == -1) + if (hSearch == INVALID_HANDLE_VALUE) rc = RC_EF; else iFile++; } else { - if (_findnext(Hsearch, &FileData)) { + if (!FindNextFile(hSearch, &FileData)) { // Restore file name and type pattern _splitpath(To_File, NULL, NULL, Fname, Ftype); rc = RC_EF; } else iFile++; - } // endif Hsearch + } // endif hSearch if (rc == RC_OK) - _splitpath(FileData.name, NULL, NULL, Fname, Ftype); + _splitpath(FileData.cFileName, NULL, NULL, Fname, Ftype); #else // !Win32 rc = RC_NF; @@ -878,8 +899,8 @@ void TDBDIR::CloseDB(PGLOBAL) { #if defined(__WIN__) // Close the search handle. - _findclose(Hsearch); - Hsearch = -1; + FindClose(hSearch); + hSearch = INVALID_HANDLE_VALUE; #else // !__WIN__ // Close the DIR handle if (Dir) { @@ -907,6 +928,7 @@ DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ) } // endif cprec // Set additional DIR access method information for column. + Tdbp = (PTDBDIR)tdbp; N = cdp->GetOffset(); } // end of DIRCOL constructor @@ -916,45 +938,73 @@ DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ) /***********************************************************************/ DIRCOL::DIRCOL(DIRCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) { - N = col1->N; + Tdbp = (PTDBDIR)tdbp; + N = col1->N; } // end of DIRCOL copy constructor +#if defined(__WIN__) +/***********************************************************************/ +/* Retrieve time information from FileData. */ +/***********************************************************************/ +void DIRCOL::SetTimeValue(PGLOBAL g, FILETIME& ftime) +{ + char tsp[24]; + SYSTEMTIME stp; + + if (FileTimeToSystemTime(&ftime, &stp)) { + sprintf(tsp, "%04d-%02d-%02d %02d:%02d:%02d", + stp.wYear, stp.wMonth, stp.wDay, stp.wHour, stp.wMinute, stp.wSecond); + + if (Value->GetType() != TYPE_STRING) { + if (!Tdbp->Dvalp) + Tdbp->Dvalp = AllocateValue(g, TYPE_DATE, 20, 0, false, + "YYYY-MM-DD hh:mm:ss"); + + Tdbp->Dvalp->SetValue_psz(tsp); + Value->SetValue_pval(Tdbp->Dvalp); + } else + Value->SetValue_psz(tsp); + + } else + Value->Reset(); + +} // end of SetTimeValue +#endif // __WIN__ + /***********************************************************************/ /* ReadColumn: what this routine does is to access the information */ /* corresponding to this column and convert it to buffer type. */ /***********************************************************************/ void DIRCOL::ReadColumn(PGLOBAL g) - { - PTDBDIR tdbp = (PTDBDIR)To_Tdb; - + { if (trace) htrc("DIR ReadColumn: col %s R%d use=%.4X status=%.4X type=%d N=%d\n", - Name, tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N); + Name, Tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N); /*********************************************************************/ /* Retrieve the information corresponding to the column number. */ /*********************************************************************/ switch (N) { #if defined(__WIN__) - case 0: Value->SetValue_psz(tdbp->Drive); break; + case 0: Value->SetValue_psz(Tdbp->Drive); break; #endif // __WIN__ - case 1: Value->SetValue_psz(tdbp->Direc); break; - case 2: Value->SetValue_psz(tdbp->Fname); break; - case 3: Value->SetValue_psz(tdbp->Ftype); break; + case 1: Value->SetValue_psz(Tdbp->Direc); break; + case 2: Value->SetValue_psz(Tdbp->Fname); break; + case 3: Value->SetValue_psz(Tdbp->Ftype); break; #if defined(__WIN__) - case 4: Value->SetValue((int)tdbp->FileData.attrib); break; - case 5: Value->SetValue((int)tdbp->FileData.size); break; - case 6: Value->SetValue((int)tdbp->FileData.time_write); break; - case 7: Value->SetValue((int)tdbp->FileData.time_create); break; - case 8: Value->SetValue((int)tdbp->FileData.time_access); break; + case 4: Value->SetValue((int)Tdbp->FileData.dwFileAttributes); break; + case 5: Value->SetValue((int)Tdbp->FileData.nFileSizeLow); break; + case 6: SetTimeValue(g, Tdbp->FileData.ftLastWriteTime); break; + case 7: SetTimeValue(g, Tdbp->FileData.ftCreationTime); break; + case 8: SetTimeValue(g, Tdbp->FileData.ftLastAccessTime); break; #else // !__WIN__ - case 4: Value->SetValue((int)tdbp->Fileinfo.st_mode); break; - case 5: Value->SetValue((int)tdbp->Fileinfo.st_size); break; - case 6: Value->SetValue((int)tdbp->Fileinfo.st_mtime); break; - case 7: Value->SetValue((int)tdbp->Fileinfo.st_ctime); break; - case 8: Value->SetValue((int)tdbp->Fileinfo.st_atime); break; - case 9: Value->SetValue((int)tdbp->Fileinfo.st_uid); break; - case 10: Value->SetValue((int)tdbp->Fileinfo.st_gid); break; + case 4: Value->SetValue((int)Tdbp->Fileinfo.st_mode); break; + case 5: Value->SetValue((int)Tdbp->Fileinfo.st_size); break; + case 6: Value->SetValue((int)Tdbp->Fileinfo.st_mtime); break; + case 7: Value->SetValue((int)Tdbp->Fileinfo.st_ctime); break; + case 8: Value->SetValue((int)Tdbp->Fileinfo.st_atime); break; + case 9: Value->SetValue((int)Tdbp->Fileinfo.st_uid); break; + case 10: Value->SetValue((int)Tdbp->Fileinfo.st_gid); break; #endif // !__WIN__ default: sprintf(g->Message, MSG(INV_DIRCOL_OFST), N); @@ -969,25 +1019,6 @@ void DIRCOL::ReadColumn(PGLOBAL g) /* ------------------------- Class TDBSDR ---------------------------- */ -/***********************************************************************/ -/* TABSDR copy constructors. */ -/***********************************************************************/ -TDBSDR::TDBSDR(PTDBSDR tdbp) : TDBDIR(tdbp) - { - Sub = tdbp->Sub; - } // end of TDBSDR copy constructor - -// Method -PTDB TDBSDR::Clone(PTABS t) - { - PTDB tp; - PGLOBAL g = t->G; // Is this really useful ??? - - tp = new(g) TDBSDR(this); - tp->SetColumns(Columns); - return tp; - } // end of Clone - /***********************************************************************/ /* SDR GetMaxSize: returns the number of retrieved files. */ /***********************************************************************/ @@ -1002,47 +1033,124 @@ int TDBSDR::GetMaxSize(PGLOBAL g) } // end of GetMaxSize /***********************************************************************/ -/* SDR GetMaxSize: returns the number of retrieved files. */ +/* SDR FindInDir: returns the number of retrieved files. */ /***********************************************************************/ int TDBSDR::FindInDir(PGLOBAL g) { - int n = 0; + int rc, n = 0; size_t m = strlen(Direc); // Start searching files in the target directory. #if defined(__WIN__) - int h = _findfirst(Path(g), &FileData); + HANDLE h; - if (h != -1) { - for (n = 1;; n++) - if (_findnext(h, &FileData)) - break; +#if defined(PATHMATCHSPEC) + if (!*Drive) + Path(g); - // Close the search handle. - _findclose(h); - } // endif h + _makepath(Fpath, Drive, Direc, "*", "*"); - // Now search files in sub-directories. - _makepath(Fpath, Drive, Direc, "*", ""); - h = _findfirst(Fpath, &FileData); + h = FindFirstFile(Fpath, &FileData); - if (h != -1) { - while (true) { - if (FileData.attrib & _A_SUBDIR && *FileData.name != '.') { - // Look in the name sub-directory - strcat(strcat(Direc, FileData.name), "\\"); - n += FindInDir(g); - Direc[m] = '\0'; // Restore path - } // endif SUBDIR + if (h == INVALID_HANDLE_VALUE) { + rc = GetLastError(); - if (_findnext(h, &FileData)) - break; + if (rc != ERROR_FILE_NOT_FOUND) { + char buf[512]; - } // endwhile + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL); + sprintf(g->Message, MSG(BAD_FILE_HANDLE), buf); + return -1; + } // endif rc - // Close the search handle. - _findclose(h); - } // endif h + return 0; + } // endif h + + while (true) { + if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + *FileData.cFileName != '.') { + // Look in the name sub-directory + strcat(strcat(Direc, FileData.cFileName), "/"); + n += FindInDir(g); + Direc[m] = '\0'; // Restore path + } else if (PathMatchSpec(FileData.cFileName, Fpath)) + n++; + + if (!FindNextFile(h, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc); + FindClose(h); + return -1; + } // endif rc + + break; + } // endif Next + + } // endwhile +#else // !PATHMATCHSPEC + h = FindFirstFile(Path(g), &FileData); + + if (h == INVALID_HANDLE_VALUE) { + rc = GetLastError(); + + if (rc != ERROR_FILE_NOT_FOUND) { + char buf[512]; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL); + sprintf(g->Message, MSG(BAD_FILE_HANDLE), buf); + return -1; + } // endif rc + + return 0; + } // endif hSearch + + while (true) { + n++; + + if (!FindNextFile(h, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc); + FindClose(h); + return -1; + } // endif rc + + break; + } // endif Next + + } // endwhile + + // Now search files in sub-directories. + _makepath(Fpath, Drive, Direc, "*", "."); + h = FindFirstFile(Fpath, &FileData); + + if (h != INVALID_HANDLE_VALUE) { + while (true) { + if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + *FileData.cFileName != '.') { + // Look in the name sub-directory + strcat(strcat(Direc, FileData.cFileName), "/"); + n += FindInDir(g); + Direc[m] = '\0'; // Restore path + } // endif SUBDIR + + if (!FindNextFile(h, &FileData)) + break; + + } // endwhile + + } // endif h +#endif // !PATHMATCHSPEC + + // Close the search handle. + FindClose(h); #else // !__WIN__ int k; DIR *dir = opendir(Direc); @@ -1094,7 +1202,7 @@ bool TDBSDR::OpenDB(PGLOBAL g) Sub->Next = NULL; Sub->Prev = NULL; #if defined(__WIN__) - Sub->H = -1; + Sub->H = INVALID_HANDLE_VALUE; Sub->Len = strlen(Direc); #else // !__WIN__ Sub->D = NULL; @@ -1120,18 +1228,20 @@ int TDBSDR::ReadDB(PGLOBAL g) // Are there more files in sub-directories retry: do { - if (Sub->H == -1) { - _makepath(Fpath, Drive, Direc, "*", ""); - Sub->H = _findfirst(Fpath, &FileData); - } else if (_findnext(Sub->H, &FileData)) { - _findclose(Sub->H); - Sub->H = -1; - *FileData.name = '\0'; - } // endif findnext + if (Sub->H == INVALID_HANDLE_VALUE) { + _makepath(Fpath, Drive, Direc, "*", "."); + Sub->H = FindFirstFile(Fpath, &FileData); + } else if (!FindNextFile(Sub->H, &FileData)) { + FindClose(Sub->H); + Sub->H = INVALID_HANDLE_VALUE; + *FileData.cFileName= '\0'; + break; + } // endif findnext - } while(*FileData.name == '.'); + } while(!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + || *FileData.cFileName== '.'); - if (Sub->H == -1) { + if (Sub->H == INVALID_HANDLE_VALUE) { // No more sub-directories. Are we in a sub-directory? if (!Sub->Prev) return rc; // No, all is finished @@ -1149,17 +1259,17 @@ int TDBSDR::ReadDB(PGLOBAL g) sup = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR)); sup->Next = NULL; sup->Prev = Sub; - sup->H = -1; + sup->H = INVALID_HANDLE_VALUE; Sub->Next = sup; } // endif Next Sub = Sub->Next; - strcat(strcat(Direc, FileData.name), "\\"); + strcat(strcat(Direc, FileData.cFileName), "/"); Sub->Len = strlen(Direc); // Reset Hsearch used by TDBDIR::ReadDB - _findclose(Hsearch); - Hsearch = -1; + FindClose(hSearch); + hSearch = INVALID_HANDLE_VALUE; goto again; } // endif H diff --git a/storage/connect/tabmul.h b/storage/connect/tabmul.h index 51fa7f9000a..3c0ab1a4aa5 100644 --- a/storage/connect/tabmul.h +++ b/storage/connect/tabmul.h @@ -69,6 +69,34 @@ class DllExport TDBMUL : public TDBASE { int iFile; // Index of currently processed file }; // end of class TDBMUL +#if 0 +/***********************************************************************/ +/* This is the MSD Access Method class declaration for files that are */ +/* physically split in multiple files having the same format. */ +/* This sub-class also include files of the sub-directories. */ +/***********************************************************************/ +class DllExport TDBMSD : public TDBMUL { + //friend class MULCOL; +public: + // Constructor + TDBMSD(PTDB tdbp) : TDBMUL(tdbp) {} + TDBMSD(PTDBMSD tdbp) : TDBMUL(tdbp) {} + + // Implementation + virtual PTDB Duplicate(PGLOBAL g); + + // Methods + virtual PTDB Clone(PTABS t); + bool InitFileNames(PGLOBAL g); + + // Database routines + +protected: + + // Members +}; // end of class TDBMSD +#endif + /***********************************************************************/ /* Directory listing table. */ /***********************************************************************/ @@ -101,18 +129,16 @@ class DllExport DIRDEF : public TABDEF { /* Directory listing table */ /***********************************************************************/ class TDBDIR : public TDBASE { friend class DIRCOL; - public: + friend class TDBMUL; +public: // Constructor TDBDIR(PDIRDEF tdp); - TDBDIR(PTDBDIR tdbp); + TDBDIR(PSZ fpat); // Implementation virtual AMT GetAmType(void) {return TYPE_AM_DIR;} - virtual PTDB Duplicate(PGLOBAL g) - {return (PTDB)new(g) TDBDIR(this);} // Methods - virtual PTDB Clone(PTABS t); virtual int GetRecpos(void) {return iFile;} // Database routines @@ -127,14 +153,16 @@ class TDBDIR : public TDBASE { virtual void CloseDB(PGLOBAL g); protected: + void Init(void); char *Path(PGLOBAL g); // Members PSZ To_File; // Points to file search pathname int iFile; // Index of currently retrieved file #if defined(__WIN__) - _finddata_t FileData; // Find data structure - intptr_t Hsearch; // Search handle + PVAL Dvalp; // Used to retrieve file date values + WIN32_FIND_DATA FileData; // Find data structure + HANDLE hSearch; // Search handle char Drive[_MAX_DRIVE]; // Drive name #else // !__WIN__ struct stat Fileinfo; // File info structure @@ -158,17 +186,11 @@ class TDBDIR : public TDBASE { /***********************************************************************/ class TDBSDR : public TDBDIR { friend class DIRCOL; + friend class TDBMUL; public: // Constructors TDBSDR(PDIRDEF tdp) : TDBDIR(tdp) {Sub = NULL;} - TDBSDR(PTDBSDR tdbp); - - // Implementation - virtual PTDB Duplicate(PGLOBAL g) - {return (PTDB)new(g) TDBSDR(this);} - - // Methods - virtual PTDB Clone(PTABS t); + TDBSDR(PSZ fpat) : TDBDIR(fpat) {Sub = NULL;} // Database routines virtual int GetMaxSize(PGLOBAL g); @@ -184,7 +206,7 @@ class TDBSDR : public TDBDIR { struct _Sub_Dir *Next; struct _Sub_Dir *Prev; #if defined(__WIN__) - intptr_t H; // Search handle + HANDLE H; // Search handle #else // !__WIN__ DIR *D; #endif // !__WIN__ @@ -214,7 +236,11 @@ class DIRCOL : public COLBLK { protected: // Default constructor not to be used DIRCOL(void) {} +#if defined(__WIN__) + void SetTimeValue(PGLOBAL g, FILETIME& ftime); +#endif // __WIN__ // Members + PTDBDIR Tdbp; // To DIR table int N; // Column number }; // end of class DIRCOL From c99d71a29ce91c359bb4d72875477144c26463b3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 12 Mar 2017 01:10:04 +0100 Subject: [PATCH 041/148] MDEV-12231 MariaDB fails to restart after 10.0.30-1.el7 update force SELinux policies to be built in mysql_release RPM packages --- cmake/build_configurations/mysql_release.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index 2c0e7699c8d..68453bab608 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -97,6 +97,8 @@ OPTION(ENABLED_LOCAL_INFILE "" ON) IF(RPM) SET(WITH_SSL system CACHE STRING "") SET(WITH_ZLIB system CACHE STRING "") + SET(CHECKMODULE /usr/bin/checkmodule CACHE STRING "") + SET(SEMODULE_PACKAGE /usr/bin/semodule_package CACHE STRING "") ELSEIF(DEB) SET(WITH_SSL system CACHE STRING "") SET(WITH_ZLIB system CACHE STRING "") From 3990e55fef0053e2e30f0d09d20daf2d96bdadc7 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 13 Mar 2017 23:31:03 +0000 Subject: [PATCH 042/148] Windows : Fix packaging when building with VS2017 --- win/packaging/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 1682bae6986..d33516044f6 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -51,7 +51,7 @@ IF(MSVC_VERSION EQUAL 1600 OR MSVC_VERSION EQUAL 1700 ) SET(WIX_MSVC_SUFFIX "VS2010") ELSEIF(MSVC_VERSION EQUAL 1800) SET(WIX_MSVC_SUFFIX "VS2013") -ELSEIF (MSVC_VERSION EQUAL 1900) +ELSE() SET(WIX_MSVC_SUFFIX "VS2015") ENDIF() From 87e37ee06b32dda19f8c17a888586dd03191eeec Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Mon, 13 Mar 2017 17:01:59 +0400 Subject: [PATCH 043/148] BUG#25575605: SETTING --SSL-MODE=REQUIRED SENDS CREDENTIALS BEFORE VERIFYING SSL CONNECTION Changed MYSQL_OPT_SSL_MODE to be the same as in 5.6 (ABI compatibility). (cherry picked from commit 47bb4eb5df1629b5d5e30aebfa9d7a6d74388a5d) --- include/mysql.h | 4 +++- include/mysql.h.pp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 7ebf2f725a2..3a27ab4128c 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -167,7 +167,9 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE + MYSQL_ENABLE_CLEARTEXT_PLUGIN, + /* Set MYSQL_OPT_SSL_MODE to be the same as in 5.6 (ABI compatibility). */ + MYSQL_OPT_SSL_MODE= 38 }; /** diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 0f292d921ee..774bf2d0301 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -263,7 +263,8 @@ enum mysql_option MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, - MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE + MYSQL_ENABLE_CLEARTEXT_PLUGIN, + MYSQL_OPT_SSL_MODE= 38 }; struct st_mysql_options_extention; struct st_mysql_options { From adbe1c5fe986392e5a6159e4711b99d2275be81b Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 14 Mar 2017 17:31:29 +0530 Subject: [PATCH 044/148] MDEV-6486: Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed with SELECT SQ, TEXT field The functon find_all_keys does call Item_subselect::walk, which calls walk() for the subquery The issue is that when a field is represented by Item_outer_ref(Item_direct_ref(Item_copy_string( ...))). Item_copy_string does have a pointer to an Item_field in Item_copy::item but does not implement Item::walk method, so we are not able to set the bitmap for that field. This is the reason why the assert fails. Fixed by adding the walk method to Item_copy class. --- mysql-test/r/subselect4.result | 13 +++++++++++++ mysql-test/t/subselect4.test | 16 ++++++++++++++++ sql/item.h | 5 +++++ 3 files changed, 34 insertions(+) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 2a229675817..2228609b82c 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2483,5 +2483,18 @@ select 1 from dual where null not in (select 1 from t2); 1 1 drop table t1,t2; +# +# MDEV-6486: Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' +# failed with SELECT SQ, TEXT field +# +CREATE TABLE t1 (a VARCHAR(8), KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),( 'bar'); +CREATE TABLE t2 (b VARCHAR(8), c TINYTEXT, KEY(b)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('baz','baz'),('qux', 'qux'); +SELECT ( SELECT COUNT(*) FROM t1 WHERE a = c ) AS field, COUNT(DISTINCT c) +FROM t2 WHERE b <= 'quux' GROUP BY field; +field COUNT(DISTINCT c) +0 1 +drop table t1,t2; SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index 056152cc706..f051c8eaaf2 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -2019,5 +2019,21 @@ select 1 from dual where null not in (select 1 from t1); select 1 from dual where null not in (select 1 from t2); drop table t1,t2; + +--echo # +--echo # MDEV-6486: Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' +--echo # failed with SELECT SQ, TEXT field +--echo # + +CREATE TABLE t1 (a VARCHAR(8), KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),( 'bar'); + +CREATE TABLE t2 (b VARCHAR(8), c TINYTEXT, KEY(b)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('baz','baz'),('qux', 'qux'); + +SELECT ( SELECT COUNT(*) FROM t1 WHERE a = c ) AS field, COUNT(DISTINCT c) +FROM t2 WHERE b <= 'quux' GROUP BY field; +drop table t1,t2; + SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/sql/item.h b/sql/item.h index 89155ac00db..9db5c7e9ac0 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3694,6 +3694,11 @@ public: virtual double val_real() = 0; virtual longlong val_int() = 0; virtual int save_in_field(Field *field, bool no_conversions) = 0; + bool walk(Item_processor processor, bool walk_subquery, uchar *args) + { + return (item->walk(processor, walk_subquery, args)) || + (this->*processor)(args); + } }; /** From 8efdf89e42bca849c5f6531fb0367fca267c93b8 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 17 Mar 2017 20:07:39 +0000 Subject: [PATCH 045/148] MDEV-12126 Correct German error message. --- sql/share/errmsg-utf8.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 6fcb460e6c6..51a9f6e3847 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -4883,7 +4883,7 @@ WARN_DATA_TRUNCATED 01000 spa "Datos truncados para columna '%s' en la línea %lu" ER_WARN_USING_OTHER_HANDLER eng "Using storage engine %s for table '%s'" - ger "Für Tabelle '%s' wird Speicher-Engine %s benutzt" + ger "Speicher-Engine %s wird für Tabelle '%s' benutzt" por "Usando engine de armazenamento %s para tabela '%s'" spa "Usando motor de almacenamiento %s para tabla '%s'" swe "Använder handler %s för tabell '%s'" From 6fa5e0814662d691be1a29bf88332348ec7c50c9 Mon Sep 17 00:00:00 2001 From: Bharathy Satish Date: Fri, 17 Mar 2017 08:41:31 +0100 Subject: [PATCH 046/148] Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY While writing comments if database object names has a new line character, then next line is considered a command, rather than a comment. This patch fixes the way comments are constructed in mysqldump. (cherry picked from commit 1099f9d17b1c697c2760f86556f5bae7d202b444) --- client/mysqldump.c | 54 +++++++++++++++++++++++------- mysql-test/r/mysqldump.result | 63 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 50 +++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 12 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index fcd29e26fe3..2775769fe52 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -549,6 +549,7 @@ static int dump_tablespaces_for_databases(char** databases); static int dump_tablespaces(char* ts_where); static void print_comment(FILE *sql_file, my_bool is_error, const char *format, ...); +static const char* fix_identifier_with_newline(char*); /* @@ -649,7 +650,7 @@ static void write_header(FILE *sql_file, char *db_name) MACHINE_TYPE); print_comment(sql_file, 0, "-- Host: %s Database: %s\n", current_host ? current_host : "localhost", - db_name ? db_name : ""); + db_name ? fix_identifier_with_newline(db_name) : ""); print_comment(sql_file, 0, "-- ------------------------------------------------------\n" ); @@ -1981,6 +1982,30 @@ static void print_comment(FILE *sql_file, my_bool is_error, const char *format, print_xml_comment(sql_file, strlen(comment_buff), comment_buff); } +/* + This function accepts object names and prefixes -- wherever \n + character is found. + + @param[in] object_name + + @return + @retval fixed object name. +*/ + +static const char* fix_identifier_with_newline(char* object_name) +{ + static char buff[COMMENT_LENGTH]= {0}; + char *ptr= buff; + memset(buff, 0, 255); + while(*object_name) + { + *ptr++ = *object_name; + if (*object_name == '\n') + ptr= strmov(ptr, "-- "); + object_name++; + } + return buff; +} /* create_delimiter @@ -2049,7 +2074,8 @@ static uint dump_events_for_db(char *db) /* nice comments */ print_comment(sql_file, 0, - "\n--\n-- Dumping events for database '%s'\n--\n", db); + "\n--\n-- Dumping events for database '%s'\n--\n", + fix_identifier_with_newline(db)); /* not using "mysql_query_with_error_report" because we may have not @@ -2266,7 +2292,8 @@ static uint dump_routines_for_db(char *db) /* nice comments */ print_comment(sql_file, 0, - "\n--\n-- Dumping routines for database '%s'\n--\n", db); + "\n--\n-- Dumping routines for database '%s'\n--\n", + fix_identifier_with_newline(db)); /* not using "mysql_query_with_error_report" because we may have not @@ -2325,7 +2352,7 @@ static uint dump_routines_for_db(char *db) query_buff); print_comment(sql_file, 1, "-- does %s have permissions on mysql.proc?\n\n", - current_user); + fix_identifier_with_newline(current_user)); maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff); } else if (strlen(row[2])) @@ -2539,11 +2566,11 @@ static uint get_table_structure(char *table, char *db, char *table_type, if (strcmp (table_type, "VIEW") == 0) /* view */ print_comment(sql_file, 0, "\n--\n-- Temporary table structure for view %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); else print_comment(sql_file, 0, "\n--\n-- Table structure for table %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); if (opt_drop) { @@ -2785,7 +2812,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, print_comment(sql_file, 0, "\n--\n-- Table structure for table %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); if (opt_drop) fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table); if (!opt_xml) @@ -3490,21 +3517,23 @@ static void dump_table(char *table, char *db) { print_comment(md_result_file, 0, "\n--\n-- Dumping data for table %s\n--\n", - result_table); + fix_identifier_with_newline(result_table)); dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM "); dynstr_append_checked(&query_string, result_table); if (where) { - print_comment(md_result_file, 0, "-- WHERE: %s\n", where); + print_comment(md_result_file, 0, "-- WHERE: %s\n", + fix_identifier_with_newline(where)); dynstr_append_checked(&query_string, " WHERE "); dynstr_append_checked(&query_string, where); } if (order_by) { - print_comment(md_result_file, 0, "-- ORDER BY: %s\n", order_by); + print_comment(md_result_file, 0, "-- ORDER BY: %s\n", + fix_identifier_with_newline(order_by)); dynstr_append_checked(&query_string, " ORDER BY "); dynstr_append_checked(&query_string, order_by); @@ -4275,7 +4304,8 @@ static int init_dumping(char *database, int init_func(char*)) char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); print_comment(md_result_file, 0, - "\n--\n-- Current Database: %s\n--\n", qdatabase); + "\n--\n-- Current Database: %s\n--\n", + fix_identifier_with_newline(qdatabase)); /* Call the view or table specific function */ init_func(qdatabase); @@ -5281,7 +5311,7 @@ static my_bool get_view_structure(char *table, char* db) print_comment(sql_file, 0, "\n--\n-- Final view structure for view %s\n--\n\n", - result_table); + fix_identifier_with_newline(result_table)); /* Table might not exist if this view was dumped with --tab. */ fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n", opt_quoted_table); diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index c578f9e8df6..24746a3a51d 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -5283,3 +5283,66 @@ a DROP TABLE t1; DROP TABLE t2; DROP DATABASE db_20772273; +# +# Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY +# +CREATE DATABASE bug25717383; +use bug25717383; +CREATE TABLE `tab +one` (a int); +CREATE VIEW `view +one` as SELECT * FROM `tab +one`; +CREATE PROCEDURE `proc +one`() SELECT * from `tab +one`; +CREATE TEMPORARY TABLE `temp +one` (id INT); +CREATE TRIGGER `trig +one` BEFORE INSERT ON `tab +one` FOR EACH ROW SET NEW.a = 1; +CREATE EVENT `event +one` ON SCHEDULE AT '2030-01-01 00:00:00' DO SET @a=5; +SHOW TABLES FROM bug25717383; +Tables_in_bug25717383 +tab +one +view +one +SHOW TRIGGERS FROM bug25717383; +Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation +trig +one INSERT tab +one SET NEW.a = 1 BEFORE NULL root@localhost utf8 utf8_general_ci latin1_swedish_ci +SHOW EVENTS FROM bug25717383; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +bug25717383 event +one root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL ENABLED 1 utf8 utf8_general_ci latin1_swedish_ci +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; +ROUTINE_NAME +proc +one +SHOW TABLES FROM bug25717383; +Tables_in_bug25717383 +tab +one +view +one +SHOW TRIGGERS FROM bug25717383; +Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation +trig +one INSERT tab +one SET NEW.a = 1 BEFORE NULL root@localhost utf8 utf8_general_ci latin1_swedish_ci +SHOW EVENTS FROM bug25717383; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +bug25717383 event +one root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL ENABLED 1 utf8 utf8_general_ci latin1_swedish_ci +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; +ROUTINE_NAME +proc +one +DROP DATABASE bug25717383; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 11d766c3293..da958f83c48 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2425,3 +2425,53 @@ SELECT * FROM t2; DROP TABLE t1; DROP TABLE t2; DROP DATABASE db_20772273; + +--echo # +--echo # Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY +--echo # + + +CREATE DATABASE bug25717383; +use bug25717383; + +CREATE TABLE `tab +one` (a int); +CREATE VIEW `view +one` as SELECT * FROM `tab +one`; + +CREATE PROCEDURE `proc +one`() SELECT * from `tab +one`; + +CREATE TEMPORARY TABLE `temp +one` (id INT); + +CREATE TRIGGER `trig +one` BEFORE INSERT ON `tab +one` FOR EACH ROW SET NEW.a = 1; + +CREATE EVENT `event +one` ON SCHEDULE AT '2030-01-01 00:00:00' DO SET @a=5; + +SHOW TABLES FROM bug25717383; +SHOW TRIGGERS FROM bug25717383; +--replace_column 6 # +SHOW EVENTS FROM bug25717383; + +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; + +--exec $MYSQL_DUMP --triggers --events --routines --add-drop-database --databases bug25717383 > $MYSQLTEST_VARDIR/tmp/bug25717383.sql + +SHOW TABLES FROM bug25717383; +SHOW TRIGGERS FROM bug25717383; +--replace_column 6 # +SHOW EVENTS FROM bug25717383; + +SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE' + ORDER BY ROUTINE_NAME; + +DROP DATABASE bug25717383; From 5de5daa74e1ff3d3b002801c22a94c556e80d942 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 18 Mar 2017 12:49:14 +0100 Subject: [PATCH 047/148] Fix MDEV-12220: Crash when doing UPDATE or DELETE on an external table (ODBC, JDBC, MYSQL) with a WHERE clause on an indexed column. Also fix a bugs in TDBEXT::MakeCommand (use of uninitialised Quote) Add in this function the eventual Schema (database) prefixing. modified: storage/connect/connect.cc modified: storage/connect/tabext.cpp Typo modified: storage/connect/tabjdbc.h --- storage/connect/connect.cc | 5 +++-- storage/connect/tabext.cpp | 40 ++++++++++++++++++++++++++++++-------- storage/connect/tabjdbc.h | 4 ++-- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 6be5bd349dc..9ec93bfe1ba 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -858,8 +858,9 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, sprintf(g->Message, MSG(TABLE_NO_INDEX), ptdb->GetName()); return RC_FX; } else if (x == 2) { - // Remote index - if (op != OP_SAME && ptdb->ReadKey(g, op, kr)) + // Remote index. Only used in read mode + if ((ptdb->GetMode() == MODE_READ || ptdb->GetMode() == MODE_READX) + && op != OP_SAME && ptdb->ReadKey(g, op, kr)) return RC_FX; goto rnd; diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index c3403ca0081..ad9716b6a10 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -434,15 +434,16 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) /***********************************************************************/ bool TDBEXT::MakeCommand(PGLOBAL g) { - char *p, *stmt, name[68], *body = NULL; + char *p, *stmt, name[132], *body = NULL, *schmp = NULL; char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1); bool qtd = Quoted > 0; + char q = qtd ? *Quote : ' '; int i = 0, k = 0; // Make a lower case copy of the originale query and change // back ticks to the data source identifier quoting character do { - qrystr[i] = (Qrystr[i] == '`') ? *Quote : tolower(Qrystr[i]); + qrystr[i] = (Qrystr[i] == '`') ? q : tolower(Qrystr[i]); } while (Qrystr[i++]); if (To_CondFil && (p = strstr(qrystr, " where "))) { @@ -459,27 +460,50 @@ bool TDBEXT::MakeCommand(PGLOBAL g) strlwr(strcat(strcat(strcpy(name, " "), Name), " ")); if (strstr(" update delete low_priority ignore quick from ", name)) { - strlwr(strcat(strcat(strcpy(name, Quote), Name), Quote)); - k += 2; + if (Quote) { + strlwr(strcat(strcat(strcpy(name, Quote), Name), Quote)); + k += 2; + } else { + strcpy(g->Message, "Quoted must be specified"); + return true; + } // endif Quote + } else strlwr(strcpy(name, Name)); // Not a keyword if ((p = strstr(qrystr, name))) { for (i = 0; i < p - qrystr; i++) - stmt[i] = (Qrystr[i] == '`') ? *Quote : Qrystr[i]; + stmt[i] = (Qrystr[i] == '`') ? q : Qrystr[i]; stmt[i] = 0; + k += i + (int)strlen(Name); - if (qtd && *(p - 1) == ' ') + if (Schema && *Schema) + schmp = Schema; + + if (qtd && *(p - 1) == ' ') { + if (schmp) + strcat(strcat(stmt, schmp), "."); + strcat(strcat(strcat(stmt, Quote), TableName), Quote); - else + } else { + if (schmp) { + if (qtd && *(p - 1) != ' ') { + stmt[i - 1] = 0; + strcat(strcat(strcat(stmt, schmp), "."), Quote); + } else + strcat(strcat(stmt, schmp), "."); + + } // endif schmp + strcat(stmt, TableName); + } // endif's i = (int)strlen(stmt); do { - stmt[i++] = (Qrystr[k] == '`') ? *Quote : Qrystr[k]; + stmt[i++] = (Qrystr[k] == '`') ? q : Qrystr[k]; } while (Qrystr[k++]); if (body) diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index 212f2a58b58..5a59b6c2df8 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -1,7 +1,7 @@ /*************** Tabjdbc H Declares Source Code File (.H) **************/ -/* Name: TABJDBC.H Version 1.0 */ +/* Name: TABJDBC.H Version 1.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */ /* */ /* This file contains the TDBJDBC classes declares. */ /***********************************************************************/ From 577915def8d39223aa23a06f898e11e82e72365a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 20 Mar 2017 18:53:45 +0100 Subject: [PATCH 048/148] remove COPYING.LESSER shouldn't have been added in the first place, MariaDB Server is GPLv2 --- CMakeLists.txt | 3 +- COPYING.LESSER | 516 ------------------------------------------------- 2 files changed, 1 insertion(+), 518 deletions(-) delete mode 100644 COPYING.LESSER diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cf2ccb175f..52fa188347e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -463,8 +463,7 @@ ADD_CUSTOM_TARGET(INFO_BIN ALL WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) -INSTALL_DOCUMENTATION(README COPYING COPYING.LESSER EXCEPTIONS-CLIENT - COMPONENT Readme) +INSTALL_DOCUMENTATION(README COPYING EXCEPTIONS-CLIENT COMPONENT Readme) # MDEV-6526 these files are not installed anymore #INSTALL_DOCUMENTATION(${CMAKE_BINARY_DIR}/Docs/INFO_SRC diff --git a/COPYING.LESSER b/COPYING.LESSER deleted file mode 100644 index c2c87d69256..00000000000 --- a/COPYING.LESSER +++ /dev/null @@ -1,516 +0,0 @@ - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. -^L - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. -^L - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. -^L - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. -^L - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. -^L - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. -^L - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. -^L - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS -^L - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301, USA - -Also add information on how to contact you by electronic and paper -mail. - -You should also get your employer (if you work as a programmer) or -your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James -Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - From a821ef76057f17a9532f525d2858bb1d31c0a56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 24 Mar 2017 18:01:56 +0200 Subject: [PATCH 049/148] MDEV-11802 innodb.innodb_bug14676111 fails on buildbot The test was unnecessarily depending on InnoDB purge, which can sometimes fail to proceed. Let us rewrite the test to use BEGIN;INSERT;ROLLBACK to cause the immediate removal of the desired records. --- .../suite/innodb/r/innodb_bug14676111.result | 18 ++++-- .../innodb/t/innodb_bug14676111-master.opt | 1 - .../suite/innodb/t/innodb_bug14676111.test | 61 +++++++++---------- 3 files changed, 41 insertions(+), 39 deletions(-) delete mode 100644 mysql-test/suite/innodb/t/innodb_bug14676111-master.opt diff --git a/mysql-test/suite/innodb/r/innodb_bug14676111.result b/mysql-test/suite/innodb/r/innodb_bug14676111.result index ebecd1d00cb..ca4a7fd7e4a 100644 --- a/mysql-test/suite/innodb/r/innodb_bug14676111.result +++ b/mysql-test/suite/innodb/r/innodb_bug14676111.result @@ -1,10 +1,13 @@ -drop table if exists t1; +set @old_innodb_limit_optimistic_insert_debug = @@innodb_limit_optimistic_insert_debug; CREATE TABLE t1 (a int not null primary key) engine=InnoDB; set global innodb_limit_optimistic_insert_debug = 2; insert into t1 values (1); +begin; insert into t1 values (5); +begin; insert into t1 values (4); insert into t1 values (3); +begin; insert into t1 values (2); analyze table t1; Table Op Msg_type Msg_text @@ -12,14 +15,14 @@ test.t1 analyze status OK select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; DATA_LENGTH / 16384 10.0000 -delete from t1 where a=4; +rollback; analyze table t1; Table Op Msg_type Msg_text test.t1 analyze status OK select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; DATA_LENGTH / 16384 8.0000 -delete from t1 where a=5; +rollback; analyze table t1; Table Op Msg_type Msg_text test.t1 analyze status OK @@ -27,23 +30,25 @@ select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = ' DATA_LENGTH / 16384 5.0000 set global innodb_limit_optimistic_insert_debug = 10000; -delete from t1 where a=2; +rollback; analyze table t1; Table Op Msg_type Msg_text test.t1 analyze status OK select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; DATA_LENGTH / 16384 3.0000 +begin; insert into t1 values (2); -delete from t1 where a=2; +rollback; analyze table t1; Table Op Msg_type Msg_text test.t1 analyze status OK select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; DATA_LENGTH / 16384 2.0000 +begin; insert into t1 values (2); -delete from t1 where a=2; +rollback; analyze table t1; Table Op Msg_type Msg_text test.t1 analyze status OK @@ -51,3 +56,4 @@ select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = ' DATA_LENGTH / 16384 1.0000 drop table t1; +set global innodb_limit_optimistic_insert_debug = @old_innodb_limit_optimistic_insert_debug; diff --git a/mysql-test/suite/innodb/t/innodb_bug14676111-master.opt b/mysql-test/suite/innodb/t/innodb_bug14676111-master.opt deleted file mode 100644 index e16b9b0b895..00000000000 --- a/mysql-test/suite/innodb/t/innodb_bug14676111-master.opt +++ /dev/null @@ -1 +0,0 @@ ---loose-innodb-purge-threads=0 diff --git a/mysql-test/suite/innodb/t/innodb_bug14676111.test b/mysql-test/suite/innodb/t/innodb_bug14676111.test index 41862b8105e..10eb6a3b13c 100644 --- a/mysql-test/suite/innodb/t/innodb_bug14676111.test +++ b/mysql-test/suite/innodb/t/innodb_bug14676111.test @@ -2,51 +2,40 @@ -- source include/have_innodb.inc -- source include/have_debug.inc +-- source include/count_sessions.inc -# Note that this test needs to be able to manipulate how/when purge is done -# using @@innodb_limit_optimistic_insert_debug. This does not work with -# background purge threads, so we disabled them in the -master.opt (they are -# off by default in normal 5.5 innodb but on by default in xtradb) - -if (`select count(*)=0 from information_schema.global_variables where variable_name = 'INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG'`) -{ - --skip Test requires InnoDB built with UNIV_DEBUG definition. -} - ---disable_query_log set @old_innodb_limit_optimistic_insert_debug = @@innodb_limit_optimistic_insert_debug; ---enable_query_log ---disable_warnings -drop table if exists t1; ---enable_warnings CREATE TABLE t1 (a int not null primary key) engine=InnoDB; -let $wait_condition= - SELECT VARIABLE_VALUE < 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS - WHERE VARIABLE_NAME = 'INNODB_PURGE_TRX_ID_AGE'; - # # make 4 leveled straight tree # set global innodb_limit_optimistic_insert_debug = 2; insert into t1 values (1); +--connect (con5,localhost,root) +begin; insert into t1 values (5); #current tree form # (1, 5) +--connect (con4,localhost,root) +begin; insert into t1 values (4); #records in a page is limited to 2 artificially. root rise occurs #current tree form # (1, 5) #(1, 4) (5) +--connection default insert into t1 values (3); #current tree form # (1, 5) # (1, 4) (5) #(1, 3) (4) (5) +--connect (con2,localhost,root) +begin; insert into t1 values (2); #current tree form # (1, 5) @@ -54,11 +43,15 @@ insert into t1 values (2); # (1, 3) (4) (5) #(1, 2) (3) (4) (5) +--connection default analyze table t1; select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; -delete from t1 where a=4; ---source include/wait_condition.inc +--connection con4 +rollback; +--disconnect con4 +--connection default + #deleting 1 record of 2 records don't cause merge artificially. #current tree form # (1, 5) @@ -69,8 +62,11 @@ delete from t1 where a=4; analyze table t1; select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; -delete from t1 where a=5; ---source include/wait_condition.inc +--connection con5 +rollback; +--disconnect con5 +--connection default + #deleting 1 record of 2 records don't cause merge artificially. #current tree form # (1) @@ -87,8 +83,11 @@ select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = ' #disable the artificial limitation of records in a page set global innodb_limit_optimistic_insert_debug = 10000; -delete from t1 where a=2; ---source include/wait_condition.inc +--connection con2 +rollback; +--disconnect con2 +--connection default + #merge page occurs. and lift up occurs. #current tree form # (1) @@ -98,14 +97,14 @@ delete from t1 where a=2; analyze table t1; select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; +begin; insert into t1 values (2); #current tree form # (1) # (1) <- lift up this level next, because it is not root # (1, 2, 3) +rollback; -delete from t1 where a=2; ---source include/wait_condition.inc #current tree form # (1) # (1, 3) @@ -113,13 +112,12 @@ delete from t1 where a=2; analyze table t1; select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 't1'; +begin; insert into t1 values (2); #current tree form # (1) # (1, 2, 3) <- lift up this level next, because the father is root - -delete from t1 where a=2; ---source include/wait_condition.inc +rollback; #current tree form # (1, 3) @@ -128,6 +126,5 @@ select DATA_LENGTH / 16384 from information_schema.TABLES where TABLE_SCHEMA = ' drop table t1; ---disable_query_log set global innodb_limit_optimistic_insert_debug = @old_innodb_limit_optimistic_insert_debug; ---enable_query_log +-- source include/wait_until_count_sessions.inc From 3ac35bb05906df8561cd9f37c98e6b70ae149140 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 28 Mar 2017 10:25:21 +0200 Subject: [PATCH 050/148] Fix crash when a line is not ended by \n. modified: storage/connect/filamap.cpp Add specifying a password when reading zipped tables. modified: storage/connect/filamzip.cpp modified: storage/connect/filamzip.h modified: storage/connect/tabdos.cpp modified: storage/connect/tabdos.h Try Vaintroub suggestion modified: storage/connect/mysql-test/connect/t/jdbc.test --- storage/connect/filamap.cpp | 21 ++++++++++------ storage/connect/filamzip.cpp | 49 +++++++++++++++++++++++++++--------- storage/connect/filamzip.h | 16 +++++++----- storage/connect/tabdos.cpp | 4 ++- storage/connect/tabdos.h | 1 + 5 files changed, 64 insertions(+), 27 deletions(-) diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp index 8fffaca3d06..84dff422db7 100644 --- a/storage/connect/filamap.cpp +++ b/storage/connect/filamap.cpp @@ -301,10 +301,9 @@ int MAPFAM::SkipRecord(PGLOBAL g, bool header) PDBUSER dup = (PDBUSER)g->Activityp->Aptr; // Skip this record - while (*Mempos++ != '\n') ; // What about Unix ??? - - if (Mempos >= Top) - return RC_EF; + while (*Mempos++ != '\n') // What about Unix ??? + if (Mempos == Top) + return RC_EF; // Update progress information dup->ProgCur = GetPos(); @@ -320,7 +319,7 @@ int MAPFAM::SkipRecord(PGLOBAL g, bool header) /***********************************************************************/ int MAPFAM::ReadBuffer(PGLOBAL g) { - int rc, len; + int rc, len, n = 1; // Are we at the end of the memory if (Mempos >= Top) { @@ -362,10 +361,14 @@ int MAPFAM::ReadBuffer(PGLOBAL g) Placed = false; // Immediately calculate next position (Used by DeleteDB) - while (*Mempos++ != '\n') ; // What about Unix ??? + while (*Mempos++ != '\n') // What about Unix ??? + if (Mempos == Top) { + n = 0; + break; + } // endif Mempos // Set caller line buffer - len = (Mempos - Fpos) - 1; + len = (Mempos - Fpos) - n; // Don't rely on ENDING setting if (len > 0 && *(Mempos - 2) == '\r') @@ -619,7 +622,9 @@ int MBKFAM::ReadBuffer(PGLOBAL g) } // endif's // Immediately calculate next position (Used by DeleteDB) - while (*Mempos++ != '\n') ; // What about Unix ??? + while (*Mempos++ != '\n') // What about Unix ??? + if (Mempos == Top) + break; // Set caller line buffer len = (Mempos - Fpos) - Ending; diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 9abb2602b56..1a27c974f30 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -386,6 +386,7 @@ UNZIPUTL::UNZIPUTL(PSZ tgt, bool mul) { zipfile = NULL; target = tgt; + pwd = NULL; fp = NULL; memory = NULL; size = 0; @@ -401,6 +402,26 @@ UNZIPUTL::UNZIPUTL(PSZ tgt, bool mul) #endif } // end of UNZIPUTL standard constructor +UNZIPUTL::UNZIPUTL(PDOSDEF tdp) +{ + zipfile = NULL; + target = tdp->GetEntry(); + pwd = tdp->Pwd; + fp = NULL; + memory = NULL; + size = 0; + entryopen = false; + multiple = tdp->GetMul(); + memset(fn, 0, sizeof(fn)); + + // Init the case mapping table. +#if defined(__WIN__) + for (int i = 0; i < 256; ++i) mapCaseTable[i] = toupper(i); +#else + for (int i = 0; i < 256; ++i) mapCaseTable[i] = i; +#endif +} // end of UNZIPUTL standard constructor + #if 0 UNZIPUTL::UNZIPUTL(PZIPUTIL zutp) { @@ -625,7 +646,7 @@ bool UNZIPUTL::openEntry(PGLOBAL g) if (rc != UNZ_OK) { sprintf(g->Message, "unzGetCurrentFileInfo64 rc=%d", rc); return true; - } else if ((rc = unzOpenCurrentFile(zipfile)) != UNZ_OK) { + } else if ((rc = unzOpenCurrentFilePassword(zipfile, pwd)) != UNZ_OK) { sprintf(g->Message, "unzOpen fn=%s rc=%d", fn, rc); return true; } // endif rc @@ -675,15 +696,17 @@ void UNZIPUTL::closeEntry() UNZFAM::UNZFAM(PDOSDEF tdp) : MAPFAM(tdp) { zutp = NULL; - target = tdp->GetEntry(); - mul = tdp->GetMul(); + tdfp = tdp; + //target = tdp->GetEntry(); + //mul = tdp->GetMul(); } // end of UNZFAM standard constructor UNZFAM::UNZFAM(PUNZFAM txfp) : MAPFAM(txfp) { zutp = txfp->zutp; - target = txfp->target; - mul = txfp->mul; + tdfp = txfp->tdfp; + //target = txfp->target; + //mul = txfp->mul; } // end of UNZFAM copy constructor /***********************************************************************/ @@ -726,7 +749,7 @@ bool UNZFAM::OpenTableFile(PGLOBAL g) /*********************************************************************/ /* Allocate the ZIP utility class. */ /*********************************************************************/ - zutp = new(g) UNZIPUTL(target, mul); + zutp = new(g) UNZIPUTL(tdfp); // We used the file name relative to recorded datapath PlugSetPath(filename, To_File, Tdbp->GetPath()); @@ -841,17 +864,19 @@ void UNZFAM::CloseTableFile(PGLOBAL g, bool) UZXFAM::UZXFAM(PDOSDEF tdp) : MPXFAM(tdp) { zutp = NULL; - target = tdp->GetEntry(); - mul = tdp->GetMul(); + tdfp = tdp; + //target = tdp->GetEntry(); + //mul = tdp->GetMul(); //Lrecl = tdp->GetLrecl(); } // end of UZXFAM standard constructor UZXFAM::UZXFAM(PUZXFAM txfp) : MPXFAM(txfp) { zutp = txfp->zutp; - target = txfp->target; - mul = txfp->mul; -//Lrecl = txfp->Lrecl; + tdfp = txfp->tdfp; + //target = txfp->target; + //mul = txfp->mul; + //Lrecl = txfp->Lrecl; } // end of UZXFAM copy constructor /***********************************************************************/ @@ -907,7 +932,7 @@ bool UZXFAM::OpenTableFile(PGLOBAL g) /* Allocate the ZIP utility class. */ /*********************************************************************/ if (!zutp) - zutp = new(g)UNZIPUTL(target, mul); + zutp = new(g)UNZIPUTL(tdfp); // We used the file name relative to recorded datapath PlugSetPath(filename, To_File, Tdbp->GetPath()); diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h index 3160703bd20..2f9e491f621 100644 --- a/storage/connect/filamzip.h +++ b/storage/connect/filamzip.h @@ -45,6 +45,7 @@ class DllExport ZIPUTIL : public BLOCK { // Members zipFile zipfile; // The ZIP container file PSZ target; // The target file name + PSZ pwd; // The ZIP file password //unz_file_info finfo; // The current file info PFBLOCK fp; //char *memory; @@ -61,8 +62,8 @@ class DllExport ZIPUTIL : public BLOCK { class DllExport UNZIPUTL : public BLOCK { public: // Constructor - UNZIPUTL(PSZ tgt, bool mul); -//UNZIPUTL(UNZIPUTL *zutp); + UNZIPUTL(PSZ tgt, bool mul); + UNZIPUTL(PDOSDEF tdp); // Implementation //PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UNZFAM(this); } @@ -80,6 +81,7 @@ class DllExport UNZIPUTL : public BLOCK { // Members unzFile zipfile; // The ZIP container file PSZ target; // The target file name + PSZ pwd; // The ZIP file password unz_file_info finfo; // The current file info PFBLOCK fp; char *memory; @@ -119,8 +121,9 @@ class DllExport UNZFAM : public MAPFAM { protected: // Members UNZIPUTL *zutp; - PSZ target; - bool mul; + PDOSDEF tdfp; +//PSZ target; +//bool mul; }; // end of UNZFAM /***********************************************************************/ @@ -147,8 +150,9 @@ class DllExport UZXFAM : public MPXFAM { protected: // Members UNZIPUTL *zutp; - PSZ target; - bool mul; + PDOSDEF tdfp; +//PSZ target; +//bool mul; }; // end of UZXFAM /***********************************************************************/ diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index f1bbef19a22..02d3fc176ce 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -98,6 +98,7 @@ DOSDEF::DOSDEF(void) Ofn = NULL; Entry = NULL; To_Indx = NULL; + Pwd = NULL; Recfm = RECFM_VAR; Mapped = false; Zipped = false; @@ -139,7 +140,8 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int) : false; Mulentries = GetBoolCatInfo("Mulentries", Mulentries); Append = GetBoolCatInfo("Append", false); - } + Pwd = GetStringCatInfo(g, "Password", NULL); + } // endif Zipped Desc = Fn = GetStringCatInfo(g, "Filename", NULL); Ofn = GetStringCatInfo(g, "Optname", Fn); diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h index 922d52ee399..c404328a675 100644 --- a/storage/connect/tabdos.h +++ b/storage/connect/tabdos.h @@ -77,6 +77,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */ PSZ Fn; /* Path/Name of corresponding file */ PSZ Ofn; /* Base Path/Name of matching index files*/ PSZ Entry; /* Zip entry name or pattern */ + PSZ Pwd; /* Zip password */ PIXDEF To_Indx; /* To index definitions blocks */ RECFM Recfm; /* 0:VAR, 1:FIX, 2:BIN, 3:VCT, 6:DBF */ bool Mapped; /* 0: disk file, 1: memory mapped file */ From ff6f4d7db11c1b8960376de3035b9e498fac5d34 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 3 Apr 2017 15:18:46 +0000 Subject: [PATCH 051/148] Windows : Fix compiling with VS2013 We do not use it now, but there is still no reason to break compilation for other users. --- storage/xtradb/btr/btr0cur.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc index 1705de7ce36..dcb197a761f 100644 --- a/storage/xtradb/btr/btr0cur.cc +++ b/storage/xtradb/btr/btr0cur.cc @@ -3863,7 +3863,7 @@ static const unsigned rows_in_range_max_retries = 4; /** We pretend that a range has that many records if the tree keeps changing for rows_in_range_max_retries retries while we try to estimate the records in a given range. */ -static const int64_t rows_in_range_arbitrary_ret_val = 10; +static const ib_int64_t rows_in_range_arbitrary_ret_val = 10; /** Estimates the number of rows in a given index range. @param[in] index index @@ -3881,7 +3881,7 @@ rows_in_range_arbitrary_ret_val as a result (if nth_attempt >= rows_in_range_max_retries and the tree is modified between the two dives). */ static -int64_t +ib_int64_t btr_estimate_n_rows_in_range_low( dict_index_t* index, const dtuple_t* tuple1, @@ -4017,7 +4017,7 @@ btr_estimate_n_rows_in_range_low( return(rows_in_range_arbitrary_ret_val); } - const int64_t ret = + const ib_int64_t ret = btr_estimate_n_rows_in_range_low( index, tuple1, mode1, tuple2, mode2, trx, @@ -4083,7 +4083,7 @@ btr_estimate_n_rows_in_range_low( @param[in] mode2 search mode for range end @param[in] trx trx @return estimated number of rows */ -int64_t +ib_int64_t btr_estimate_n_rows_in_range( dict_index_t* index, const dtuple_t* tuple1, @@ -4092,7 +4092,7 @@ btr_estimate_n_rows_in_range( ulint mode2, trx_t* trx) { - const int64_t ret = btr_estimate_n_rows_in_range_low( + const ib_int64_t ret = btr_estimate_n_rows_in_range_low( index, tuple1, mode1, tuple2, mode2, trx, 1 /* first attempt */); From f2dc04abea172e4c5d701a749902c88f4a626c2c Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 3 Apr 2017 18:48:48 +0000 Subject: [PATCH 052/148] Compiling, Windows . Avoid unnecessary rebuilds with MSVC. To export symbols from the mysqld.exe, use lib.exe with /DEF, rather than pre-link step when building mysqld.exe. This helps to avoid relinking all plugins, if mysqld.exe was recompiled but the list of its exports has not changed. Also removed unnecessary DEPENDS in some ADD_CUSTOM_COMMAND (gen_lex_token, gen_lex_hash etc). They confuse VS generator which tends to recreate headers and do unnecessary recompilations. --- cmake/plugin.cmake | 11 +++++- sql/CMakeLists.txt | 83 +++++++++++++++++++++++++++++++----------- win/create_def_file.js | 46 ++++++++++++++++++++--- 3 files changed, 111 insertions(+), 29 deletions(-) diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index e1d2af2add6..ba7bac837b1 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -179,8 +179,15 @@ MACRO(MYSQL_ADD_PLUGIN) # executable to the linker command line (it would result into link error). # Thus we skip TARGET_LINK_LIBRARIES on Linux, as it would only generate # an additional dependency. - IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") - TARGET_LINK_LIBRARIES (${target} mysqld ${ARG_LINK_LIBRARIES}) + IF(MSVC) + ADD_DEPENDENCIES(${target} gen_mysqld_lib) + TARGET_LINK_LIBRARIES(${target} mysqld_import_lib) + ELSEIF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + TARGET_LINK_LIBRARIES (${target} mysqld) + ENDIF() + + IF(ARG_LINK_LIBRARIES) + TARGET_LINK_LIBRARIES (${target} ${ARG_LINK_LIBRARIES}) ENDIF() ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES}) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 652664fa438..5cdf597301f 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -46,7 +46,6 @@ ENDIF() ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h COMMAND gen_lex_token > lex_token.h - DEPENDS gen_lex_token ) ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER) @@ -150,6 +149,63 @@ ELSE() SET(MYSQLD_SOURCE main.cc ${DTRACE_PROBES_ALL}) ENDIF() + +IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS) + + # mysqld.exe must to export symbols from some specific libs. + # These symbols are used by dynamic plugins, that "link" to mysqld. + # + # To do that, we + # + # 1. Generate mysqld_lib.def text file with all symbols from static + # libraries mysys, dbug, strings, sql. + # 2. Then we call + # lib.exe /DEF:mysqld_lib.def ... + # to create import library mysqld_lib.lib and export library mysqld_lib.exp + # 3. mysqld.exe links with mysqld_lib.exp (exporting symbols) + # 4. plugins link with mysqld_lib.lib (importing symbols) + # + # We do not not regenerate .def, .lib and .exp + # without necessity.E.g source modifications, that do not + # change list of exported symbols, will not result in a relink for plugins. + + SET(MYSQLD_DEF ${CMAKE_CURRENT_BINARY_DIR}/mysqld_lib.def) + SET(MYSQLD_EXP ${CMAKE_CURRENT_BINARY_DIR}/mysqld_lib.exp) + SET(MYSQLD_LIB ${CMAKE_CURRENT_BINARY_DIR}/mysqld_lib.lib) + SET(MYSQLD_CORELIBS sql mysys mysys_ssl dbug strings) + FOREACH (CORELIB ${MYSQLD_CORELIBS}) + GET_TARGET_PROPERTY(LOC ${CORELIB} LOCATION) + FILE(TO_NATIVE_PATH ${LOC} LOC) + SET (LIB_LOCATIONS ${LIB_LOCATIONS} ${LOC}) + ENDFOREACH (CORELIB) + + SET(_PLATFORM x86) + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(_PLATFORM x64) + ENDIF() + + ADD_CUSTOM_COMMAND( + OUTPUT ${MYSQLD_DEF} + COMMAND cscript ARGS //nologo ${PROJECT_SOURCE_DIR}/win/create_def_file.js + ${_PLATFORM} /forLib ${LIB_LOCATIONS} > mysqld_lib.def.tmp + COMMAND ${CMAKE_COMMAND} -E copy_if_different mysqld_lib.def.tmp mysqld_lib.def + COMMAND ${CMAKE_COMMAND} -E remove mysqld_lib.def.tmp + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${MYSQLD_CORELIBS} + ) + + ADD_CUSTOM_COMMAND( + OUTPUT ${MYSQLD_LIB} + COMMAND lib + ARGS /NAME:mysqld.exe "/DEF:${MYSQLD_DEF}" "/MACHINE:${_PLATFORM}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${MYSQLD_DEF} + ) + ADD_CUSTOM_TARGET(gen_mysqld_lib DEPENDS ${MYSQLD_LIB}) + ADD_LIBRARY(mysqld_import_lib UNKNOWN IMPORTED GLOBAL) + SET_TARGET_PROPERTIES(mysqld_import_lib PROPERTIES IMPORTED_LOCATION ${MYSQLD_LIB}) +ENDIF() + MYSQL_ADD_EXECUTABLE(mysqld ${MYSQLD_SOURCE} DESTINATION ${INSTALL_SBINDIR} COMPONENT Server) IF(APPLE) @@ -170,25 +226,9 @@ IF(NOT WITHOUT_DYNAMIC_PLUGINS) SET_TARGET_PROPERTIES(mysqld PROPERTIES LINK_FLAGS "${mysqld_link_flags} -Wl,--export-all-symbols") ENDIF() IF(MSVC) - # Set module definition file. Also use non-incremental linker, - # incremental appears to crash from time to time,if used with /DEF option - SET_TARGET_PROPERTIES(mysqld PROPERTIES LINK_FLAGS "${mysqld_link_flags} /DEF:mysqld.def /INCREMENTAL:NO") - - FOREACH (CORELIB sql mysys mysys_ssl dbug strings) - GET_TARGET_PROPERTY(LOC ${CORELIB} LOCATION) - FILE(TO_NATIVE_PATH ${LOC} LOC) - SET (LIB_LOCATIONS ${LIB_LOCATIONS} ${LOC}) - ENDFOREACH (CORELIB ${MYSQLD_CORE_LIBS}) - SET(_PLATFORM x86) - IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(_PLATFORM x64) - ENDIF() - ADD_CUSTOM_COMMAND(TARGET mysqld PRE_LINK - COMMAND echo ${_PLATFORM} && cscript ARGS //nologo ${PROJECT_SOURCE_DIR}/win/create_def_file.js - ${_PLATFORM} ${LIB_LOCATIONS} > mysqld.def - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - ADD_DEPENDENCIES(sql GenError) - ENDIF(MSVC) + SET_TARGET_PROPERTIES(mysqld PROPERTIES LINK_FLAGS "${mysqld_link_flags} \"${MYSQLD_EXP}\"") + ADD_DEPENDENCIES(mysqld gen_mysqld_lib) + ENDIF() ENDIF(NOT WITHOUT_DYNAMIC_PLUGINS) SET_TARGET_PROPERTIES(mysqld PROPERTIES ENABLE_EXPORTS TRUE) @@ -254,7 +294,6 @@ ENDIF() ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h COMMAND gen_lex_hash > lex_hash.h - DEPENDS gen_lex_hash ) MYSQL_ADD_EXECUTABLE(mysql_tzinfo_to_sql tztime.cc COMPONENT Server) @@ -379,7 +418,7 @@ IF(WIN32) ${CMAKE_CURRENT_BINARY_DIR}/my_bootstrap.sql mysql_bootstrap_sql.c WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS comp_sql ${my_bootstrap_sql} + DEPENDS ${my_bootstrap_sql} ) MYSQL_ADD_EXECUTABLE(mysql_install_db diff --git a/win/create_def_file.js b/win/create_def_file.js index 5fb28ef0bee..25bbbb4eb3d 100644 --- a/win/create_def_file.js +++ b/win/create_def_file.js @@ -54,6 +54,22 @@ var is64 = args.Item(0).toLowerCase() == "x64"; var shell = new ActiveXObject("WScript.Shell"); var fso = new ActiveXObject("Scripting.FileSystemObject"); +/* + If .def file is used with together with lib.exe + the name mangling for stdcall is slightly different. + + Undescore prefix for stdcall function name must be removed for + lib.exe but not link.exe (see ScrubSymbol()) + + This difference is not documented anywhere and could + be a bug in compiler tools. + + We use a parameter /forLib, if the resulting .def file is used + with lib.exe . +*/ +var forLib = false; + + OutputSymbols(CollectSymbols()); @@ -62,8 +78,8 @@ function OutputSymbols(symbols) { var out = WScript.StdOut; out.WriteLine("EXPORTS"); - for (var sym in symbols) - out.WriteLine(sym); + for (var i= 0; i < symbols.length; i++) + out.WriteLine(symbols[i]); } function echo(message) @@ -72,9 +88,10 @@ function echo(message) } // Extract global symbol names and type from objects +// Returns string array with symbol names function CollectSymbols() { - var uniqueSymbols = new Array(); + var uniqueSymbols = new Object(); try { @@ -146,7 +163,19 @@ function CollectSymbols() uniqueSymbols[symbol] = 1; } fso.DeleteFile(rspfilename); - return uniqueSymbols; + // Sort symbols names + var keys=[]; + var sorted = {}; + for (key in uniqueSymbols) + { + if (uniqueSymbols.hasOwnProperty(key)) + { + keys.push(key); + } + } + keys.sort(); + + return keys; } // performs necessary cleanup on the symbol name @@ -156,6 +185,9 @@ function ScrubSymbol(symbol) if (symbol.charAt(0) != "_") return symbol; + if (forLib) + return symbol.substring(1, symbol.length); + var atSign = symbol.indexOf("@"); if (atSign != -1) { @@ -189,7 +221,11 @@ function CreateResponseFile(filename) var index = 1; for (; index < args.length; index++) { - addToResponseFile(args.Item(index),responseFile); + var param = args.Item(index); + if (param == "/forLib") + forLib = true; + else + addToResponseFile(args.Item(index),responseFile); } responseFile.Close(); } From b0395d8701ec49f49ad23f9917a3b2369bb49e7a Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 4 Apr 2017 10:04:52 -0700 Subject: [PATCH 053/148] Fixed the bug mdev-12429 and its duplicates mdev-12145 and mdev-9886. Also fixed a wrong result for a test case for mdev-7691 (the alternative one). The test cases for all these bug have materialized semi-joins used inside dependent sub-queries. The patch actually reverts the change inroduced by Monty in 2003. It looks like this change is not valid anymore after the implementation of semi-joins. Adjusted output from EXPLAIN for many other test cases. --- mysql-test/r/innodb_icp,innodb_plugin.rdiff | 4 +- mysql-test/r/innodb_icp.result | 2 +- mysql-test/r/join_outer.result | 2 +- mysql-test/r/join_outer_jcl6.result | 2 +- mysql-test/r/myisam_icp.result | 4 +- mysql-test/r/subselect3.result | 8 +- mysql-test/r/subselect3_jcl6.result | 8 +- mysql-test/r/subselect4.result | 8 +- mysql-test/r/subselect_innodb.result | 2 +- mysql-test/r/subselect_mat.result | 109 ++++++++++++++++++++ mysql-test/r/subselect_sj.result | 2 +- mysql-test/r/subselect_sj_jcl6.result | 2 +- mysql-test/r/subselect_sj_mat.result | 109 ++++++++++++++++++++ mysql-test/t/subselect_sj_mat.test | 87 ++++++++++++++++ sql/sql_select.cc | 2 +- 15 files changed, 329 insertions(+), 22 deletions(-) diff --git a/mysql-test/r/innodb_icp,innodb_plugin.rdiff b/mysql-test/r/innodb_icp,innodb_plugin.rdiff index 3cb85b79ece..f8ac1186f4a 100644 --- a/mysql-test/r/innodb_icp,innodb_plugin.rdiff +++ b/mysql-test/r/innodb_icp,innodb_plugin.rdiff @@ -1,5 +1,5 @@ ---- r/innodb_icp.result 2013-07-16 17:01:00.000000000 +0400 -+++ r/innodb_icp,innodb_plugin.reject 2013-07-16 17:16:53.000000000 +0400 +--- innodb_icp.result 2017-04-02 23:39:45.063149325 -0700 ++++ innodb_icp,innodb_plugin.result 2017-04-02 23:36:33.279164925 -0700 @@ -213,7 +213,7 @@ EXPLAIN SELECT c1 FROM t3 WHERE c1 >= 'c-1004=w' and c1 <= 'c-1006=w' and i1 > 2; diff --git a/mysql-test/r/innodb_icp.result b/mysql-test/r/innodb_icp.result index e34a4469de2..9ca02595939 100644 --- a/mysql-test/r/innodb_icp.result +++ b/mysql-test/r/innodb_icp.result @@ -432,7 +432,7 @@ WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON it.i=it.i WHERE it.pk-t1.i<10 id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where 2 DEPENDENT SUBQUERY it eq_ref PRIMARY PRIMARY 4 func 1 Using where -2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join) SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON it.i=it.i WHERE it.pk-t1.i<10); pk i diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 40abc197a36..5dbb0f1d8b6 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1744,7 +1744,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 2 100.00 Using where; Using index; Using temporary; Using filesort 1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 func 1 100.00 Using where; Using index 2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 func 1 100.00 Using where; Using index -2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t3.pk 1 100.00 Using where; Using index +2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t3.pk 1 100.00 Using index Warnings: Note 1276 Field or reference 'test.t2.pk' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t2`.`pk` AS `pk`,<`test`.`t2`.`pk`>((select (`test`.`t3`.`pk` + if(isnull(`test`.`t4`.`pk`),0,`test`.`t4`.`pk`)) from `test`.`t3` left join `test`.`t4` on((`test`.`t4`.`pk` = `test`.`t3`.`pk`)) where (`test`.`t3`.`pk` = (`test`.`t2`.`pk` + 1000)) limit 1)) AS `t` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`pk` = (`test`.`t1`.`pk` + 1000)) and (`test`.`t1`.`pk` > 1000)) group by `test`.`t2`.`pk` diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result index 81395612269..bdc4be0cb8c 100644 --- a/mysql-test/r/join_outer_jcl6.result +++ b/mysql-test/r/join_outer_jcl6.result @@ -1755,7 +1755,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 2 100.00 Using where; Using index; Using temporary; Using filesort 1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 func 1 100.00 Using where; Using index 2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 func 1 100.00 Using where; Using index -2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t3.pk 1 100.00 Using where; Using index +2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t3.pk 1 100.00 Using index Warnings: Note 1276 Field or reference 'test.t2.pk' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t2`.`pk` AS `pk`,<`test`.`t2`.`pk`>((select (`test`.`t3`.`pk` + if(isnull(`test`.`t4`.`pk`),0,`test`.`t4`.`pk`)) from `test`.`t3` left join `test`.`t4` on((`test`.`t4`.`pk` = `test`.`t3`.`pk`)) where (`test`.`t3`.`pk` = (`test`.`t2`.`pk` + 1000)) limit 1)) AS `t` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`pk` = (`test`.`t1`.`pk` + 1000)) and (`test`.`t1`.`pk` > 1000)) group by `test`.`t2`.`pk` diff --git a/mysql-test/r/myisam_icp.result b/mysql-test/r/myisam_icp.result index 2c157102270..9b31bca7932 100644 --- a/mysql-test/r/myisam_icp.result +++ b/mysql-test/r/myisam_icp.result @@ -436,7 +436,7 @@ WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON it.i=it.i WHERE it.pk-t1.i<10 id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where 2 DEPENDENT SUBQUERY it eq_ref PRIMARY PRIMARY 4 func 1 Using index condition -2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join) SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON it.i=it.i WHERE it.pk-t1.i<10); pk i @@ -797,7 +797,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t ALL PRIMARY,c NULL NULL NULL 64 Using where 1 PRIMARY t2 ref g g 5 test.t.c 19 Using where 2 DEPENDENT SUBQUERY t1 index PRIMARY PRIMARY 4 NULL 64 Using where; Using index -2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using index condition; Using where +2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where SELECT COUNT(*) FROM t1 AS t, t2 WHERE c = g AND (EXISTS (SELECT * FROM t1, t2 WHERE a = f AND h <= t.e AND a > t.b) diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 487ffe655c1..796f4a6f872 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -266,7 +266,7 @@ from t2; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 2 DEPENDENT SUBQUERY t1 ref_or_null a a 5 func 2 100.00 Using where; Full scan on NULL key -2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 100 100.00 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join) Warnings: Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(((`test`.`t2`.`a`,`test`.`t2`.`b`),(select `test`.`t1`.`a`,`test`.`t1`.`b` from `test`.`t1` join `test`.`t4` where ((`test`.`t1`.`c` = `test`.`t2`.`oref`) and trigcond((((`test`.`t2`.`a`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`))) and trigcond((((`test`.`t2`.`b`) = `test`.`t1`.`b`) or isnull(`test`.`t1`.`b`)))) having (trigcond((`test`.`t1`.`a`)) and trigcond((`test`.`t1`.`b`)))))) AS `Z` from `test`.`t2` @@ -1240,19 +1240,19 @@ explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where 2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 10 Using where -2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where 2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 10 Using where -2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) explain select straight_join * from t2 X, t2 Y where X.a in (select straight_join A.a from t1 A, t1 B); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY X ALL NULL NULL NULL NULL 10 Using where 1 PRIMARY Y ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 10 Using where -2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) create table t0 (a int, b int); insert into t0 values(1,1); explain select * from t0, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30); diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result index 9cd3018718c..f3f1ee546ff 100644 --- a/mysql-test/r/subselect3_jcl6.result +++ b/mysql-test/r/subselect3_jcl6.result @@ -276,7 +276,7 @@ from t2; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 2 DEPENDENT SUBQUERY t1 ref_or_null a a 5 func 2 100.00 Using where; Full scan on NULL key -2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 100 100.00 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join) Warnings: Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(((`test`.`t2`.`a`,`test`.`t2`.`b`),(select `test`.`t1`.`a`,`test`.`t1`.`b` from `test`.`t1` join `test`.`t4` where ((`test`.`t1`.`c` = `test`.`t2`.`oref`) and trigcond((((`test`.`t2`.`a`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`))) and trigcond((((`test`.`t2`.`b`) = `test`.`t1`.`b`) or isnull(`test`.`t1`.`b`)))) having (trigcond((`test`.`t1`.`a`)) and trigcond((`test`.`t1`.`b`)))))) AS `Z` from `test`.`t2` @@ -1250,19 +1250,19 @@ explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where 2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 10 Using where -2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where 2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 10 Using where -2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) explain select straight_join * from t2 X, t2 Y where X.a in (select straight_join A.a from t1 A, t1 B); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY X ALL NULL NULL NULL NULL 10 Using where 1 PRIMARY Y ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 10 Using where -2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) create table t0 (a int, b int); insert into t0 values(1,1); explain select * from t0, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30); diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 2228609b82c..d3c63ff9a2f 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -19,7 +19,7 @@ SELECT 1 FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE 1 = (SELECT MIN(t2.b) FROM t3)) ORDER BY count(*); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL a 5 NULL 2 Using where; Using index; Using temporary +1 PRIMARY t1 index NULL a 5 NULL 2 Using index; Using temporary 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where 3 DEPENDENT SUBQUERY t3 system NULL NULL NULL NULL 0 const row not found # should not crash the next statement @@ -1418,7 +1418,7 @@ GROUP BY f9; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE 3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 SELECT COUNT(t2.f3), (SELECT COUNT(f3) FROM t1 WHERE t2.f1) AS f9 FROM t2 JOIN t1 ON t1.f3 @@ -1434,7 +1434,7 @@ ORDER BY f9; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE 3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 SELECT COUNT(t2.f3), (SELECT COUNT(f3) FROM t1 WHERE t2.f1) AS f9 FROM t2 JOIN t1 ON t1.f3 @@ -2444,9 +2444,11 @@ WHERE EXISTS ( )"; EXECUTE stmt; i +4 6 EXECUTE stmt; i +4 6 drop table t1, t2, t3; # diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index e8a545778aa..06cfb8b45d2 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -273,7 +273,7 @@ EXPLAIN SELECT 1 FROM t1 WHERE NOT EXISTS id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 1 Using where 2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY,d d 2 func 1 Using where -3 DEPENDENT SUBQUERY t2 index NULL d 2 NULL 1 Using where; Using index +3 DEPENDENT SUBQUERY t2 index NULL d 2 NULL 1 Using index DROP TABLE t2; CREATE TABLE t2 (b INT, c INT, UNIQUE KEY (b), UNIQUE KEY (b, c )) ENGINE=INNODB; INSERT INTO t2 VALUES (1, 1); diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index e4843929fcb..ffa37b025eb 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -2163,6 +2163,115 @@ execute stmt; a 0 drop table t1; +# +# MDEV-12429: IN subquery used in WHERE of EXISTS subquery +# +CREATE TABLE t1 ( +pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); +SELECT sq1.f2 FROM t1 AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +f2 +foo +EXPLAIN +SELECT sq1.f2 FROM t1 AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY sq1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 +2 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 +# this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT sq1.f2 FROM t1 AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +f2 +foo +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1; +# +# MDEV-12145: IN subquery used in WHERE of EXISTS subquery +# +CREATE TABLE t1 (f1 INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (4),(6); +CREATE TABLE t2 (i2 INT, KEY(i2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (8),(7),(1); +CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM; +INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5); +SELECT * FROM t1 +WHERE EXISTS ( SELECT * FROM t2, t3 +WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +f1 +6 +EXPLAIN EXTENDED +SELECT * FROM t1 +WHERE EXISTS ( SELECT * FROM t2, t3 +WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where +2 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 DEPENDENT SUBQUERY t2 index i2 i2 5 NULL 3 100.00 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t3 ref i3 i3 5 test.t2.i2 2 100.00 Using index +3 MATERIALIZED t3 ALL NULL NULL NULL NULL 8 100.00 +Warnings: +Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`f1` = `test`.`t3`.`f3`)))) +# this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT * FROM t1 +WHERE EXISTS ( SELECT * FROM t2, t3 +WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +f1 +6 +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1,t2,t3; +# +# MDEV-9686: IN subquery used in WHERE of a subquery from select list +# +CREATE TABLE t1 (pk INT PRIMARY KEY, f1 INT); +INSERT INTO t1 VALUES (1, 4),(2, 3),(3, 3),(4, 6),(5, 3); +CREATE TABLE t2 (f2 INT); +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +# t1.pk is always IN ( SELECT f2 FROM t2 ), +# so the IN condition should be true for every row, +# and thus COUNT(*) should always return 5 +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 +WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +pk f1 sq +1 4 5 +2 3 5 +3 3 5 +4 6 5 +5 3 5 +EXPLAIN EXTENDED +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 +WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 +2 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using join buffer (flat, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 +Warnings: +Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`f1` AS `f1`,<`test`.`t1`.`pk`>((select count(0) from `test`.`t2` semi join (`test`.`t2`) where (`test`.`t1`.`pk` = `test`.`t2`.`f2`))) AS `sq` from `test`.`t1` +# this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 +WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +pk f1 sq +1 4 5 +2 3 5 +3 3 5 +4 6 5 +5 3 5 +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1,t2; # End of 5.5 tests set @subselect_mat_test_optimizer_switch_value=null; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off'; diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 1662d4eb14a..50a70a6614a 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -177,7 +177,7 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY m16 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY m17 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY m18 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join) -2 DEPENDENT SUBQUERY m19 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY m19 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join) select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t10)) where t1.a < 5; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 96bae673184..ccf348fa311 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -190,7 +190,7 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY m16 ALL NULL NULL NULL NULL 3 Using join buffer (incremental, BNL join) 2 DEPENDENT SUBQUERY m17 ALL NULL NULL NULL NULL 3 Using join buffer (incremental, BNL join) 2 DEPENDENT SUBQUERY m18 ALL NULL NULL NULL NULL 3 Using join buffer (incremental, BNL join) -2 DEPENDENT SUBQUERY m19 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (incremental, BNL join) +2 DEPENDENT SUBQUERY m19 ALL NULL NULL NULL NULL 3 Using join buffer (incremental, BNL join) select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t10)) where t1.a < 5; diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index cfcbf612030..47f578fb589 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -2203,4 +2203,113 @@ execute stmt; a 0 drop table t1; +# +# MDEV-12429: IN subquery used in WHERE of EXISTS subquery +# +CREATE TABLE t1 ( +pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); +SELECT sq1.f2 FROM t1 AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +f2 +foo +EXPLAIN +SELECT sq1.f2 FROM t1 AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY sq1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 +2 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 +# this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT sq1.f2 FROM t1 AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +f2 +foo +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1; +# +# MDEV-12145: IN subquery used in WHERE of EXISTS subquery +# +CREATE TABLE t1 (f1 INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (4),(6); +CREATE TABLE t2 (i2 INT, KEY(i2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (8),(7),(1); +CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM; +INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5); +SELECT * FROM t1 +WHERE EXISTS ( SELECT * FROM t2, t3 +WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +f1 +6 +EXPLAIN EXTENDED +SELECT * FROM t1 +WHERE EXISTS ( SELECT * FROM t2, t3 +WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where +2 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 DEPENDENT SUBQUERY t2 index i2 i2 5 NULL 3 100.00 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t3 ref i3 i3 5 test.t2.i2 2 100.00 Using index +3 MATERIALIZED t3 ALL NULL NULL NULL NULL 8 100.00 +Warnings: +Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`f1` = `test`.`t3`.`f3`)))) +# this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT * FROM t1 +WHERE EXISTS ( SELECT * FROM t2, t3 +WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +f1 +6 +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1,t2,t3; +# +# MDEV-9686: IN subquery used in WHERE of a subquery from select list +# +CREATE TABLE t1 (pk INT PRIMARY KEY, f1 INT); +INSERT INTO t1 VALUES (1, 4),(2, 3),(3, 3),(4, 6),(5, 3); +CREATE TABLE t2 (f2 INT); +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +# t1.pk is always IN ( SELECT f2 FROM t2 ), +# so the IN condition should be true for every row, +# and thus COUNT(*) should always return 5 +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 +WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +pk f1 sq +1 4 5 +2 3 5 +3 3 5 +4 6 5 +5 3 5 +EXPLAIN EXTENDED +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 +WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 +2 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using join buffer (flat, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 +Warnings: +Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`f1` AS `f1`,<`test`.`t1`.`pk`>((select count(0) from `test`.`t2` semi join (`test`.`t2`) where (`test`.`t1`.`pk` = `test`.`t2`.`f2`))) AS `sq` from `test`.`t1` +# this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 +WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +pk f1 sq +1 4 5 +2 3 5 +3 3 5 +4 6 5 +5 3 5 +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1,t2; # End of 5.5 tests diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test index dd30b21201d..cd71ae5c901 100644 --- a/mysql-test/t/subselect_sj_mat.test +++ b/mysql-test/t/subselect_sj_mat.test @@ -1857,4 +1857,91 @@ execute stmt; drop table t1; +--echo # +--echo # MDEV-12429: IN subquery used in WHERE of EXISTS subquery +--echo # + +CREATE TABLE t1 ( + pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); + +SELECT sq1.f2 FROM t1 AS sq1 + WHERE EXISTS ( SELECT * FROM t1 AS sq2 + WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); + +EXPLAIN +SELECT sq1.f2 FROM t1 AS sq1 + WHERE EXISTS ( SELECT * FROM t1 AS sq2 + WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); + +--echo # this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT sq1.f2 FROM t1 AS sq1 + WHERE EXISTS ( SELECT * FROM t1 AS sq2 + WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +set optimizer_switch= @save_optimizer_switch; + +DROP TABLE t1; + +--echo # +--echo # MDEV-12145: IN subquery used in WHERE of EXISTS subquery +--echo # + +CREATE TABLE t1 (f1 INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (4),(6); + +CREATE TABLE t2 (i2 INT, KEY(i2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (8),(7),(1); + +CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM; +INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5); + +SELECT * FROM t1 + WHERE EXISTS ( SELECT * FROM t2, t3 + WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +EXPLAIN EXTENDED +SELECT * FROM t1 + WHERE EXISTS ( SELECT * FROM t2, t3 + WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); + +--echo # this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT * FROM t1 + WHERE EXISTS ( SELECT * FROM t2, t3 + WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); +set optimizer_switch= @save_optimizer_switch; + +DROP TABLE t1,t2,t3; + +--echo # +--echo # MDEV-9686: IN subquery used in WHERE of a subquery from select list +--echo # + +CREATE TABLE t1 (pk INT PRIMARY KEY, f1 INT); +INSERT INTO t1 VALUES (1, 4),(2, 3),(3, 3),(4, 6),(5, 3); + +CREATE TABLE t2 (f2 INT); +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); + +--echo # t1.pk is always IN ( SELECT f2 FROM t2 ), +--echo # so the IN condition should be true for every row, +--echo # and thus COUNT(*) should always return 5 + +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 + WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +EXPLAIN EXTENDED +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 + WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; + +--echo # this checks the result set above +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch= 'materialization=off,semijoin=off'; +SELECT pk, f1, ( SELECT COUNT(*) FROM t2 + WHERE t1.pk IN ( SELECT f2 FROM t2 ) ) AS sq FROM t1; +set optimizer_switch= @save_optimizer_switch; + +DROP TABLE t1,t2; + --echo # End of 5.5 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 43b3b6bf47b..d83e8e2bfce 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8794,7 +8794,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5 */ if (tab == join->join_tab + join->top_join_tab_count - 1) - current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT; + current_map|= RAND_TABLE_BIT; used_tables|=current_map; if (tab->type == JT_REF && tab->quick && From 8e36216a06603942613f8157b9b790e98f90d608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 5 Apr 2017 14:46:35 +0300 Subject: [PATCH 054/148] =?UTF-8?q?Import=20two=20ALTER=20TABLE=E2=80=A6AL?= =?UTF-8?q?GORITHM=3DINPLACE=20tests=20from=20MySQL=205.6.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, revert part of MDEV-7685 that added an InnoDB abort when ALTER TABLE…ALGORITHM=INPLACE is reporting that it ran out of file space. --- .../suite/innodb/r/innodb-alter-debug.result | 56 +++++++++++++ .../innodb/r/innodb-alter-nullable.result | 53 +++++++++++++ .../suite/innodb/t/innodb-alter-debug.test | 79 +++++++++++++++++++ .../suite/innodb/t/innodb-alter-nullable.test | 76 ++++++++++++++++++ storage/innobase/handler/handler0alter.cc | 1 - storage/xtradb/handler/handler0alter.cc | 1 - 6 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-alter-debug.result create mode 100644 mysql-test/suite/innodb/r/innodb-alter-nullable.result create mode 100644 mysql-test/suite/innodb/t/innodb-alter-debug.test create mode 100644 mysql-test/suite/innodb/t/innodb-alter-nullable.test diff --git a/mysql-test/suite/innodb/r/innodb-alter-debug.result b/mysql-test/suite/innodb/r/innodb-alter-debug.result new file mode 100644 index 00000000000..78976030ac8 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-alter-debug.result @@ -0,0 +1,56 @@ +SET NAMES utf8; +CREATE TABLE ① ( +c1 INT PRIMARY KEY, c2 INT DEFAULT 1, ct TEXT, INDEX(c2)) +ENGINE = InnoDB; +CREATE TABLE t1ć (c1 INT PRIMARY KEY, c2 INT, INDEX(c2), +CONSTRAINT t1c2 FOREIGN KEY (c2) REFERENCES ①(c2)) +ENGINE=InnoDB; +INSERT INTO ① SET c1 = 1; +SET @saved_debug_dbug = @@SESSION.debug_dbug; +SET DEBUG_DBUG = '+d,ib_drop_foreign_error'; +ALTER TABLE t1ć DROP FOREIGN KEY t1c2, RENAME TO ②; +ERROR HY000: The table 't1ć' is full +SET DEBUG_DBUG = @saved_debug_dbug; +SET DEBUG_DBUG = '+d,ib_rename_column_error'; +ALTER TABLE ① CHANGE c2 š INT; +ERROR HY000: The table '①' is full +SET DEBUG_DBUG = @saved_debug_dbug; +SHOW CREATE TABLE t1ć; +Table Create Table +t1ć CREATE TABLE `t1ć` ( + `c1` int(11) NOT NULL, + `c2` int(11) DEFAULT NULL, + PRIMARY KEY (`c1`), + KEY `c2` (`c2`), + CONSTRAINT `t1c2` FOREIGN KEY (`c2`) REFERENCES `①` (`c2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1ć, ①; +# +# Bug #21364096 THE BOGUS DUPLICATE KEY ERROR IN ONLINE DDL +# WITH INCORRECT KEY NAME +create table t1 (id int auto_increment primary key, a int, unique key uk(a)) +engine = innodb; +insert into t1 select 1, 1; +insert into t1 select 2, 2; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL s1 WAIT_FOR s2'; +alter table t1 add b int, ALGORITHM=inplace; +/* connection con1 */ +SET DEBUG_SYNC = 'now WAIT_FOR s1'; +insert into t1 select NULL, 1; +ERROR 23000: Duplicate entry '1' for key 'uk' +SET DEBUG_SYNC = 'now SIGNAL s2'; +/* connection default */ +/* reap */ alter table t1 add b int, ALGORITHM=inplace; +ERROR 23000: Duplicate entry '1' for key 'uk' +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL s1 WAIT_FOR s2'; +alter table t1 add b int, ALGORITHM=inplace;; +/* connection con1 */ +set DEBUG_SYNC = 'now WAIT_FOR s1'; +update t1 set a=1 where id=2; +ERROR 23000: Duplicate entry '1' for key 'uk' +SET DEBUG_SYNC = 'now SIGNAL s2'; +/* connection default */ +/* reap */ alter table t1 add b int, ALGORITHM=inplace; +ERROR 23000: Duplicate entry '1' for key 'uk' +SET DEBUG_SYNC = 'RESET'; +drop table t1; diff --git a/mysql-test/suite/innodb/r/innodb-alter-nullable.result b/mysql-test/suite/innodb/r/innodb-alter-nullable.result new file mode 100644 index 00000000000..e9711b2ac31 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-alter-nullable.result @@ -0,0 +1,53 @@ +CREATE TABLE t (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT) ENGINE=InnoDB; +INSERT INTO t VALUES (1,2,3),(4,5,6),(7,8,9); +ALTER TABLE t CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +set @old_sql_mode = @@sql_mode; +set @@sql_mode = 'STRICT_TRANS_TABLES'; +ALTER TABLE t MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +set @@sql_mode = @old_sql_mode; +ALTER TABLE t CHANGE c2 c2 INT, CHANGE c2 c2 INT NOT NULL; +ERROR 42S22: Unknown column 'c2' in 't' +ALTER TABLE t MODIFY c2 INT, MODIFY c2 INT NOT NULL; +ERROR 42S22: Unknown column 'c2' in 't' +ALTER TABLE t MODIFY c2 INT UNSIGNED, MODIFY c2 INT; +ERROR 42S22: Unknown column 'c2' in 't' +ALTER TABLE t MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL; +ERROR 42S22: Unknown column 'c2' in 't' +ALTER TABLE t CHANGE c2 c2 INT NOT NULL; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +ALTER TABLE t MODIFY c2 INT NOT NULL; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +SET SQL_MODE='STRICT_ALL_TABLES'; +UPDATE t SET c2=NULL; +ERROR 23000: Column 'c2' cannot be null +SELECT * FROM t; +c1 c2 c3 +1 2 3 +4 5 6 +7 8 9 +ALTER TABLE t MODIFY c2 INT, ALGORITHM=INPLACE; +BEGIN; +UPDATE t SET c2=NULL; +SELECT * FROM t; +c1 c2 c3 +1 NULL 3 +4 NULL 6 +7 NULL 9 +ROLLBACK; +SELECT * FROM t; +c1 c2 c3 +1 2 3 +4 5 6 +7 8 9 +ALTER TABLE t MODIFY c2 INT NULL, ALGORITHM=INPLACE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES +WHERE NAME='test/t'; +TABLE_ID NAME FLAG N_COLS SPACE FILE_FORMAT ROW_FORMAT ZIP_PAGE_SIZE +# test/t 1 6 # Antelope Compact 0 +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/innodb-alter-debug.test b/mysql-test/suite/innodb/t/innodb-alter-debug.test new file mode 100644 index 00000000000..70017ffba35 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-alter-debug.test @@ -0,0 +1,79 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--source include/count_sessions.inc + +SET NAMES utf8; + +CREATE TABLE ① ( + c1 INT PRIMARY KEY, c2 INT DEFAULT 1, ct TEXT, INDEX(c2)) +ENGINE = InnoDB; + +CREATE TABLE t1ć (c1 INT PRIMARY KEY, c2 INT, INDEX(c2), + CONSTRAINT t1c2 FOREIGN KEY (c2) REFERENCES ①(c2)) +ENGINE=InnoDB; + +INSERT INTO ① SET c1 = 1; + +SET @saved_debug_dbug = @@SESSION.debug_dbug; +SET DEBUG_DBUG = '+d,ib_drop_foreign_error'; +--error ER_RECORD_FILE_FULL +ALTER TABLE t1ć DROP FOREIGN KEY t1c2, RENAME TO ②; +SET DEBUG_DBUG = @saved_debug_dbug; + +SET DEBUG_DBUG = '+d,ib_rename_column_error'; +--error ER_RECORD_FILE_FULL +ALTER TABLE ① CHANGE c2 š INT; +SET DEBUG_DBUG = @saved_debug_dbug; + +SHOW CREATE TABLE t1ć; + +DROP TABLE t1ć, ①; + +--echo # +--echo # Bug #21364096 THE BOGUS DUPLICATE KEY ERROR IN ONLINE DDL +--echo # WITH INCORRECT KEY NAME + +create table t1 (id int auto_increment primary key, a int, unique key uk(a)) +engine = innodb; +insert into t1 select 1, 1; +insert into t1 select 2, 2; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL s1 WAIT_FOR s2'; +--send alter table t1 add b int, ALGORITHM=inplace + +--echo /* connection con1 */ +connect (con1,localhost,root,,); +SET DEBUG_SYNC = 'now WAIT_FOR s1'; +--error ER_DUP_ENTRY +insert into t1 select NULL, 1; +SET DEBUG_SYNC = 'now SIGNAL s2'; + +--echo /* connection default */ +connection default; +--echo /* reap */ alter table t1 add b int, ALGORITHM=inplace; +--error ER_DUP_ENTRY +--reap + +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL s1 WAIT_FOR s2'; +--send alter table t1 add b int, ALGORITHM=inplace; + +--echo /* connection con1 */ +connection con1; +set DEBUG_SYNC = 'now WAIT_FOR s1'; +--error ER_DUP_ENTRY +update t1 set a=1 where id=2; +SET DEBUG_SYNC = 'now SIGNAL s2'; +disconnect con1; + +--echo /* connection default */ +connection default; +--echo /* reap */ alter table t1 add b int, ALGORITHM=inplace; +--error ER_DUP_ENTRY +--reap +SET DEBUG_SYNC = 'RESET'; + +drop table t1; + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb-alter-nullable.test b/mysql-test/suite/innodb/t/innodb-alter-nullable.test new file mode 100644 index 00000000000..3f1e82b3183 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-alter-nullable.test @@ -0,0 +1,76 @@ +--source include/have_innodb.inc + +# Save the initial number of concurrent sessions. +--source include/count_sessions.inc + +CREATE TABLE t (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT) ENGINE=InnoDB; +INSERT INTO t VALUES (1,2,3),(4,5,6),(7,8,9); + +--enable_info +# This one will be a no-op. +# MySQL should perhaps issue an error, because it refuses to modify +# the PRIMARY KEY column c1 from NOT NULL to NULL. +ALTER TABLE t CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE; + +# NULL -> NOT NULL only allowed INPLACE if strict sql_mode is on. +--disable_info +set @old_sql_mode = @@sql_mode; +set @@sql_mode = 'STRICT_TRANS_TABLES'; +--enable_info +ALTER TABLE t MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE; +--disable_info +set @@sql_mode = @old_sql_mode; +--enable_info + +# Request some conflicting changes for a single column. +--error ER_BAD_FIELD_ERROR +ALTER TABLE t CHANGE c2 c2 INT, CHANGE c2 c2 INT NOT NULL; +--error ER_BAD_FIELD_ERROR +ALTER TABLE t MODIFY c2 INT, MODIFY c2 INT NOT NULL; +--error ER_BAD_FIELD_ERROR +ALTER TABLE t MODIFY c2 INT UNSIGNED, MODIFY c2 INT; +--error ER_BAD_FIELD_ERROR +ALTER TABLE t MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL; + +# No-ops. +ALTER TABLE t CHANGE c2 c2 INT NOT NULL; +ALTER TABLE t MODIFY c2 INT NOT NULL; +--disable_info + +connect (con1,localhost,root,,); +connection con1; + +SET SQL_MODE='STRICT_ALL_TABLES'; + +--error ER_BAD_NULL_ERROR +UPDATE t SET c2=NULL; + +SELECT * FROM t; + +connection default; + +# This should change the column to NULL. +ALTER TABLE t MODIFY c2 INT, ALGORITHM=INPLACE; + +connection con1; +BEGIN; +UPDATE t SET c2=NULL; +SELECT * FROM t; +ROLLBACK; +SELECT * FROM t; + +disconnect con1; +connection default; + +# This should be no-op. +ALTER TABLE t MODIFY c2 INT NULL, ALGORITHM=INPLACE; + +--replace_column 1 # 5 # +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES +WHERE NAME='test/t'; + +DROP TABLE t; + +# Check that all connections opened by test cases in this file are really +# gone so execution of other tests won't be affected by their presence. +--source include/wait_until_count_sessions.inc diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index cc00b841579..dc084dc1b95 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -129,7 +129,6 @@ my_error_innodb( break; case DB_OUT_OF_FILE_SPACE: my_error(ER_RECORD_FILE_FULL, MYF(0), table); - ut_error; break; case DB_TEMP_FILE_WRITE_FAILURE: my_error(ER_GET_ERRMSG, MYF(0), diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index cfae2725b05..3d20c9abccf 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -130,7 +130,6 @@ my_error_innodb( break; case DB_OUT_OF_FILE_SPACE: my_error(ER_RECORD_FILE_FULL, MYF(0), table); - ut_error; break; case DB_TEMP_FILE_WRITE_FAILURE: my_error(ER_GET_ERRMSG, MYF(0), From 57a699b0a0f3300404948775356d31fb478e80c6 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 17 Jun 2016 16:51:11 +0200 Subject: [PATCH 055/148] MDEV-8642: WHERE Clause not applied on View - Empty result set returned An attempt to mark reference as dependent lead to transfering this property to original view field and through it to other references of this field which can't be dependent. --- mysql-test/r/view.result | 37 +++++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 38 ++++++++++++++++++++++++++++++++++++++ sql/item.cc | 13 ------------- 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 3c6eb235a57..d6da2a03b46 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5907,6 +5907,43 @@ a 2 DROP VIEW v1; DROP TABLE t1; +# +# MDEV-8642: WHERE Clause not applied on View - Empty result set returned +# +CREATE TABLE `t1` ( +`id` int(20) NOT NULL AUTO_INCREMENT, +`use_case` int(11) DEFAULT NULL, +`current_deadline` date DEFAULT NULL, +`ts_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`id`), +UNIQUE KEY `id_UNIQUE` (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=13976 DEFAULT CHARSET=latin1; +INSERT INTO `t1` VALUES (1,10,'2015-12-18','2015-08-18 08:38:16'); +INSERT INTO `t1` VALUES (2,20,'2015-10-18','2015-08-18 08:43:30'); +CREATE VIEW v1 AS SELECT +use_case as use_case_id, +( +SELECT +deadline_sub.current_deadline +FROM +t1 deadline_sub +WHERE +deadline_sub.use_case = use_case_id +AND ts_create = (SELECT +MIN(ts_create) +FROM +t1 startdate_sub +WHERE +startdate_sub.use_case = use_case_id +) +) AS InitialDeadline +FROM +t1; +SELECT * FROM v1 where use_case_id = 10; +use_case_id InitialDeadline +10 2015-12-18 +drop view v1; +drop table t1; # ----------------------------------------------------------------- # -- End of 10.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 630c247e85b..89a8e0c9ffc 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5775,6 +5775,44 @@ DROP VIEW v1; DROP TABLE t1; +--echo # +--echo # MDEV-8642: WHERE Clause not applied on View - Empty result set returned +--echo # + +CREATE TABLE `t1` ( + `id` int(20) NOT NULL AUTO_INCREMENT, + `use_case` int(11) DEFAULT NULL, + `current_deadline` date DEFAULT NULL, + `ts_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `id_UNIQUE` (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=13976 DEFAULT CHARSET=latin1; +INSERT INTO `t1` VALUES (1,10,'2015-12-18','2015-08-18 08:38:16'); +INSERT INTO `t1` VALUES (2,20,'2015-10-18','2015-08-18 08:43:30'); +CREATE VIEW v1 AS SELECT + use_case as use_case_id, + ( + SELECT + deadline_sub.current_deadline + FROM + t1 deadline_sub + WHERE + deadline_sub.use_case = use_case_id + AND ts_create = (SELECT + MIN(ts_create) + FROM + t1 startdate_sub + WHERE + startdate_sub.use_case = use_case_id + ) + ) AS InitialDeadline +FROM + t1; + +SELECT * FROM v1 where use_case_id = 10; + +drop view v1; +drop table t1; --echo # ----------------------------------------------------------------- --echo # -- End of 10.0 tests. diff --git a/sql/item.cc b/sql/item.cc index 86f1795a4da..dbec742e4a2 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7141,19 +7141,6 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) last_checked_context->select_lex->nest_level); } } - else if (ref_type() != VIEW_REF) - { - /* - It could be that we're referring to something that's in ancestor selects. - We must make an appropriate mark_as_dependent() call for each such - outside reference. - */ - Dependency_marker dep_marker; - dep_marker.current_select= current_sel; - dep_marker.thd= thd; - (*ref)->walk(&Item::enumerate_field_refs_processor, FALSE, - (uchar*)&dep_marker); - } DBUG_ASSERT(*ref); /* From 5c579482eb2dd33c7fea80ea1ab412977606458a Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 7 Apr 2017 16:25:02 -0700 Subject: [PATCH 056/148] Adjusted test results after the fix for mdev-12429. --- mysql-test/suite/maria/icp.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/maria/icp.result b/mysql-test/suite/maria/icp.result index 9552580bb88..0ebf7cf1da8 100644 --- a/mysql-test/suite/maria/icp.result +++ b/mysql-test/suite/maria/icp.result @@ -438,7 +438,7 @@ WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON it.i=it.i WHERE it.pk-t1.i<10 id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where 2 DEPENDENT SUBQUERY it eq_ref PRIMARY PRIMARY 4 func 1 Using index condition -2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join) SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON it.i=it.i WHERE it.pk-t1.i<10); pk i @@ -799,7 +799,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t ALL PRIMARY,c NULL NULL NULL 64 Using where 1 PRIMARY t2 ref g g 5 test.t.c 19 Using where 2 DEPENDENT SUBQUERY t1 index PRIMARY PRIMARY 4 NULL 64 Using where; Using index -2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using index condition; Using where +2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where SELECT COUNT(*) FROM t1 AS t, t2 WHERE c = g AND (EXISTS (SELECT * FROM t1, t2 WHERE a = f AND h <= t.e AND a > t.b) From 7dd6efeaab688d703e3569c4f54f30502e88dd2f Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 2 Apr 2017 16:43:43 +1000 Subject: [PATCH 057/148] Don't use full path of libtool This is to be friendly to our OSX users where the libtool path is very different. Ref: * https://github.com/Homebrew/homebrew-core/blob/master/Formula/mariadb.rb#L44..L46 --- cmake/libutils.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake index 5125b9482cd..2e65e8b5ba3 100644 --- a/cmake/libutils.cmake +++ b/cmake/libutils.cmake @@ -188,7 +188,7 @@ MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) # binaries properly) ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD COMMAND rm ${TARGET_LOCATION} - COMMAND /usr/bin/libtool -static -o ${TARGET_LOCATION} + COMMAND libtool -static -o ${TARGET_LOCATION} ${STATIC_LIBS} ) ELSE() From 88613e1df69ab416d43f21551acec340648d0017 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Thu, 1 Dec 2016 09:59:58 +0100 Subject: [PATCH 058/148] MDEV-11201: gtid_ignore_duplicates incorrectly ignores statements when GTID replication is not enabled When master_use_gtid=no, the IO thread loads the slave GTID state from the master during connect. This races with the SQL thread when gtid_ignore_duplicates=1. If an event is in the relay log from before the new connect and has not been applied yet, moving the slave position causes the SQL thread to think that event should be skipped due to gtid_ignore_duplicates=1. This patch simply disables gtid_ignore_duplicates when not using GTID, which seems to be what one would expect. --- sql/rpl_parallel.cc | 3 ++- sql/slave.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index e5964e9c038..43e52c00e8d 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -1109,7 +1109,8 @@ handle_rpl_parallel_thread(void *arg) thd->wait_for_commit_ptr= &rgi->commit_orderer; - if (opt_gtid_ignore_duplicates) + if (opt_gtid_ignore_duplicates && + rgi->rli->mi->using_gtid != Master_info::USE_GTID_NO) { int res= rpl_global_gtid_slave_state->check_duplicate_gtid(&rgi->current_gtid, diff --git a/sql/slave.cc b/sql/slave.cc index 70b1c5b025e..8801e9e9ab5 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3612,7 +3612,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, DBUG_RETURN(1); } - if (opt_gtid_ignore_duplicates) + if (opt_gtid_ignore_duplicates && + rli->mi->using_gtid != Master_info::USE_GTID_NO) { int res= rpl_global_gtid_slave_state->check_duplicate_gtid (&serial_rgi->current_gtid, serial_rgi); From d53b541389a02c36448a4ebe21f2a7de7d53f9b3 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Thu, 13 Apr 2017 09:35:57 -0400 Subject: [PATCH 059/148] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index bc0b19220b6..ade2e129c54 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=55 +MYSQL_VERSION_PATCH=56 MYSQL_VERSION_EXTRA= From d185f1d68bb1f37bea10d8ac6188e5a04faf4522 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 19 Apr 2017 14:30:52 +0200 Subject: [PATCH 060/148] Fix use of `require` in mysql-test-run. The motivation for this is that Perl is moving towards not having current directory ./ in @INC by default. This is causing mysql-test-run.pl to fail in latest Debian Unstable: https://lists.debian.org/debian-devel-announce/2016/08/msg00013.html However, we have `use "lib"`, there is no need for current directory in @INC, except for a gross hack. In mtr_cases.pm, there is a `require "mtr_misc.pl"`, which hides mtr_misc.pl away in mtr_cases namespace. And things only work because mysql-test-run.pl loads it with a different name, `require "lib/mtr_misc.pl"`! (Perl will `require` only once for each unique filename). Fix this by only using `require` in main program, and referencing functions with :: scope from other namespaces. For multi-use in different namespaces, proper `use` modules should be used. Signed-off-by: Kristian Nielsen --- mysql-test/lib/mtr_cases.pm | 4 +--- mysql-test/lib/mtr_report.pm | 3 +-- mysql-test/mysql-test-run.pl | 10 +++++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 870df115f58..642cc6ce282 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -60,8 +60,6 @@ use My::Test; use My::Find; use My::Suite; -require "mtr_misc.pl"; - # locate plugin suites, depending on whether it's a build tree or installed my @plugin_suitedirs; my $plugin_suitedir_regex; @@ -1098,7 +1096,7 @@ sub get_tags_from_file($$) { $file_to_tags{$file}= $tags; $file_to_master_opts{$file}= $master_opts; $file_to_slave_opts{$file}= $slave_opts; - $file_combinations{$file}= [ uniq(@combinations) ]; + $file_combinations{$file}= [ ::uniq(@combinations) ]; $file_in_overlay{$file} = 1 if $in_overlay; return @{$tags}; } diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 9ab82c454ed..97ace54f0fb 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -34,7 +34,6 @@ use mtr_match; use My::Platform; use POSIX qw[ _exit ]; use IO::Handle qw[ flush ]; -require "mtr_io.pl"; use mtr_results; my $tot_real_time= 0; @@ -92,7 +91,7 @@ sub mtr_report_test_passed ($) { my $timer_str= ""; if ( $timer and -f "$::opt_vardir/log/timer" ) { - $timer_str= mtr_fromfile("$::opt_vardir/log/timer"); + $timer_str= ::mtr_fromfile("$::opt_vardir/log/timer"); $tinfo->{timer}= $timer_str; resfile_test_info('duration', $timer_str) if $::opt_resfile; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 02ca2fc4a83..0d9626b77e1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -102,11 +102,11 @@ use mtr_results; use IO::Socket::INET; use IO::Select; -require "lib/mtr_process.pl"; -require "lib/mtr_io.pl"; -require "lib/mtr_gcov.pl"; -require "lib/mtr_gprof.pl"; -require "lib/mtr_misc.pl"; +require "mtr_process.pl"; +require "mtr_io.pl"; +require "mtr_gcov.pl"; +require "mtr_gprof.pl"; +require "mtr_misc.pl"; $SIG{INT}= sub { mtr_error("Got ^C signal"); }; $SIG{HUP}= sub { mtr_error("Hangup detected on controlling terminal"); }; From d34a67b067606f61c9ec6700769770418d5bb47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 19 Apr 2017 22:30:18 +0300 Subject: [PATCH 061/148] MDEV-12534 Use atomic operations whenever available Allow 64-bit atomic operations on 32-bit systems, only relying on HAVE_ATOMIC_BUILTINS_64, disregarding the width of the register file. Define UNIV_WORD_SIZE correctly on all systems, including Windows. In MariaDB 10.0 and 10.1, it was incorrectly defined as 4 on 64-bit Windows. Define HAVE_ATOMIC_BUILTINS_64 on Windows (64-bit atomics are available on both 32-bit and 64-bit Windows platforms; the operations were unnecessarily disabled even on 64-bit Windows). MONITOR_OS_PENDING_READS, MONITOR_OS_PENDING_WRITES: Enable by default. os_file_n_pending_preads, os_file_n_pending_pwrites, os_n_pending_reads, os_n_pending_writes: Remove. Use the monitor counters instead. os_file_count_mutex: Remove. On a system that does not support 64-bit atomics, monitor_mutex will be used instead. --- storage/innobase/buf/buf0rea.cc | 14 +-- storage/innobase/include/os0file.h | 12 +- storage/innobase/include/os0sync.h | 5 +- storage/innobase/include/srv0mon.h | 62 ++++++--- storage/innobase/include/univ.i | 12 +- storage/innobase/os/os0file.cc | 196 +++++++---------------------- storage/innobase/srv/srv0mon.cc | 5 +- storage/innobase/srv/srv0srv.cc | 4 +- storage/innobase/sync/sync0arr.cc | 7 +- storage/xtradb/buf/buf0rea.cc | 14 +-- storage/xtradb/include/os0file.h | 12 +- storage/xtradb/include/os0sync.h | 5 +- storage/xtradb/include/srv0mon.h | 62 ++++++--- storage/xtradb/include/univ.i | 12 +- storage/xtradb/os/os0file.cc | 181 +++++++------------------- storage/xtradb/srv/srv0mon.cc | 5 +- storage/xtradb/srv/srv0srv.cc | 4 +- storage/xtradb/sync/sync0arr.cc | 7 +- 18 files changed, 214 insertions(+), 405 deletions(-) diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 7c8369c0c09..27f45308813 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -881,15 +881,11 @@ buf_read_recv_pages( count++; if (count > 1000) { - fprintf(stderr, - "InnoDB: Error: InnoDB has waited for" - " 10 seconds for pending\n" - "InnoDB: reads to the buffer pool to" - " be finished.\n" - "InnoDB: Number of pending reads %lu," - " pending pread calls %lu\n", - (ulong) buf_pool->n_pend_reads, - (ulong) os_file_n_pending_preads); + ib_logf(IB_LOG_LEVEL_ERROR, + "waited for 10 seconds for " ULINTPF + " pending reads to the buffer pool to" + " be finished", + buf_pool->n_pend_reads); os_aio_print_debug = TRUE; } diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 6cb4f54d629..bdb4682eafb 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -51,16 +51,6 @@ extern ibool os_has_said_disk_full; /** Flag: enable debug printout for asynchronous i/o */ extern ibool os_aio_print_debug; -/** Number of pending os_file_pread() operations */ -extern ulint os_file_n_pending_preads; -/** Number of pending os_file_pwrite() operations */ -extern ulint os_file_n_pending_pwrites; - -/** Number of pending read operations */ -extern ulint os_n_pending_reads; -/** Number of pending write operations */ -extern ulint os_n_pending_writes; - #ifdef __WIN__ /** We define always WIN_ASYNC_IO, and check at run-time whether diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 0754210c47a..dd6de43dc0b 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -667,10 +667,7 @@ os_atomic_clear(volatile lock_word_t* ptr) # define HAVE_ATOMIC_BUILTINS # define HAVE_ATOMIC_BUILTINS_BYTE - -# ifndef _WIN32 -# define HAVE_ATOMIC_BUILTINS_64 -# endif +# define HAVE_ATOMIC_BUILTINS_64 /**********************************************************//** Atomic compare and exchange of signed integers (both 32 and 64 bit). diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 2d90f47eefe..09af5d4159b 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -2,6 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -541,22 +542,30 @@ on the counters */ /** Increment a monitor counter under mutex protection. Use MONITOR_INC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release @param monitor monitor to be incremented by 1 -@param mutex mutex to acquire and relese */ -# define MONITOR_MUTEX_INC(mutex, monitor) \ +@param enabled whether the monitor is enabled */ +#define MONITOR_MUTEX_INC_LOW(mutex, monitor, enabled) \ ut_ad(!mutex_own(mutex)); \ - if (MONITOR_IS_ON(monitor)) { \ + if (enabled) { \ mutex_enter(mutex); \ if (++MONITOR_VALUE(monitor) > MONITOR_MAX_VALUE(monitor)) { \ MONITOR_MAX_VALUE(monitor) = MONITOR_VALUE(monitor); \ } \ mutex_exit(mutex); \ } +/** Increment a monitor counter under mutex protection. +Use MONITOR_INC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release +@param monitor monitor to be incremented by 1 */ +#define MONITOR_MUTEX_INC(mutex, monitor) \ + MONITOR_MUTEX_INC_LOW(mutex, monitor, MONITOR_IS_ON(monitor)) /** Decrement a monitor counter under mutex protection. Use MONITOR_DEC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release @param monitor monitor to be decremented by 1 -@param mutex mutex to acquire and relese */ -# define MONITOR_MUTEX_DEC(mutex, monitor) \ +@param enabled whether the monitor is enabled */ +#define MONITOR_MUTEX_DEC_LOW(mutex, monitor, enabled) \ ut_ad(!mutex_own(mutex)); \ if (MONITOR_IS_ON(monitor)) { \ mutex_enter(mutex); \ @@ -565,13 +574,20 @@ Use MONITOR_DEC if appropriate mutex protection already exists. } \ mutex_exit(mutex); \ } +/** Decrement a monitor counter under mutex protection. +Use MONITOR_DEC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release +@param monitor monitor to be decremented by 1 */ +#define MONITOR_MUTEX_DEC(mutex, monitor) \ + MONITOR_MUTEX_DEC_LOW(mutex, monitor, MONITOR_IS_ON(monitor)) #if defined HAVE_ATOMIC_BUILTINS_64 /** Atomically increment a monitor counter. Use MONITOR_INC if appropriate mutex protection exists. -@param monitor monitor to be incremented by 1 */ -# define MONITOR_ATOMIC_INC(monitor) \ - if (MONITOR_IS_ON(monitor)) { \ +@param monitor monitor to be incremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_INC_LOW(monitor, enabled) \ + if (enabled) { \ ib_uint64_t value; \ value = os_atomic_increment_uint64( \ (ib_uint64_t*) &MONITOR_VALUE(monitor), 1); \ @@ -584,9 +600,10 @@ Use MONITOR_INC if appropriate mutex protection exists. /** Atomically decrement a monitor counter. Use MONITOR_DEC if appropriate mutex protection exists. -@param monitor monitor to be decremented by 1 */ -# define MONITOR_ATOMIC_DEC(monitor) \ - if (MONITOR_IS_ON(monitor)) { \ +@param monitor monitor to be decremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_DEC_LOW(monitor, enabled) \ + if (enabled) { \ ib_uint64_t value; \ value = os_atomic_decrement_uint64( \ (ib_uint64_t*) &MONITOR_VALUE(monitor), 1); \ @@ -617,14 +634,29 @@ srv_mon_free(void); /** Atomically increment a monitor counter. Use MONITOR_INC if appropriate mutex protection exists. -@param monitor monitor to be incremented by 1 */ -# define MONITOR_ATOMIC_INC(monitor) MONITOR_MUTEX_INC(&monitor_mutex, monitor) +@param monitor monitor to be incremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_INC_LOW(monitor, enabled) \ + MONITOR_MUTEX_INC_LOW(&monitor_mutex, monitor, enabled) /** Atomically decrement a monitor counter. Use MONITOR_DEC if appropriate mutex protection exists. -@param monitor monitor to be decremented by 1 */ -# define MONITOR_ATOMIC_DEC(monitor) MONITOR_MUTEX_DEC(&monitor_mutex, monitor) +@param monitor monitor to be decremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_DEC_LOW(monitor, enabled) \ + MONITOR_MUTEX_DEC_LOW(&monitor_mutex, monitor, enabled) #endif /* HAVE_ATOMIC_BUILTINS_64 */ +/** Atomically increment a monitor counter if it is enabled. +Use MONITOR_INC if appropriate mutex protection exists. +@param monitor monitor to be incremented by 1 */ +#define MONITOR_ATOMIC_INC(monitor) \ + MONITOR_ATOMIC_INC_LOW(monitor, MONITOR_IS_ON(monitor)) +/** Atomically decrement a monitor counter if it is enabled. +Use MONITOR_DEC if appropriate mutex protection exists. +@param monitor monitor to be decremented by 1 */ +#define MONITOR_ATOMIC_DEC(monitor) \ + MONITOR_ATOMIC_DEC_LOW(monitor, MONITOR_IS_ON(monitor)) + #define MONITOR_DEC(monitor) \ if (MONITOR_IS_ON(monitor)) { \ MONITOR_VALUE(monitor)--; \ diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 824a06829f9..fc0bf0aeeca 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -285,22 +285,12 @@ definitions: */ #endif /* !UNIV_MUST_NOT_INLINE */ -#ifdef _WIN32 -#define UNIV_WORD_SIZE 4 -#elif defined(_WIN64) -#define UNIV_WORD_SIZE 8 -#else -/** MySQL config.h generated by GNU autoconf will define SIZEOF_LONG in Posix */ -#define UNIV_WORD_SIZE SIZEOF_LONG -#endif +#define UNIV_WORD_SIZE SIZEOF_SIZE_T /** The following alignment is used in memory allocations in memory heap management to ensure correct alignment for doubles etc. */ #define UNIV_MEM_ALIGNMENT 8 -/** The following alignment is used in aligning lints etc. */ -#define UNIV_WORD_ALIGNMENT UNIV_WORD_SIZE - /* DATABASE VERSION CONTROL ======================== diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index eb8b3a53d32..ff67c90eecf 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2012, 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -284,21 +284,6 @@ UNIV_INTERN time_t os_last_printout; UNIV_INTERN ibool os_has_said_disk_full = FALSE; -#if !defined(UNIV_HOTBACKUP) \ - && (!defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8) -/** The mutex protecting the following counts of pending I/O operations */ -static os_ib_mutex_t os_file_count_mutex; -#endif /* !UNIV_HOTBACKUP && (!HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8) */ - -/** Number of pending os_file_pread() operations */ -UNIV_INTERN ulint os_file_n_pending_preads = 0; -/** Number of pending os_file_pwrite() operations */ -UNIV_INTERN ulint os_file_n_pending_pwrites = 0; -/** Number of pending write operations */ -UNIV_INTERN ulint os_n_pending_writes = 0; -/** Number of pending read operations */ -UNIV_INTERN ulint os_n_pending_reads = 0; - #ifdef UNIV_DEBUG # ifndef UNIV_HOTBACKUP /**********************************************************************//** @@ -752,10 +737,6 @@ void os_io_init_simple(void) /*===================*/ { -#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 - os_file_count_mutex = os_mutex_create(); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8 */ - for (ulint i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) { os_file_seek_mutexes[i] = os_mutex_create(); } @@ -2364,9 +2345,6 @@ os_file_pread( os_offset_t offset) /*!< in: file offset from where to read */ { off_t offs; -#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) - ssize_t n_bytes; -#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */ ut_ad(n); @@ -2383,33 +2361,12 @@ os_file_pread( os_n_file_reads++; -#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_increment_ulint(&os_n_pending_reads, 1); - (void) os_atomic_increment_ulint(&os_file_n_pending_preads, 1); - MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_preads++; - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */ - - n_bytes = pread(file, buf, n, offs); - -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1); - (void) os_atomic_decrement_ulint(&os_file_n_pending_preads, 1); - MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_preads--; - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD == 8 */ + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS); +#ifdef HAVE_PREAD + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); + ssize_t n_bytes = pread(file, buf, n, offs); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); return(n_bytes); #else { @@ -2419,15 +2376,7 @@ os_file_pread( ulint i; #endif /* !UNIV_HOTBACKUP */ -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_increment_ulint(&os_n_pending_reads, 1); - MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */ + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); #ifndef UNIV_HOTBACKUP /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; @@ -2447,16 +2396,7 @@ os_file_pread( os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1); - MONITOR_ATOIC_DEC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD_SIZE == 8 */ - + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); return(ret); } #endif @@ -2493,32 +2433,11 @@ os_file_pwrite( os_n_file_writes++; -#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD) -#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_pwrites++; - os_n_pending_writes++; - MONITOR_INC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); -#else - (void) os_atomic_increment_ulint(&os_n_pending_writes, 1); - (void) os_atomic_increment_ulint(&os_file_n_pending_pwrites, 1); - MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_WRITES); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */ - + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_WRITES); +#ifdef HAVE_PWRITE + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor); ret = pwrite(file, buf, (ssize_t) n, offs); - -#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_pwrites--; - os_n_pending_writes--; - MONITOR_DEC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); -#else - (void) os_atomic_decrement_ulint(&os_n_pending_writes, 1); - (void) os_atomic_decrement_ulint(&os_file_n_pending_pwrites, 1); - MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_WRITES); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */ + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor); return(ret); #else @@ -2528,10 +2447,7 @@ os_file_pwrite( ulint i; # endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes++; - MONITOR_INC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor); # ifndef UNIV_HOTBACKUP /* Protect the seek / write operation with a mutex */ @@ -2555,14 +2471,10 @@ func_exit: os_mutex_exit(os_file_seek_mutexes[i]); # endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes--; - MONITOR_DEC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); - + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor); return(ret); } -#endif /* !UNIV_HOTBACKUP */ +#endif /* HAVE_PWRITE */ } #endif @@ -2597,6 +2509,7 @@ os_file_read_func( os_n_file_reads++; os_bytes_read_since_printout += n; + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS); try_again: ut_ad(buf); @@ -2605,10 +2518,7 @@ try_again: low = (DWORD) offset & 0xFFFFFFFF; high = (DWORD) (offset >> 32); - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); #ifndef UNIV_HOTBACKUP /* Protect the seek / read operation with a mutex */ @@ -2626,11 +2536,7 @@ try_again: os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); - + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); goto error_handling; } @@ -2640,10 +2546,7 @@ try_again: os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); if (ret && len == n) { return(TRUE); @@ -2728,6 +2631,7 @@ os_file_read_no_error_handling_func( os_n_file_reads++; os_bytes_read_since_printout += n; + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS); try_again: ut_ad(buf); @@ -2736,10 +2640,7 @@ try_again: low = (DWORD) offset & 0xFFFFFFFF; high = (DWORD) (offset >> 32); - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); #ifndef UNIV_HOTBACKUP /* Protect the seek / read operation with a mutex */ @@ -2757,11 +2658,7 @@ try_again: os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); - + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); goto error_handling; } @@ -2771,10 +2668,7 @@ try_again: os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); if (ret && len == n) { return(TRUE); @@ -2854,7 +2748,6 @@ os_file_write_func( ulint n) /*!< in: number of bytes to write */ { ut_ad(!srv_read_only_mode); - #ifdef __WIN__ BOOL ret; DWORD len; @@ -2876,14 +2769,12 @@ os_file_write_func( ut_ad(buf); ut_ad(n > 0); + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_WRITES); retry: low = (DWORD) offset & 0xFFFFFFFF; high = (DWORD) (offset >> 32); - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes++; - MONITOR_INC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor); #ifndef UNIV_HOTBACKUP /* Protect the seek / write operation with a mutex */ @@ -2901,10 +2792,7 @@ retry: os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes--; - MONITOR_DEC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor); ut_print_timestamp(stderr); @@ -2928,10 +2816,7 @@ retry: os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes--; - MONITOR_DEC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor); if (ret && len == n) { @@ -5751,19 +5636,24 @@ os_aio_print( time_elapsed = 0.001 + difftime(current_time, os_last_printout); fprintf(file, - "Pending flushes (fsync) log: %lu; buffer pool: %lu\n" - "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n", - (ulong) fil_n_pending_log_flushes, - (ulong) fil_n_pending_tablespace_flushes, - (ulong) os_n_file_reads, - (ulong) os_n_file_writes, - (ulong) os_n_fsyncs); + "Pending flushes (fsync) log: " ULINTPF + "; buffer pool: " ULINTPF "\n" + ULINTPF " OS file reads, " + ULINTPF " OS file writes, " + ULINTPF " OS fsyncs\n", + fil_n_pending_log_flushes, + fil_n_pending_tablespace_flushes, + os_n_file_reads, + os_n_file_writes, + os_n_fsyncs); - if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) { + const ulint n_reads = MONITOR_VALUE(MONITOR_OS_PENDING_READS); + const ulint n_writes = MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); + + if (n_reads != 0 || n_writes != 0) { fprintf(file, - "%lu pending preads, %lu pending pwrites\n", - (ulong) os_file_n_pending_preads, - (ulong) os_file_n_pending_pwrites); + ULINTPF " pending reads, " ULINTPF " pending writes\n", + n_reads, n_writes); } if (os_n_file_reads == os_n_file_reads_old) { diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 4a709160ea6..ea21a4c1454 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -2,6 +2,7 @@ Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -643,11 +644,11 @@ static monitor_info_t innodb_counter_info[] = MONITOR_DEFAULT_START, MONITOR_OVLD_OS_FSYNC}, {"os_pending_reads", "os", "Number of reads pending", - MONITOR_NONE, + MONITOR_DEFAULT_ON, MONITOR_DEFAULT_START, MONITOR_OS_PENDING_READS}, {"os_pending_writes", "os", "Number of writes pending", - MONITOR_NONE, + MONITOR_DEFAULT_ON, MONITOR_DEFAULT_START, MONITOR_OS_PENDING_WRITES}, {"os_log_bytes_written", "os", diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 723ae838f07..58e69c3c9e7 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1409,10 +1409,10 @@ srv_export_innodb_status(void) mutex_enter(&srv_innodb_monitor_mutex); export_vars.innodb_data_pending_reads = - os_n_pending_reads; + MONITOR_VALUE(MONITOR_OS_PENDING_READS); export_vars.innodb_data_pending_writes = - os_n_pending_writes; + MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); export_vars.innodb_data_pending_fsyncs = fil_n_pending_log_flushes diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc index c7163695a3f..6ffe3cab8c8 100644 --- a/storage/innobase/sync/sync0arr.cc +++ b/storage/innobase/sync/sync0arr.cc @@ -1069,9 +1069,10 @@ sync_array_print_long_waits( now the values of pending calls of these. */ fprintf(stderr, - "InnoDB: Pending preads %lu, pwrites %lu\n", - (ulong) os_file_n_pending_preads, - (ulong) os_file_n_pending_pwrites); + "InnoDB: Pending reads " UINT64PF + ", writes " UINT64PF "\n", + MONITOR_VALUE(MONITOR_OS_PENDING_READS), + MONITOR_VALUE(MONITOR_OS_PENDING_WRITES)); srv_print_innodb_monitor = TRUE; os_event_set(srv_monitor_event); diff --git a/storage/xtradb/buf/buf0rea.cc b/storage/xtradb/buf/buf0rea.cc index c28df72df92..9053f38924e 100644 --- a/storage/xtradb/buf/buf0rea.cc +++ b/storage/xtradb/buf/buf0rea.cc @@ -986,15 +986,11 @@ not_to_recover: count++; if (count > 1000) { - fprintf(stderr, - "InnoDB: Error: InnoDB has waited for" - " 10 seconds for pending\n" - "InnoDB: reads to the buffer pool to" - " be finished.\n" - "InnoDB: Number of pending reads %lu," - " pending pread calls %lu\n", - (ulong) buf_pool->n_pend_reads, - (ulong) os_file_n_pending_preads); + ib_logf(IB_LOG_LEVEL_ERROR, + "waited for 10 seconds for " ULINTPF + " pending reads to the buffer pool to" + " be finished", + buf_pool->n_pend_reads); os_aio_print_debug = TRUE; } diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h index 60a9c3475e7..b8f30977fbe 100644 --- a/storage/xtradb/include/os0file.h +++ b/storage/xtradb/include/os0file.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -52,16 +52,6 @@ extern ibool os_has_said_disk_full; /** Flag: enable debug printout for asynchronous i/o */ extern ibool os_aio_print_debug; -/** Number of pending os_file_pread() operations */ -extern ulint os_file_n_pending_preads; -/** Number of pending os_file_pwrite() operations */ -extern ulint os_file_n_pending_pwrites; - -/** Number of pending read operations */ -extern ulint os_n_pending_reads; -/** Number of pending write operations */ -extern ulint os_n_pending_writes; - #ifdef __WIN__ /** We define always WIN_ASYNC_IO, and check at run-time whether diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h index f6207555f1a..48c56a73369 100644 --- a/storage/xtradb/include/os0sync.h +++ b/storage/xtradb/include/os0sync.h @@ -718,10 +718,7 @@ os_atomic_clear(volatile lock_word_t* ptr) # define HAVE_ATOMIC_BUILTINS # define HAVE_ATOMIC_BUILTINS_BYTE - -# ifndef _WIN32 -# define HAVE_ATOMIC_BUILTINS_64 -# endif +# define HAVE_ATOMIC_BUILTINS_64 /**********************************************************//** Atomic compare and exchange of signed integers (both 32 and 64 bit). diff --git a/storage/xtradb/include/srv0mon.h b/storage/xtradb/include/srv0mon.h index 2d90f47eefe..09af5d4159b 100644 --- a/storage/xtradb/include/srv0mon.h +++ b/storage/xtradb/include/srv0mon.h @@ -2,6 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -541,22 +542,30 @@ on the counters */ /** Increment a monitor counter under mutex protection. Use MONITOR_INC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release @param monitor monitor to be incremented by 1 -@param mutex mutex to acquire and relese */ -# define MONITOR_MUTEX_INC(mutex, monitor) \ +@param enabled whether the monitor is enabled */ +#define MONITOR_MUTEX_INC_LOW(mutex, monitor, enabled) \ ut_ad(!mutex_own(mutex)); \ - if (MONITOR_IS_ON(monitor)) { \ + if (enabled) { \ mutex_enter(mutex); \ if (++MONITOR_VALUE(monitor) > MONITOR_MAX_VALUE(monitor)) { \ MONITOR_MAX_VALUE(monitor) = MONITOR_VALUE(monitor); \ } \ mutex_exit(mutex); \ } +/** Increment a monitor counter under mutex protection. +Use MONITOR_INC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release +@param monitor monitor to be incremented by 1 */ +#define MONITOR_MUTEX_INC(mutex, monitor) \ + MONITOR_MUTEX_INC_LOW(mutex, monitor, MONITOR_IS_ON(monitor)) /** Decrement a monitor counter under mutex protection. Use MONITOR_DEC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release @param monitor monitor to be decremented by 1 -@param mutex mutex to acquire and relese */ -# define MONITOR_MUTEX_DEC(mutex, monitor) \ +@param enabled whether the monitor is enabled */ +#define MONITOR_MUTEX_DEC_LOW(mutex, monitor, enabled) \ ut_ad(!mutex_own(mutex)); \ if (MONITOR_IS_ON(monitor)) { \ mutex_enter(mutex); \ @@ -565,13 +574,20 @@ Use MONITOR_DEC if appropriate mutex protection already exists. } \ mutex_exit(mutex); \ } +/** Decrement a monitor counter under mutex protection. +Use MONITOR_DEC if appropriate mutex protection already exists. +@param mutex mutex to acquire and release +@param monitor monitor to be decremented by 1 */ +#define MONITOR_MUTEX_DEC(mutex, monitor) \ + MONITOR_MUTEX_DEC_LOW(mutex, monitor, MONITOR_IS_ON(monitor)) #if defined HAVE_ATOMIC_BUILTINS_64 /** Atomically increment a monitor counter. Use MONITOR_INC if appropriate mutex protection exists. -@param monitor monitor to be incremented by 1 */ -# define MONITOR_ATOMIC_INC(monitor) \ - if (MONITOR_IS_ON(monitor)) { \ +@param monitor monitor to be incremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_INC_LOW(monitor, enabled) \ + if (enabled) { \ ib_uint64_t value; \ value = os_atomic_increment_uint64( \ (ib_uint64_t*) &MONITOR_VALUE(monitor), 1); \ @@ -584,9 +600,10 @@ Use MONITOR_INC if appropriate mutex protection exists. /** Atomically decrement a monitor counter. Use MONITOR_DEC if appropriate mutex protection exists. -@param monitor monitor to be decremented by 1 */ -# define MONITOR_ATOMIC_DEC(monitor) \ - if (MONITOR_IS_ON(monitor)) { \ +@param monitor monitor to be decremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_DEC_LOW(monitor, enabled) \ + if (enabled) { \ ib_uint64_t value; \ value = os_atomic_decrement_uint64( \ (ib_uint64_t*) &MONITOR_VALUE(monitor), 1); \ @@ -617,14 +634,29 @@ srv_mon_free(void); /** Atomically increment a monitor counter. Use MONITOR_INC if appropriate mutex protection exists. -@param monitor monitor to be incremented by 1 */ -# define MONITOR_ATOMIC_INC(monitor) MONITOR_MUTEX_INC(&monitor_mutex, monitor) +@param monitor monitor to be incremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_INC_LOW(monitor, enabled) \ + MONITOR_MUTEX_INC_LOW(&monitor_mutex, monitor, enabled) /** Atomically decrement a monitor counter. Use MONITOR_DEC if appropriate mutex protection exists. -@param monitor monitor to be decremented by 1 */ -# define MONITOR_ATOMIC_DEC(monitor) MONITOR_MUTEX_DEC(&monitor_mutex, monitor) +@param monitor monitor to be decremented by 1 +@param enabled whether the monitor is enabled */ +# define MONITOR_ATOMIC_DEC_LOW(monitor, enabled) \ + MONITOR_MUTEX_DEC_LOW(&monitor_mutex, monitor, enabled) #endif /* HAVE_ATOMIC_BUILTINS_64 */ +/** Atomically increment a monitor counter if it is enabled. +Use MONITOR_INC if appropriate mutex protection exists. +@param monitor monitor to be incremented by 1 */ +#define MONITOR_ATOMIC_INC(monitor) \ + MONITOR_ATOMIC_INC_LOW(monitor, MONITOR_IS_ON(monitor)) +/** Atomically decrement a monitor counter if it is enabled. +Use MONITOR_DEC if appropriate mutex protection exists. +@param monitor monitor to be decremented by 1 */ +#define MONITOR_ATOMIC_DEC(monitor) \ + MONITOR_ATOMIC_DEC_LOW(monitor, MONITOR_IS_ON(monitor)) + #define MONITOR_DEC(monitor) \ if (MONITOR_IS_ON(monitor)) { \ MONITOR_VALUE(monitor)--; \ diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 6acb0eec319..7497e7f5d05 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -304,22 +304,12 @@ definitions: */ #endif /* !UNIV_MUST_NOT_INLINE */ -#ifdef _WIN32 -#define UNIV_WORD_SIZE 4 -#elif defined(_WIN64) -#define UNIV_WORD_SIZE 8 -#else -/** MySQL config.h generated by GNU autoconf will define SIZEOF_LONG in Posix */ -#define UNIV_WORD_SIZE SIZEOF_LONG -#endif +#define UNIV_WORD_SIZE SIZEOF_SIZE_T /** The following alignment is used in memory allocations in memory heap management to ensure correct alignment for doubles etc. */ #define UNIV_MEM_ALIGNMENT 8 -/** The following alignment is used in aligning lints etc. */ -#define UNIV_WORD_ALIGNMENT UNIV_WORD_SIZE - /* DATABASE VERSION CONTROL ======================== diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index a30b688ad74..48ae49f28e4 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -291,21 +291,6 @@ UNIV_INTERN time_t os_last_printout; UNIV_INTERN ibool os_has_said_disk_full = FALSE; -#if !defined(UNIV_HOTBACKUP) \ - && (!defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8) -/** The mutex protecting the following counts of pending I/O operations */ -static os_ib_mutex_t os_file_count_mutex; -#endif /* !UNIV_HOTBACKUP && (!HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8) */ - -/** Number of pending os_file_pread() operations */ -UNIV_INTERN ulint os_file_n_pending_preads = 0; -/** Number of pending os_file_pwrite() operations */ -UNIV_INTERN ulint os_file_n_pending_pwrites = 0; -/** Number of pending write operations */ -UNIV_INTERN ulint os_n_pending_writes = 0; -/** Number of pending read operations */ -UNIV_INTERN ulint os_n_pending_reads = 0; - #ifdef UNIV_DEBUG # ifndef UNIV_HOTBACKUP /**********************************************************************//** @@ -887,10 +872,6 @@ void os_io_init_simple(void) /*===================*/ { -#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 - os_file_count_mutex = os_mutex_create(); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8 */ - for (ulint i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) { os_file_seek_mutexes[i] = os_mutex_create(); } @@ -2580,10 +2561,6 @@ os_file_pread( trx_t* trx) { off_t offs; -#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) - ssize_t n_bytes; - ssize_t n_read; -#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */ ulint sec; ulint ms; ib_uint64_t start_time; @@ -2613,22 +2590,16 @@ os_file_pread( } else { start_time = 0; } -#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_increment_ulint(&os_n_pending_reads, 1); - (void) os_atomic_increment_ulint(&os_file_n_pending_preads, 1); - MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_preads++; - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */ + + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS); +#ifdef HAVE_PREAD + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); + + ssize_t n_bytes; /* Handle partial reads and signal interruptions correctly */ for (n_bytes = 0; n_bytes < (ssize_t) n; ) { - n_read = pread(file, buf, (ssize_t)n - n_bytes, offs); + ssize_t n_read = pread(file, buf, (ssize_t)n - n_bytes, offs); if (n_read > 0) { n_bytes += n_read; offs += n_read; @@ -2640,17 +2611,7 @@ os_file_pread( } } -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1); - (void) os_atomic_decrement_ulint(&os_file_n_pending_preads, 1); - MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_preads--; - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD == 8 */ + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); if (UNIV_UNLIKELY(start_time != 0)) { @@ -2669,15 +2630,7 @@ os_file_pread( ulint i; #endif /* !UNIV_HOTBACKUP */ -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_increment_ulint(&os_n_pending_reads, 1); - MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */ + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); #ifndef UNIV_HOTBACKUP /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; @@ -2707,15 +2660,7 @@ os_file_pread( os_mutex_exit(os_file_seek_mutexes[i]); #endif /* !UNIV_HOTBACKUP */ -#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8 - (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1); - MONITOR_ATOIC_DEC(MONITOR_OS_PENDING_READS); -#else - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); -#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD_SIZE == 8 */ + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); if (UNIV_UNLIKELY(start_time != 0) { @@ -2761,18 +2706,9 @@ os_file_pwrite( os_n_file_writes++; -#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD) -#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_pwrites++; - os_n_pending_writes++; - MONITOR_INC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); -#else - (void) os_atomic_increment_ulint(&os_n_pending_writes, 1); - (void) os_atomic_increment_ulint(&os_file_n_pending_pwrites, 1); - MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_WRITES); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */ + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_WRITES); +#ifdef HAVE_PWRITE + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor); /* Handle partial writes and signal interruptions correctly */ for (ret = 0; ret < (ssize_t) n; ) { @@ -2791,17 +2727,7 @@ os_file_pwrite( } } -#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 - os_mutex_enter(os_file_count_mutex); - os_file_n_pending_pwrites--; - os_n_pending_writes--; - MONITOR_DEC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); -#else - (void) os_atomic_decrement_ulint(&os_n_pending_writes, 1); - (void) os_atomic_decrement_ulint(&os_file_n_pending_pwrites, 1); - MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_WRITES); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */ + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor); return(ret); #else @@ -2811,10 +2737,7 @@ os_file_pwrite( ulint i; # endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes++; - MONITOR_INC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor); # ifndef UNIV_HOTBACKUP /* Protect the seek / write operation with a mutex */ @@ -2848,14 +2771,10 @@ func_exit: os_mutex_exit(os_file_seek_mutexes[i]); # endif /* !UNIV_HOTBACKUP */ - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes--; - MONITOR_DEC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); - + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor); return(ret); } -#endif /* !UNIV_HOTBACKUP */ +#endif /* HAVE_PWRITE */ } #endif @@ -2887,15 +2806,13 @@ os_file_read_func( os_n_file_reads++; os_bytes_read_since_printout += n; + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS); try_again: ut_ad(buf); ut_ad(n > 0); - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); memset (&overlapped, 0, sizeof (overlapped)); overlapped.Offset = (DWORD)(offset & 0xFFFFFFFF); @@ -2908,10 +2825,7 @@ try_again: else if(GetLastError() == ERROR_IO_PENDING) { ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE); } - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); if (ret && len == n) { return(TRUE); @@ -2995,15 +2909,13 @@ os_file_read_no_error_handling_func( os_n_file_reads++; os_bytes_read_since_printout += n; + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS); try_again: ut_ad(buf); ut_ad(n > 0); - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads++; - MONITOR_INC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor); memset (&overlapped, 0, sizeof (overlapped)); overlapped.Offset = (DWORD)(offset & 0xFFFFFFFF); @@ -3016,10 +2928,7 @@ try_again: else if(GetLastError() == ERROR_IO_PENDING) { ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE); } - os_mutex_enter(os_file_count_mutex); - os_n_pending_reads--; - MONITOR_DEC(MONITOR_OS_PENDING_READS); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor); if (ret && len == n) { return(TRUE); @@ -3113,12 +3022,10 @@ os_file_write_func( ut_ad(buf); ut_ad(n > 0); + const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_WRITES); retry: - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes++; - MONITOR_INC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor); memset (&overlapped, 0, sizeof (overlapped)); overlapped.Offset = (DWORD)(offset & 0xFFFFFFFF); @@ -3133,10 +3040,7 @@ retry: ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE); } - os_mutex_enter(os_file_count_mutex); - os_n_pending_writes--; - MONITOR_DEC(MONITOR_OS_PENDING_WRITES); - os_mutex_exit(os_file_count_mutex); + MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor); if (ret && len == n) { @@ -4230,10 +4134,6 @@ os_aio_free(void) } } -#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 - os_mutex_free(os_file_count_mutex); -#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8 */ - for (ulint i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) { os_mutex_free(os_file_seek_mutexes[i]); } @@ -5909,19 +5809,24 @@ os_aio_print( time_elapsed = 0.001 + difftime(current_time, os_last_printout); fprintf(file, - "Pending flushes (fsync) log: %lu; buffer pool: %lu\n" - "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n", - (ulong) fil_n_pending_log_flushes, - (ulong) fil_n_pending_tablespace_flushes, - (ulong) os_n_file_reads, - (ulong) os_n_file_writes, - (ulong) os_n_fsyncs); + "Pending flushes (fsync) log: " ULINTPF + "; buffer pool: " ULINTPF "\n" + ULINTPF " OS file reads, " + ULINTPF " OS file writes, " + ULINTPF " OS fsyncs\n", + fil_n_pending_log_flushes, + fil_n_pending_tablespace_flushes, + os_n_file_reads, + os_n_file_writes, + os_n_fsyncs); - if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) { + const ulint n_reads = MONITOR_VALUE(MONITOR_OS_PENDING_READS); + const ulint n_writes = MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); + + if (n_reads != 0 || n_writes != 0) { fprintf(file, - "%lu pending preads, %lu pending pwrites\n", - (ulong) os_file_n_pending_preads, - (ulong) os_file_n_pending_pwrites); + ULINTPF " pending reads, " ULINTPF " pending writes\n", + n_reads, n_writes); } if (os_n_file_reads == os_n_file_reads_old) { diff --git a/storage/xtradb/srv/srv0mon.cc b/storage/xtradb/srv/srv0mon.cc index 4a709160ea6..ea21a4c1454 100644 --- a/storage/xtradb/srv/srv0mon.cc +++ b/storage/xtradb/srv/srv0mon.cc @@ -2,6 +2,7 @@ Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -643,11 +644,11 @@ static monitor_info_t innodb_counter_info[] = MONITOR_DEFAULT_START, MONITOR_OVLD_OS_FSYNC}, {"os_pending_reads", "os", "Number of reads pending", - MONITOR_NONE, + MONITOR_DEFAULT_ON, MONITOR_DEFAULT_START, MONITOR_OS_PENDING_READS}, {"os_pending_writes", "os", "Number of writes pending", - MONITOR_NONE, + MONITOR_DEFAULT_ON, MONITOR_DEFAULT_START, MONITOR_OS_PENDING_WRITES}, {"os_log_bytes_written", "os", diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index ffa1e36ebcd..c47119e63cf 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -1735,10 +1735,10 @@ srv_export_innodb_status(void) mutex_enter(&srv_innodb_monitor_mutex); export_vars.innodb_data_pending_reads = - os_n_pending_reads; + MONITOR_VALUE(MONITOR_OS_PENDING_READS); export_vars.innodb_data_pending_writes = - os_n_pending_writes; + MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); export_vars.innodb_data_pending_fsyncs = fil_n_pending_log_flushes diff --git a/storage/xtradb/sync/sync0arr.cc b/storage/xtradb/sync/sync0arr.cc index e16eddae80c..7325cb49145 100644 --- a/storage/xtradb/sync/sync0arr.cc +++ b/storage/xtradb/sync/sync0arr.cc @@ -1161,9 +1161,10 @@ sync_array_print_long_waits( now the values of pending calls of these. */ fprintf(stderr, - "InnoDB: Pending preads %lu, pwrites %lu\n", - (ulong) os_file_n_pending_preads, - (ulong) os_file_n_pending_pwrites); + "InnoDB: Pending reads " UINT64PF + ", writes " UINT64PF "\n", + MONITOR_VALUE(MONITOR_OS_PENDING_READS), + MONITOR_VALUE(MONITOR_OS_PENDING_WRITES)); srv_print_innodb_monitor = TRUE; os_event_set(srv_monitor_event); From 39f1917f467139d9ea3ab2f6415ce8f5fb934a69 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sat, 10 Sep 2016 20:42:20 +0200 Subject: [PATCH 062/148] Attempt to fix strange rpm dependency issue following prior patch --- cmake/cpack_rpm.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index c5af3e68984..5789eb7694a 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -218,6 +218,9 @@ SETA(CPACK_RPM_test_PACKAGE_PROVIDES "perl(mtr_io.pl)" "perl(mtr_match)" "perl(mtr_misc.pl)" + "perl(mtr_gcov.pl)" + "perl(mtr_gprof.pl)" + "perl(mtr_process.pl)" "perl(mtr_report)" "perl(mtr_results)" "perl(mtr_unique)") From 786363e89b834629410932afd3191af72b4001eb Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 18 Apr 2017 10:29:59 +0200 Subject: [PATCH 063/148] compiler warning way-too-smart compilers don't like the "confusing indentation" --- sql/item_sum.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 02d2875195d..9a2e2e6cd4c 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3429,7 +3429,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) args[i]->fix_fields(thd, args + i)) || args[i]->check_cols(1)) return TRUE; - with_subselect|= args[i]->with_subselect; + with_subselect|= args[i]->with_subselect; } /* skip charset aggregation for order columns */ From 036b689f187361848a315a192a83556256c0fe96 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 18 Apr 2017 11:29:02 +0200 Subject: [PATCH 064/148] MDEV-12310 openat(, ...O_EXEC) fails on Illumos / Solaris it could be * O_SEARCH on Illumos * O_EXEC on FreeBSD * O_PATH on Linux ugh --- mysys/mysys_priv.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 4b489504c26..661c4c184f1 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -89,9 +89,13 @@ void sf_free(void *ptr); void my_error_unregister_all(void); -#if !defined(O_PATH) && defined(O_EXEC) /* FreeBSD */ +#ifndef O_PATH /* not Linux */ +#if defined(O_SEARCH) /* Illumos */ +#define O_PATH O_SEARCH +#elif defined(O_EXEC) /* FreeBSD */ #define O_PATH O_EXEC #endif +#endif #ifdef O_PATH #define HAVE_OPEN_PARENT_DIR_NOSYMLINKS From 0001049be0af0d5386cbf6009aeb2101243b311a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 18 Apr 2017 11:36:11 +0200 Subject: [PATCH 065/148] MDEV-12276 Missing DBUG_RETURN or DBUG_VOID_RETURN macro in function "do_exec" --- client/mysqltest.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 5327bb7717b..b22959677d0 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1038,7 +1038,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query, if (!(v= var_get(p, &p, 0, 0))) { report_or_die( "Bad variable in eval"); - return; + DBUG_VOID_RETURN; } dynstr_append_mem(query_eval, v->str_val, v->str_val_len); } @@ -1753,7 +1753,7 @@ static int run_command(char* cmd, if (!(res_file= popen(cmd, "r"))) { report_or_die("popen(\"%s\", \"r\") failed", cmd); - return -1; + DBUG_RETURN(-1); } while (fgets(buf, sizeof(buf), res_file)) @@ -2661,7 +2661,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end) report_or_die("Query '%s' didn't return a result set", ds_query.str); dynstr_free(&ds_query); eval_expr(var, "", 0); - return; + DBUG_VOID_RETURN; } dynstr_free(&ds_query); @@ -2852,7 +2852,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var) dynstr_free(&ds_query); dynstr_free(&ds_col); eval_expr(var, "", 0); - return; + DBUG_VOID_RETURN; } { @@ -2877,7 +2877,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var) ds_col.str, ds_query.str); dynstr_free(&ds_query); dynstr_free(&ds_col); - return; + DBUG_VOID_RETURN; } DBUG_PRINT("info", ("Found column %d with name '%s'", i, fields[i].name)); @@ -3323,7 +3323,7 @@ void do_exec(struct st_command *command) if (!*cmd) { report_or_die("Missing argument in exec"); - return; + DBUG_VOID_RETURN; } command->last_argument= command->end; @@ -3357,7 +3357,7 @@ void do_exec(struct st_command *command) dynstr_free(&ds_cmd); if (command->abort_on_error) report_or_die("popen(\"%s\", \"r\") failed", command->first_argument); - return; + DBUG_VOID_RETURN; } ds_result= &ds_res; @@ -3415,7 +3415,7 @@ void do_exec(struct st_command *command) ds_cmd.str, error, status, errno, ds_res.str); dynstr_free(&ds_cmd); - return; + DBUG_VOID_RETURN; } DBUG_PRINT("info", @@ -3547,7 +3547,7 @@ void do_system(struct st_command *command) if (strlen(command->first_argument) == 0) { report_or_die("Missing arguments to system, nothing to do!"); - return; + DBUG_VOID_RETURN; } init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256); @@ -4540,7 +4540,7 @@ void do_perl(struct st_command *command) if (command->abort_on_error) die("popen(\"%s\", \"r\") failed", buf); dynstr_free(&ds_delimiter); - return; + DBUG_VOID_RETURN; } while (fgets(buf, sizeof(buf), res_file)) From 4fe65ca33a6012ec60c665f6eeb5ff08969fb267 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 18 Apr 2017 12:35:05 +0200 Subject: [PATCH 066/148] =?UTF-8?q?MDEV-12230=20include/my=5Fsys.h:600:43:?= =?UTF-8?q?=20error:=20unknown=20type=20name=20=E2=80=98PSI=5Ffile=5Fkey?= =?UTF-8?q?=E2=80=99"=20when=20-DWITHOUT=5FSERVER=3D1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cherry-pick 2c2bd8c155 (MDEV-12261 build failure without P_S) from 10.0 --- include/my_sys.h | 3 +- include/mysql/psi/mysql_file.h | 47 ++++++++++++++++++++++++++++++++ mysys/my_symlink2.c | 14 ++++------ sql/handler.cc | 2 +- sql/sql_db.cc | 4 +-- storage/maria/ma_delete_table.c | 4 +-- storage/myisam/mi_delete_table.c | 4 +-- 7 files changed, 61 insertions(+), 17 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 10551e119ac..27940683dad 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -580,8 +580,7 @@ extern File my_create_with_symlink(const char *linkname, const char *filename, myf MyFlags); extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags); extern int my_symlink(const char *content, const char *linkname, myf MyFlags); -extern int my_handler_delete_with_symlink(PSI_file_key key, const char *name, - const char *ext, myf sync_dir); +extern int my_handler_delete_with_symlink(const char *filename, myf sync_dir); extern size_t my_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags); extern size_t my_pread(File Filedes,uchar *Buffer,size_t Count,my_off_t offset, diff --git a/include/mysql/psi/mysql_file.h b/include/mysql/psi/mysql_file.h index 4a0f3fdd68b..aa3ed7e901d 100644 --- a/include/mysql/psi/mysql_file.h +++ b/include/mysql/psi/mysql_file.h @@ -434,6 +434,20 @@ inline_mysql_file_create_with_symlink(P1, P2, P3, P4, P5) #endif +/** + @def mysql_file_delete_with_symlink(K, P1, P2, P3) + Instrumented delete with symbolic link. + @c mysql_file_delete_with_symlink is a replacement + for @c my_handler_delete_with_symlink. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_delete_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_delete_with_symlink(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_delete_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_delete_with_symlink(P1, P2, P3) +#endif + /** @def mysql_file_rename_with_symlink(K, P1, P2, P3) Instrumented rename with symbolic link. @@ -1305,6 +1319,7 @@ inline_mysql_file_rename( return result; } + static inline File inline_mysql_file_create_with_symlink( #ifdef HAVE_PSI_INTERFACE @@ -1334,6 +1349,38 @@ inline_mysql_file_create_with_symlink( return file; } +static inline int +inline_mysql_file_delete_with_symlink( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *name, const char *ext, myf flags) +{ + int result; + char fullname[FN_REFLEN]; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + PSI_file_locker_state state; +#endif + fn_format(fullname, name, "", ext, MY_UNPACK_FILENAME | MY_APPEND_EXT); +#ifdef HAVE_PSI_INTERFACE + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(&state, key, PSI_FILE_DELETE, + fullname, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_handler_delete_with_symlink(fullname, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + + static inline int inline_mysql_file_rename_with_symlink( #ifdef HAVE_PSI_INTERFACE diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index 5fe7b8fcae9..c851468ce1b 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -170,22 +170,20 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) in this case both the symlink and the symlinked file are deleted, but only if the symlinked file is not in the datadir. */ -int my_handler_delete_with_symlink(PSI_file_key key, const char *name, - const char *ext, myf sync_dir) +int my_handler_delete_with_symlink(const char *filename, myf sync_dir) { - char orig[FN_REFLEN], real[FN_REFLEN]; + char real[FN_REFLEN]; int res= 0; DBUG_ENTER("my_handler_delete_with_symlink"); - fn_format(orig, name, "", ext, MY_UNPACK_FILENAME | MY_APPEND_EXT); - if (my_is_symlink(orig)) + if (my_is_symlink(filename)) { /* Delete the symlinked file only if the symlink is not pointing into datadir. */ - if (!(my_realpath(real, orig, MYF(0)) || mysys_test_invalid_symlink(real))) - res= mysql_file_delete(key, real, MYF(MY_NOSYMLINKS | MY_WME | sync_dir)); + if (!(my_realpath(real, filename, MYF(0)) || mysys_test_invalid_symlink(real))) + res= my_delete(real, MYF(MY_NOSYMLINKS | sync_dir)); } - DBUG_RETURN(mysql_file_delete(key, orig, MYF(MY_WME | sync_dir)) || res); + DBUG_RETURN(my_delete(filename, MYF(sync_dir)) || res); } diff --git a/sql/handler.cc b/sql/handler.cc index 2ae144a86cc..dc40e34bc3d 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3381,7 +3381,7 @@ int handler::delete_table(const char *name) for (const char **ext=bas_ext(); *ext ; ext++) { - if (my_handler_delete_with_symlink(key_file_misc, name, *ext, 0)) + if (mysql_file_delete_with_symlink(key_file_misc, name, *ext, 0)) { if (my_errno != ENOENT) { diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 7bb4f0fa60e..580590b38a3 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1085,7 +1085,7 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp, We ignore ENOENT error in order to skip files that was deleted by concurrently running statement like REPAIR TABLE ... */ - if (my_handler_delete_with_symlink(key_file_misc, filePath, "", MYF(0)) && + if (mysql_file_delete_with_symlink(key_file_misc, filePath, "", MYF(0)) && my_errno != ENOENT) { my_error(EE_DELETE, MYF(0), filePath, my_errno); @@ -1206,7 +1206,7 @@ long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path) continue; } strxmov(filePath, org_path, "/", file->name, NullS); - if (my_handler_delete_with_symlink(key_file_misc, filePath, "", MYF(MY_WME))) + if (mysql_file_delete_with_symlink(key_file_misc, filePath, "", MYF(MY_WME))) { goto err; } diff --git a/storage/maria/ma_delete_table.c b/storage/maria/ma_delete_table.c index c4bcd5ba060..f80ec1384b3 100644 --- a/storage/maria/ma_delete_table.c +++ b/storage/maria/ma_delete_table.c @@ -86,8 +86,8 @@ int maria_delete_table_files(const char *name, myf sync_dir) { DBUG_ENTER("maria_delete_table_files"); - if (my_handler_delete_with_symlink(key_file_kfile, name, MARIA_NAME_IEXT, sync_dir) || - my_handler_delete_with_symlink(key_file_dfile, name, MARIA_NAME_DEXT, sync_dir)) + if (mysql_file_delete_with_symlink(key_file_kfile, name, MARIA_NAME_IEXT, sync_dir) || + mysql_file_delete_with_symlink(key_file_dfile, name, MARIA_NAME_DEXT, sync_dir)) DBUG_RETURN(my_errno); DBUG_RETURN(0); } diff --git a/storage/myisam/mi_delete_table.c b/storage/myisam/mi_delete_table.c index ebedfbda343..ca395ffbef5 100644 --- a/storage/myisam/mi_delete_table.c +++ b/storage/myisam/mi_delete_table.c @@ -28,8 +28,8 @@ int mi_delete_table(const char *name) check_table_is_closed(name,"delete"); #endif - if (my_handler_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, 0) || - my_handler_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, 0)) + if (mysql_file_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, 0) || + mysql_file_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, 0)) DBUG_RETURN(my_errno); DBUG_RETURN(0); } From c6ee3fe9d4056dcd6ee9f9aabd3424c1b27fc506 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 19 Apr 2017 20:31:05 +0200 Subject: [PATCH 067/148] respect client's desire to force ssl even when WITH_SSL=NO of course, this combination can never succeed, we must fail to connect here. --- sql-common/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index b348afcff2d..e0412fca6bc 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1815,8 +1815,8 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , mysql->options.ssl_ca= set_ssl_option_unpack_path(ca); mysql->options.ssl_capath= set_ssl_option_unpack_path(capath); mysql->options.ssl_cipher= strdup_if_not_null(cipher); - mysql->options.use_ssl= TRUE; #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ + mysql->options.use_ssl= TRUE; DBUG_RETURN(0); } @@ -2563,7 +2563,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, int3store(buff+2, net->max_packet_size); end= buff+5; } -#ifdef HAVE_OPENSSL /* If client uses ssl and client also has to verify the server @@ -2581,6 +2580,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, goto error; } +#ifdef HAVE_OPENSSL if (mysql->client_flag & CLIENT_SSL) { /* Do the SSL layering. */ From 87b6df31c4ae97c09dc67e370978112fe39764bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 21 Apr 2017 04:36:50 +0300 Subject: [PATCH 068/148] MDEV-12488 Remove type mismatch in InnoDB printf-like calls This is a reduced version of an originally much larger patch. We will keep the definition of the ulint, lint data types unchanged, and we will not be replacing fprintf() calls with ib_logf(). On Windows, use the standard format strings instead of nonstandard extensions. This patch fixes some errors in format strings. Most notably, an IMPORT TABLESPACE error message in InnoDB was displaying the number of columns instead of the mismatching flags. --- extra/innochecksum.cc | 34 +++-- .../suite/innodb/r/innodb-wl5522,xtradb.rdiff | 56 -------- .../suite/innodb/r/innodb-wl5522.result | 12 +- storage/innobase/include/univ.i | 16 +-- storage/innobase/log/log0recv.cc | 6 +- storage/innobase/row/row0import.cc | 128 +++++++++-------- storage/innobase/row/row0merge.cc | 65 +++++---- storage/xtradb/include/univ.i | 16 +-- storage/xtradb/log/log0recv.cc | 6 +- storage/xtradb/row/row0import.cc | 131 +++++++++--------- storage/xtradb/row/row0merge.cc | 66 +++++---- 11 files changed, 238 insertions(+), 298 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/innodb-wl5522,xtradb.rdiff diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index c09458630c8..04807334baa 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -360,12 +360,13 @@ int main(int argc, char **argv) { if (verbose) printf("Number of pages: "); - printf("%lu\n", pages); + printf(ULINTPF "\n", pages); goto ok; } else if (verbose) { - printf("file %s = %llu bytes (%lu pages)...\n", filename, size, (ulong)pages); + printf("file %s = %llu bytes (" ULINTPF " pages)...\n", + filename, size, pages); if (do_one_page) printf("InnoChecksum; checking page %lu\n", do_page); else @@ -421,7 +422,8 @@ int main(int argc, char **argv) if (compressed) { /* compressed pages */ if (!page_zip_verify_checksum(buf, physical_page_size)) { - fprintf(stderr, "Fail; page %lu invalid (fails compressed page checksum).\n", ct); + fprintf(stderr, "Fail; page " ULINTPF + " invalid (fails compressed page checksum).\n", ct); if (!skip_corrupt) goto error; } @@ -431,10 +433,14 @@ int main(int argc, char **argv) logseq= mach_read_from_4(buf + FIL_PAGE_LSN + 4); logseqfield= mach_read_from_4(buf + logical_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM + 4); if (debug) - printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield); + printf("page " ULINTPF + ": log sequence number: first = " ULINTPF + "; second = " ULINTPF "\n", + ct, logseq, logseqfield); if (logseq != logseqfield) { - fprintf(stderr, "Fail; page %lu invalid (fails log sequence number check)\n", ct); + fprintf(stderr, "Fail; page " ULINTPF + " invalid (fails log sequence number check)\n", ct); if (!skip_corrupt) goto error; } @@ -443,10 +449,14 @@ int main(int argc, char **argv) oldcsum= buf_calc_page_old_checksum(buf); oldcsumfield= mach_read_from_4(buf + logical_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM); if (debug) - printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield); + printf("page " ULINTPF + ": old style: calculated = " ULINTPF + "; recorded = " ULINTPF "\n", + ct, oldcsum, oldcsumfield); if (oldcsumfield != mach_read_from_4(buf + FIL_PAGE_LSN) && oldcsumfield != oldcsum) { - fprintf(stderr, "Fail; page %lu invalid (fails old style checksum)\n", ct); + fprintf(stderr, "Fail; page " ULINTPF + " invalid (fails old style checksum)\n", ct); if (!skip_corrupt) goto error; } @@ -456,11 +466,14 @@ int main(int argc, char **argv) crc32= buf_calc_page_crc32(buf); csumfield= mach_read_from_4(buf + FIL_PAGE_SPACE_OR_CHKSUM); if (debug) - printf("page %lu: new style: calculated = %lu; crc32 = %lu; recorded = %lu\n", + printf("page " ULINTPF + ": new style: calculated = " ULINTPF + "; crc32 = " ULINTPF "; recorded = " ULINTPF "\n", ct, csum, crc32, csumfield); if (csumfield != 0 && crc32 != csumfield && csum != csumfield) { - fprintf(stderr, "Fail; page %lu invalid (fails innodb and crc32 checksum)\n", ct); + fprintf(stderr, "Fail; page " ULINTPF + " invalid (fails innodb and crc32 checksum)\n", ct); if (!skip_corrupt) goto error; } @@ -479,7 +492,8 @@ int main(int argc, char **argv) if (!lastt) lastt= now; if (now - lastt >= 1) { - printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100); + printf("page " ULINTPF " okay: %.3f%% done\n", + (ct - 1), (float) ct / pages * 100); lastt= now; } } diff --git a/mysql-test/suite/innodb/r/innodb-wl5522,xtradb.rdiff b/mysql-test/suite/innodb/r/innodb-wl5522,xtradb.rdiff deleted file mode 100644 index 4aea0b451ec..00000000000 --- a/mysql-test/suite/innodb/r/innodb-wl5522,xtradb.rdiff +++ /dev/null @@ -1,56 +0,0 @@ ---- suite/innodb/r/innodb-wl5522.result -+++ suite/innodb/r/innodb-wl5522.reject -@@ -580,7 +580,7 @@ - ERROR HY000: Tablespace has been discarded for table 't1' - restore: t1 .ibd and .cfg files - ALTER TABLE t1 IMPORT TABLESPACE; --ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x0) -+ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x0) - unlink: t1.ibd - unlink: t1.cfg - DROP TABLE t1; -@@ -592,7 +592,7 @@ - ERROR HY000: Tablespace has been discarded for table 't1' - restore: t1 .ibd and .cfg files - ALTER TABLE t1 IMPORT TABLESPACE; --ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x0) -+ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x0) - unlink: t1.ibd - unlink: t1.cfg - DROP TABLE t1; -@@ -766,7 +766,7 @@ - ERROR HY000: Tablespace has been discarded for table 't1' - restore: t1 .ibd and .cfg files - ALTER TABLE t1 IMPORT TABLESPACE; --ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x1) -+ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x1) - unlink: t1.ibd - unlink: t1.cfg - DROP TABLE t1; -@@ -778,7 +778,7 @@ - ERROR HY000: Tablespace has been discarded for table 't1' - restore: t1 .ibd and .cfg files - ALTER TABLE t1 IMPORT TABLESPACE; --ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x1) -+ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1) - unlink: t1.ibd - unlink: t1.cfg - DROP TABLE t1; -@@ -955,7 +955,7 @@ - ERROR HY000: Tablespace has been discarded for table 't1' - restore: t1 .ibd and .cfg files - ALTER TABLE t1 IMPORT TABLESPACE; --ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x21) -+ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x21) - unlink: t1.ibd - unlink: t1.cfg - DROP TABLE t1; -@@ -967,7 +967,7 @@ - ERROR HY000: Tablespace has been discarded for table 't1' - restore: t1 .ibd and .cfg files - ALTER TABLE t1 IMPORT TABLESPACE; --ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x21) -+ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x21) - unlink: t1.ibd - unlink: t1.cfg - DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-wl5522.result b/mysql-test/suite/innodb/r/innodb-wl5522.result index fb4ac37b9fd..2116dfbf3fa 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522.result @@ -580,7 +580,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x0) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x0) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -592,7 +592,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x0) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x0) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -766,7 +766,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x1) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x1) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -778,7 +778,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x1) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -955,7 +955,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x21) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x21) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -967,7 +967,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x5 and the meta-data file has 0x21) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x21) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index fc0bf0aeeca..eff834503ad 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -419,13 +419,12 @@ the word size of the machine, that is on a 32-bit platform 32 bits, and on a macro ULINTPF. */ -#ifdef __WIN__ +#ifdef _WIN32 /* Use the integer types and formatting strings defined in Visual Studio. */ -# define UINT32PF "%I32u" -# define INT64PF "%I64d" -# define UINT64PF "%I64u" -# define UINT64PFx "%016I64x" -# define DBUG_LSN_PF "%llu" +# define UINT32PF "%u" +# define INT64PF "%lld" +# define UINT64PF "%llu" +# define UINT64PFx "%016llx" typedef __int64 ib_int64_t; typedef unsigned __int64 ib_uint64_t; typedef unsigned __int32 ib_uint32_t; @@ -435,13 +434,12 @@ typedef unsigned __int32 ib_uint32_t; # define INT64PF "%" PRId64 # define UINT64PF "%" PRIu64 # define UINT64PFx "%016" PRIx64 -# define DBUG_LSN_PF UINT64PF typedef int64_t ib_int64_t; typedef uint64_t ib_uint64_t; typedef uint32_t ib_uint32_t; -# endif /* __WIN__ */ +#endif -# define IB_ID_FMT UINT64PF +#define IB_ID_FMT UINT64PF #ifdef _WIN64 typedef unsigned __int64 ulint; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index a90041aaa90..ec9c2795d0a 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1702,7 +1702,7 @@ recv_recover_page_func( } DBUG_PRINT("ib_log", - ("apply " DBUG_LSN_PF ": %u len %u " + ("apply " LSN_PF ": %u len %u " "page %u:%u", recv->start_lsn, (unsigned) recv->type, (unsigned) recv->len, @@ -2350,7 +2350,7 @@ loop: recv_sys->recovered_lsn = new_recovered_lsn; DBUG_PRINT("ib_log", - ("scan " DBUG_LSN_PF ": log rec %u len %u " + ("scan " LSN_PF ": log rec %u len %u " "page %u:%u", old_lsn, (unsigned) type, (unsigned) len, (unsigned) space, (unsigned) page_no)); @@ -2441,7 +2441,7 @@ loop: #endif /* UNIV_LOG_DEBUG */ DBUG_PRINT("ib_log", - ("scan " DBUG_LSN_PF ": multi-log rec %u " + ("scan " LSN_PF ": multi-log rec %u " "len %u page %u:%u", recv_sys->recovered_lsn, (unsigned) type, (unsigned) len, diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 12609c3a65d..da8e1aab2c9 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -573,8 +574,8 @@ AbstractCallback::init( } else if (!is_compressed_table() && m_page_size != UNIV_PAGE_SIZE) { ib_logf(IB_LOG_LEVEL_ERROR, - "Page size %lu of ibd file is not the same " - "as the server page size %lu", + "Page size " ULINTPF " of ibd file is not the same " + "as the server page size " ULINTPF, m_page_size, UNIV_PAGE_SIZE); return(DB_CORRUPTION); @@ -583,8 +584,8 @@ AbstractCallback::init( ib_logf(IB_LOG_LEVEL_ERROR, "File size " UINT64PF " is not a multiple " - "of the page size %lu", - (ib_uint64_t) file_size, (ulong) m_page_size); + "of the page size " ULINTPF, + (ib_uint64_t) file_size, m_page_size); return(DB_CORRUPTION); } @@ -725,8 +726,8 @@ FetchIndexRootPages::operator() ( if (block->page.offset * m_page_size != offset) { ib_logf(IB_LOG_LEVEL_ERROR, "Page offset doesn't match file offset: " - "page offset: %lu, file offset: %lu", - (ulint) block->page.offset, + "page offset: %u, file offset: " ULINTPF, + block->page.offset, (ulint) (offset / m_page_size)); err = DB_CORRUPTION; @@ -1159,10 +1160,9 @@ row_import::match_index_columns( ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Index field count %lu doesn't match" - " tablespace metadata file value %lu", - (ulong) index->n_fields, - (ulong) cfg_index->m_n_fields); + "Index field count %u doesn't match" + " tablespace metadata file value " ULINTPF, + index->n_fields, cfg_index->m_n_fields); return(DB_ERROR); } @@ -1179,34 +1179,31 @@ row_import::match_index_columns( ER_TABLE_SCHEMA_MISMATCH, "Index field name %s doesn't match" " tablespace metadata field name %s" - " for field position %lu", - field->name, cfg_field->name, (ulong) i); + " for field position " ULINTPF, + field->name, cfg_field->name, i); err = DB_ERROR; } if (cfg_field->prefix_len != field->prefix_len) { ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Index %s field %s prefix len %lu" - " doesn't match metadata file value" - " %lu", - index->name, field->name, - (ulong) field->prefix_len, - (ulong) cfg_field->prefix_len); + ER_TABLE_SCHEMA_MISMATCH, + "Index %s field %s prefix len %u" + " doesn't match metadata file value %u", + index->name, field->name, + field->prefix_len, cfg_field->prefix_len); err = DB_ERROR; } if (cfg_field->fixed_len != field->fixed_len) { ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Index %s field %s fixed len %lu" - " doesn't match metadata file value" - " %lu", - index->name, field->name, - (ulong) field->fixed_len, - (ulong) cfg_field->fixed_len); + ER_TABLE_SCHEMA_MISMATCH, + "Index %s field %s fixed len %u" + " doesn't match metadata file value %u", + index->name, field->name, + field->fixed_len, + cfg_field->fixed_len); err = DB_ERROR; } @@ -1248,12 +1245,11 @@ row_import::match_table_columns( } else if (cfg_col_index != col->ind) { ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Column %s ordinal value mismatch, it's at " - "%lu in the table and %lu in the tablespace " - "meta-data file", - col_name, - (ulong) col->ind, (ulong) cfg_col_index); + ER_TABLE_SCHEMA_MISMATCH, + "Column %s ordinal value mismatch, it's at %u" + " in the table and " ULINTPF + " in the tablespace meta-data file", + col_name, col->ind, cfg_col_index); err = DB_ERROR; } else { @@ -1336,19 +1332,19 @@ row_import::match_schema( { /* Do some simple checks. */ - if (m_flags != m_table->flags) { + if ((m_table->flags ^ m_flags) & ~DICT_TF_MASK_DATA_DIR) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Table flags don't match, server table has 0x%lx " - "and the meta-data file has 0x%lx", - (ulong) m_table->n_cols, (ulong) m_flags); + "Table flags don't match, server table has 0x%x" + " and the meta-data file has 0x%lx", + m_table->flags, ulong(m_flags)); return(DB_ERROR); } else if (m_table->n_cols != m_n_cols) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Number of columns don't match, table has %lu " - "columns but the tablespace meta-data file has " - "%lu columns", - (ulong) m_table->n_cols, (ulong) m_n_cols); + "Number of columns don't match, table has %u" + " columns but the tablespace meta-data file has " + ULINTPF " columns", + m_table->n_cols, m_n_cols); return(DB_ERROR); } else if (UT_LIST_GET_LEN(m_table->indexes) != m_n_indexes) { @@ -1358,11 +1354,10 @@ row_import::match_schema( table matching the IMPORT definition. */ ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Number of indexes don't match, table has %lu " - "indexes but the tablespace meta-data file has " - "%lu indexes", - (ulong) UT_LIST_GET_LEN(m_table->indexes), - (ulong) m_n_indexes); + "Number of indexes don't match, table has " ULINTPF + " indexes but the tablespace meta-data file has " + ULINTPF " indexes", + UT_LIST_GET_LEN(m_table->indexes), m_n_indexes); return(DB_ERROR); } @@ -1438,8 +1433,8 @@ row_import::set_root_by_heuristic() UNIV_NOTHROW table_name, sizeof(table_name), m_table->name, FALSE); ib_logf(IB_LOG_LEVEL_WARN, - "Table %s should have %lu indexes but the tablespace " - "has %lu indexes", + "Table %s should have " ULINTPF + " indexes but the tablespace has " ULINTPF " indexes", table_name, UT_LIST_GET_LEN(m_table->indexes), m_n_indexes); @@ -1677,9 +1672,10 @@ PageConverter::adjust_cluster_index_blob_column( ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_INNODB_INDEX_CORRUPT, - "Externally stored column(%lu) has a reference " - "length of %lu in the cluster index %s", - (ulong) i, (ulong) len, index_name); + "Externally stored column(" ULINTPF + ") has a reference length of " ULINTPF + " in the cluster index %s", + i, len, index_name); return(DB_CORRUPTION); } @@ -2040,7 +2036,8 @@ PageConverter::update_page( return(err); } - ib_logf(IB_LOG_LEVEL_WARN, "Unknown page type (%lu)", page_type); + ib_logf(IB_LOG_LEVEL_WARN, "Unknown page type (" ULINTPF ")", + page_type); return(DB_CORRUPTION); } @@ -2074,7 +2071,8 @@ PageConverter::validate( if (checksum != 0) { /* Checksum check passed in buf_page_is_corrupted(). */ ib_logf(IB_LOG_LEVEL_WARN, - "%s: Page %lu checksum %lu should be zero.", + "%s: Page %lu checksum " ULINTPF + " should be zero.", m_filepath, (ulong) (offset / m_page_size), checksum); } @@ -2388,11 +2386,10 @@ row_import_adjust_root_pages_of_secondary_indexes( ib_errf(trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_INNODB_INDEX_CORRUPT, - "Index '%s' contains %lu entries, " - "should be %lu, you should recreate " + "Index '%s' contains " ULINTPF " entries, " + "should be " ULINTPF ", you should recreate " "this index.", index_name, - (ulong) purge.get_n_rows(), - (ulong) n_rows_in_table); + purge.get_n_rows(), n_rows_in_table); index->type |= DICT_CORRUPT; @@ -2743,7 +2740,7 @@ row_import_read_index_data( if (len > OS_FILE_MAX_PATH) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_INNODB_INDEX_CORRUPT, - "Index name length (%lu) is too long, " + "Index name length (" ULINTPF ") is too long, " "the meta-data is corrupt", len); return(DB_CORRUPTION); @@ -2824,8 +2821,8 @@ row_import_read_indexes( } else if (cfg->m_n_indexes > 1024) { // FIXME: What is the upper limit? */ ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - "Number of indexes in meta-data file is too high: %lu", - (ulong) cfg->m_n_indexes); + "Number of indexes in meta-data file is too high: " + ULINTPF, cfg->m_n_indexes); cfg->m_n_indexes = 0; return(DB_CORRUPTION); @@ -2923,8 +2920,8 @@ row_import_read_columns( if (len == 0 || len > 128) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - "Column name length %lu, is invalid", - (ulong) len); + "Column name length " ULINTPF ", is invalid", + len); return(DB_CORRUPTION); } @@ -3095,8 +3092,9 @@ row_import_read_v1( ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, "Tablespace to be imported has a different " "page size than this server. Server page size " - "is %lu, whereas tablespace page size is %lu", - UNIV_PAGE_SIZE, (ulong) cfg->m_page_size); + "is " ULINTPF ", whereas tablespace page size is " + ULINTPF, + UNIV_PAGE_SIZE, cfg->m_page_size); return(DB_ERROR); } @@ -3161,8 +3159,8 @@ row_import_read_meta_data( return(row_import_read_v1(file, thd, &cfg)); default: ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - "Unsupported meta-data version number (%lu), " - "file ignored", (ulong) cfg.m_version); + "Unsupported meta-data version number (" ULINTPF "), " + "file ignored", cfg.m_version); } return(DB_ERROR); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index f214633e9ce..33345c2e6f2 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 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 @@ -95,7 +96,8 @@ row_merge_tuple_print( } ut_print_buf(f, dfield_get_data(field), len); if (len != field_len) { - fprintf(f, " (total %lu bytes)", field_len); + fprintf(f, " (total " ULINTPF " bytes)", + field_len); } } } @@ -781,9 +783,9 @@ row_merge_buf_write( ut_ad(b < &block[srv_sort_buf_size]); #ifdef UNIV_DEBUG if (row_merge_print_write) { - fprintf(stderr, "row_merge_buf_write %p,%d,%lu %lu", - (void*) b, of->fd, (ulong) of->offset, - (ulong) i); + fprintf(stderr, "row_merge_buf_write %p,%d," + ULINTPF " " ULINTPF, + (void*) b, of->fd, of->offset, i); row_merge_tuple_print(stderr, entry, n_fields); } #endif /* UNIV_DEBUG */ @@ -800,8 +802,8 @@ row_merge_buf_write( #endif /* UNIV_DEBUG_VALGRIND */ #ifdef UNIV_DEBUG if (row_merge_print_write) { - fprintf(stderr, "row_merge_buf_write %p,%d,%lu EOF\n", - (void*) b, of->fd, (ulong) of->offset); + fprintf(stderr, "row_merge_buf_write %p,%d," ULINTPF " EOF\n", + (void*) b, of->fd, of->offset); } #endif /* UNIV_DEBUG */ } @@ -857,15 +859,8 @@ row_merge_read( #ifdef UNIV_DEBUG if (row_merge_print_block_read) { - fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n", - fd, (ulong) offset); - } -#endif /* UNIV_DEBUG */ - -#ifdef UNIV_DEBUG - if (row_merge_print_block_read) { - fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n", - fd, (ulong) offset); + fprintf(stderr, "row_merge_read fd=%d ofs=" ULINTPF "\n", + fd, offset); } #endif /* UNIV_DEBUG */ @@ -908,8 +903,8 @@ row_merge_write( #ifdef UNIV_DEBUG if (row_merge_print_block_write) { - fprintf(stderr, "row_merge_write fd=%d ofs=%lu\n", - fd, (ulong) offset); + fprintf(stderr, "row_merge_write fd=%d ofs=" ULINTPF "\n", + fd, offset); } #endif /* UNIV_DEBUG */ @@ -957,9 +952,10 @@ row_merge_read_rec( *mrec = NULL; #ifdef UNIV_DEBUG if (row_merge_print_read) { - fprintf(stderr, "row_merge_read %p,%p,%d,%lu EOF\n", + fprintf(stderr, "row_merge_read %p,%p,%d," ULINTPF + " EOF\n", (const void*) b, (const void*) block, - fd, (ulong) *foffs); + fd, *foffs); } #endif /* UNIV_DEBUG */ return(NULL); @@ -1074,9 +1070,9 @@ err_exit: func_exit: #ifdef UNIV_DEBUG if (row_merge_print_read) { - fprintf(stderr, "row_merge_read %p,%p,%d,%lu ", + fprintf(stderr, "row_merge_read %p,%p,%d," ULINTPF " ", (const void*) b, (const void*) block, - fd, (ulong) *foffs); + fd, *foffs); rec_print_comp(stderr, *mrec, offsets); putc('\n', stderr); } @@ -1110,8 +1106,8 @@ row_merge_write_rec_low( ut_ad(e == rec_offs_extra_size(offsets) + 1); if (row_merge_print_write) { - fprintf(stderr, "row_merge_write %p,%d,%lu ", - (void*) b, fd, (ulong) foffs); + fprintf(stderr, "row_merge_write %p,%d," ULINTPF " ", + (void*) b, fd, foffs); rec_print_comp(stderr, mrec, offsets); putc('\n', stderr); } @@ -1213,8 +1209,8 @@ row_merge_write_eof( ut_ad(foffs); #ifdef UNIV_DEBUG if (row_merge_print_write) { - fprintf(stderr, "row_merge_write %p,%p,%d,%lu EOF\n", - (void*) b, (void*) block, fd, (ulong) *foffs); + fprintf(stderr, "row_merge_write %p,%p,%d," ULINTPF " EOF\n", + (void*) b, (void*) block, fd, *foffs); } #endif /* UNIV_DEBUG */ @@ -2053,11 +2049,12 @@ row_merge_blocks( #ifdef UNIV_DEBUG if (row_merge_print_block) { fprintf(stderr, - "row_merge_blocks fd=%d ofs=%lu + fd=%d ofs=%lu" - " = fd=%d ofs=%lu\n", - file->fd, (ulong) *foffs0, - file->fd, (ulong) *foffs1, - of->fd, (ulong) of->offset); + "row_merge_blocks fd=%d ofs=" ULINTPF + " + fd=%d ofs=" ULINTPF + " = fd=%d ofs=" ULINTPF "\n", + file->fd, *foffs0, + file->fd, *foffs1, + of->fd, of->offset); } #endif /* UNIV_DEBUG */ @@ -2156,10 +2153,10 @@ row_merge_blocks_copy( #ifdef UNIV_DEBUG if (row_merge_print_block) { fprintf(stderr, - "row_merge_blocks_copy fd=%d ofs=%lu" - " = fd=%d ofs=%lu\n", - file->fd, (ulong) foffs0, - of->fd, (ulong) of->offset); + "row_merge_blocks_copy fd=%d ofs=" ULINTPF + " = fd=%d ofs=" ULINTPF "\n", + file->fd, *foffs0, + of->fd, of->offset); } #endif /* UNIV_DEBUG */ diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 7497e7f5d05..fff5c0a67a1 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -438,13 +438,12 @@ the word size of the machine, that is on a 32-bit platform 32 bits, and on a macro ULINTPF. */ -#ifdef __WIN__ +#ifdef _WIN32 /* Use the integer types and formatting strings defined in Visual Studio. */ -# define UINT32PF "%I32u" -# define INT64PF "%I64d" -# define UINT64PF "%I64u" -# define UINT64PFx "%016I64x" -# define DBUG_LSN_PF "%llu" +# define UINT32PF "%u" +# define INT64PF "%lld" +# define UINT64PF "%llu" +# define UINT64PFx "%016llx" typedef __int64 ib_int64_t; typedef unsigned __int64 ib_uint64_t; typedef unsigned __int32 ib_uint32_t; @@ -454,13 +453,12 @@ typedef unsigned __int32 ib_uint32_t; # define INT64PF "%" PRId64 # define UINT64PF "%" PRIu64 # define UINT64PFx "%016" PRIx64 -# define DBUG_LSN_PF UINT64PF typedef int64_t ib_int64_t; typedef uint64_t ib_uint64_t; typedef uint32_t ib_uint32_t; -# endif /* __WIN__ */ +#endif -# define IB_ID_FMT UINT64PF +#define IB_ID_FMT UINT64PF #ifdef _WIN64 typedef unsigned __int64 ulint; diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc index afb8b7f00b8..4edfb1e4347 100644 --- a/storage/xtradb/log/log0recv.cc +++ b/storage/xtradb/log/log0recv.cc @@ -1792,7 +1792,7 @@ recv_recover_page_func( } DBUG_PRINT("ib_log", - ("apply " DBUG_LSN_PF ": %u len %u " + ("apply " LSN_PF ": %u len %u " "page %u:%u", recv->start_lsn, (unsigned) recv->type, (unsigned) recv->len, @@ -2440,7 +2440,7 @@ loop: recv_sys->recovered_lsn = new_recovered_lsn; DBUG_PRINT("ib_log", - ("scan " DBUG_LSN_PF ": log rec %u len %u " + ("scan " LSN_PF ": log rec %u len %u " "page %u:%u", old_lsn, (unsigned) type, (unsigned) len, (unsigned) space, (unsigned) page_no)); @@ -2531,7 +2531,7 @@ loop: #endif /* UNIV_LOG_DEBUG */ DBUG_PRINT("ib_log", - ("scan " DBUG_LSN_PF ": multi-log rec %u " + ("scan " LSN_PF ": multi-log rec %u " "len %u page %u:%u", recv_sys->recovered_lsn, (unsigned) type, (unsigned) len, diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index e1fef3d3716..23b9ba60269 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -573,8 +574,8 @@ AbstractCallback::init( } else if (!is_compressed_table() && m_page_size != UNIV_PAGE_SIZE) { ib_logf(IB_LOG_LEVEL_ERROR, - "Page size %lu of ibd file is not the same " - "as the server page size %lu", + "Page size " ULINTPF " of ibd file is not the same " + "as the server page size " ULINTPF, m_page_size, UNIV_PAGE_SIZE); return(DB_CORRUPTION); @@ -583,8 +584,8 @@ AbstractCallback::init( ib_logf(IB_LOG_LEVEL_ERROR, "File size " UINT64PF " is not a multiple " - "of the page size %lu", - (ib_uint64_t) file_size, (ulong) m_page_size); + "of the page size " ULINTPF, + (ib_uint64_t) file_size, m_page_size); return(DB_CORRUPTION); } @@ -725,8 +726,8 @@ FetchIndexRootPages::operator() ( if (block->page.offset * m_page_size != offset) { ib_logf(IB_LOG_LEVEL_ERROR, "Page offset doesn't match file offset: " - "page offset: %lu, file offset: %lu", - (ulint) block->page.offset, + "page offset: %u, file offset: " ULINTPF, + block->page.offset, (ulint) (offset / m_page_size)); err = DB_CORRUPTION; @@ -1159,10 +1160,9 @@ row_import::match_index_columns( ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Index field count %lu doesn't match" - " tablespace metadata file value %lu", - (ulong) index->n_fields, - (ulong) cfg_index->m_n_fields); + "Index field count %u doesn't match" + " tablespace metadata file value " ULINTPF, + index->n_fields, cfg_index->m_n_fields); return(DB_ERROR); } @@ -1179,34 +1179,31 @@ row_import::match_index_columns( ER_TABLE_SCHEMA_MISMATCH, "Index field name %s doesn't match" " tablespace metadata field name %s" - " for field position %lu", - field->name, cfg_field->name, (ulong) i); + " for field position " ULINTPF, + field->name, cfg_field->name, i); err = DB_ERROR; } if (cfg_field->prefix_len != field->prefix_len) { ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Index %s field %s prefix len %lu" - " doesn't match metadata file value" - " %lu", - index->name, field->name, - (ulong) field->prefix_len, - (ulong) cfg_field->prefix_len); + ER_TABLE_SCHEMA_MISMATCH, + "Index %s field %s prefix len %u" + " doesn't match metadata file value %u", + index->name, field->name, + field->prefix_len, cfg_field->prefix_len); err = DB_ERROR; } if (cfg_field->fixed_len != field->fixed_len) { ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Index %s field %s fixed len %lu" - " doesn't match metadata file value" - " %lu", - index->name, field->name, - (ulong) field->fixed_len, - (ulong) cfg_field->fixed_len); + ER_TABLE_SCHEMA_MISMATCH, + "Index %s field %s fixed len %u" + " doesn't match metadata file value %u", + index->name, field->name, + field->fixed_len, + cfg_field->fixed_len); err = DB_ERROR; } @@ -1248,12 +1245,11 @@ row_import::match_table_columns( } else if (cfg_col_index != col->ind) { ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Column %s ordinal value mismatch, it's at " - "%lu in the table and %lu in the tablespace " - "meta-data file", - col_name, - (ulong) col->ind, (ulong) cfg_col_index); + ER_TABLE_SCHEMA_MISMATCH, + "Column %s ordinal value mismatch, it's at %u" + " in the table and " ULINTPF + " in the tablespace meta-data file", + col_name, col->ind, cfg_col_index); err = DB_ERROR; } else { @@ -1335,23 +1331,20 @@ row_import::match_schema( THD* thd) UNIV_NOTHROW { /* Do some simple checks. */ - const unsigned relevant_flags = m_flags & ~DICT_TF_MASK_DATA_DIR; - const unsigned relevant_table_flags - = m_table->flags & ~DICT_TF_MASK_DATA_DIR; - if (relevant_flags != relevant_table_flags) { + if ((m_table->flags ^ m_flags) & ~DICT_TF_MASK_DATA_DIR) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Table flags don't match, server table has 0x%x " - "and the meta-data file has 0x%x", - relevant_table_flags, relevant_flags); + "Table flags don't match, server table has 0x%x" + " and the meta-data file has 0x%lx", + m_table->flags, ulong(m_flags)); return(DB_ERROR); } else if (m_table->n_cols != m_n_cols) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Number of columns don't match, table has %lu " - "columns but the tablespace meta-data file has " - "%lu columns", - (ulong) m_table->n_cols, (ulong) m_n_cols); + "Number of columns don't match, table has %u " + "columns but the tablespace meta-data file has " + ULINTPF " columns", + m_table->n_cols, m_n_cols); return(DB_ERROR); } else if (UT_LIST_GET_LEN(m_table->indexes) != m_n_indexes) { @@ -1361,11 +1354,10 @@ row_import::match_schema( table matching the IMPORT definition. */ ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Number of indexes don't match, table has %lu " - "indexes but the tablespace meta-data file has " - "%lu indexes", - (ulong) UT_LIST_GET_LEN(m_table->indexes), - (ulong) m_n_indexes); + "Number of indexes don't match, table has " ULINTPF + " indexes but the tablespace meta-data file has " + ULINTPF " indexes", + UT_LIST_GET_LEN(m_table->indexes), m_n_indexes); return(DB_ERROR); } @@ -1441,8 +1433,8 @@ row_import::set_root_by_heuristic() UNIV_NOTHROW table_name, sizeof(table_name), m_table->name, FALSE); ib_logf(IB_LOG_LEVEL_WARN, - "Table %s should have %lu indexes but the tablespace " - "has %lu indexes", + "Table %s should have " ULINTPF + " indexes but the tablespace has " ULINTPF " indexes", table_name, UT_LIST_GET_LEN(m_table->indexes), m_n_indexes); @@ -1680,9 +1672,10 @@ PageConverter::adjust_cluster_index_blob_column( ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_INNODB_INDEX_CORRUPT, - "Externally stored column(%lu) has a reference " - "length of %lu in the cluster index %s", - (ulong) i, (ulong) len, index_name); + "Externally stored column(" ULINTPF + ") has a reference length of " ULINTPF + " in the cluster index %s", + i, len, index_name); return(DB_CORRUPTION); } @@ -2043,7 +2036,8 @@ PageConverter::update_page( return(err); } - ib_logf(IB_LOG_LEVEL_WARN, "Unknown page type (%lu)", page_type); + ib_logf(IB_LOG_LEVEL_WARN, "Unknown page type (" ULINTPF ")", + page_type); return(DB_CORRUPTION); } @@ -2077,7 +2071,8 @@ PageConverter::validate( if (checksum != 0) { /* Checksum check passed in buf_page_is_corrupted(). */ ib_logf(IB_LOG_LEVEL_WARN, - "%s: Page %lu checksum %lu should be zero.", + "%s: Page %lu checksum " ULINTPF + " should be zero.", m_filepath, (ulong) (offset / m_page_size), checksum); } @@ -2391,11 +2386,10 @@ row_import_adjust_root_pages_of_secondary_indexes( ib_errf(trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_INNODB_INDEX_CORRUPT, - "Index '%s' contains %lu entries, " - "should be %lu, you should recreate " + "Index '%s' contains " ULINTPF " entries, " + "should be " ULINTPF ", you should recreate " "this index.", index_name, - (ulong) purge.get_n_rows(), - (ulong) n_rows_in_table); + purge.get_n_rows(), n_rows_in_table); index->type |= DICT_CORRUPT; @@ -2746,7 +2740,7 @@ row_import_read_index_data( if (len > OS_FILE_MAX_PATH) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_INNODB_INDEX_CORRUPT, - "Index name length (%lu) is too long, " + "Index name length (" ULINTPF ") is too long, " "the meta-data is corrupt", len); return(DB_CORRUPTION); @@ -2827,8 +2821,8 @@ row_import_read_indexes( } else if (cfg->m_n_indexes > 1024) { // FIXME: What is the upper limit? */ ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - "Number of indexes in meta-data file is too high: %lu", - (ulong) cfg->m_n_indexes); + "Number of indexes in meta-data file is too high: " + ULINTPF, cfg->m_n_indexes); cfg->m_n_indexes = 0; return(DB_CORRUPTION); @@ -2926,8 +2920,8 @@ row_import_read_columns( if (len == 0 || len > 128) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - "Column name length %lu, is invalid", - (ulong) len); + "Column name length " ULINTPF ", is invalid", + len); return(DB_CORRUPTION); } @@ -3098,8 +3092,9 @@ row_import_read_v1( ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, "Tablespace to be imported has a different " "page size than this server. Server page size " - "is %lu, whereas tablespace page size is %lu", - UNIV_PAGE_SIZE, (ulong) cfg->m_page_size); + "is " ULINTPF ", whereas tablespace page size is " + ULINTPF, + UNIV_PAGE_SIZE, cfg->m_page_size); return(DB_ERROR); } @@ -3164,8 +3159,8 @@ row_import_read_meta_data( return(row_import_read_v1(file, thd, &cfg)); default: ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - "Unsupported meta-data version number (%lu), " - "file ignored", (ulong) cfg.m_version); + "Unsupported meta-data version number (" ULINTPF "), " + "file ignored", cfg.m_version); } return(DB_ERROR); diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index bcc37fb530c..5082aae15cf 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -96,7 +96,8 @@ row_merge_tuple_print( } ut_print_buf(f, dfield_get_data(field), len); if (len != field_len) { - fprintf(f, " (total %lu bytes)", field_len); + fprintf(f, " (total " ULINTPF " bytes)", + field_len); } } } @@ -789,9 +790,9 @@ row_merge_buf_write( ut_ad(b < &block[srv_sort_buf_size]); #ifdef UNIV_DEBUG if (row_merge_print_write) { - fprintf(stderr, "row_merge_buf_write %p,%d,%lu %lu", - (void*) b, of->fd, (ulong) of->offset, - (ulong) i); + fprintf(stderr, "row_merge_buf_write %p,%d," + ULINTPF " " ULINTPF, + (void*) b, of->fd, of->offset, i); row_merge_tuple_print(stderr, entry, n_fields); } #endif /* UNIV_DEBUG */ @@ -808,8 +809,8 @@ row_merge_buf_write( #endif /* UNIV_DEBUG_VALGRIND */ #ifdef UNIV_DEBUG if (row_merge_print_write) { - fprintf(stderr, "row_merge_buf_write %p,%d,%lu EOF\n", - (void*) b, of->fd, (ulong) of->offset); + fprintf(stderr, "row_merge_buf_write %p,%d," ULINTPF " EOF\n", + (void*) b, of->fd, of->offset); } #endif /* UNIV_DEBUG */ } @@ -865,15 +866,8 @@ row_merge_read( #ifdef UNIV_DEBUG if (row_merge_print_block_read) { - fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n", - fd, (ulong) offset); - } -#endif /* UNIV_DEBUG */ - -#ifdef UNIV_DEBUG - if (row_merge_print_block_read) { - fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n", - fd, (ulong) offset); + fprintf(stderr, "row_merge_read fd=%d ofs=" ULINTPF "\n", + fd, offset); } #endif /* UNIV_DEBUG */ @@ -916,8 +910,8 @@ row_merge_write( #ifdef UNIV_DEBUG if (row_merge_print_block_write) { - fprintf(stderr, "row_merge_write fd=%d ofs=%lu\n", - fd, (ulong) offset); + fprintf(stderr, "row_merge_write fd=%d ofs=" ULINTPF "\n", + fd, offset); } #endif /* UNIV_DEBUG */ @@ -965,9 +959,10 @@ row_merge_read_rec( *mrec = NULL; #ifdef UNIV_DEBUG if (row_merge_print_read) { - fprintf(stderr, "row_merge_read %p,%p,%d,%lu EOF\n", + fprintf(stderr, "row_merge_read %p,%p,%d," ULINTPF + " EOF\n", (const void*) b, (const void*) block, - fd, (ulong) *foffs); + fd, *foffs); } #endif /* UNIV_DEBUG */ return(NULL); @@ -1082,9 +1077,9 @@ err_exit: func_exit: #ifdef UNIV_DEBUG if (row_merge_print_read) { - fprintf(stderr, "row_merge_read %p,%p,%d,%lu ", + fprintf(stderr, "row_merge_read %p,%p,%d," ULINTPF " ", (const void*) b, (const void*) block, - fd, (ulong) *foffs); + fd, *foffs); rec_print_comp(stderr, *mrec, offsets); putc('\n', stderr); } @@ -1118,8 +1113,8 @@ row_merge_write_rec_low( ut_ad(e == rec_offs_extra_size(offsets) + 1); if (row_merge_print_write) { - fprintf(stderr, "row_merge_write %p,%d,%lu ", - (void*) b, fd, (ulong) foffs); + fprintf(stderr, "row_merge_write %p,%d," ULINTPF " ", + (void*) b, fd, foffs); rec_print_comp(stderr, mrec, offsets); putc('\n', stderr); } @@ -1221,8 +1216,8 @@ row_merge_write_eof( ut_ad(foffs); #ifdef UNIV_DEBUG if (row_merge_print_write) { - fprintf(stderr, "row_merge_write %p,%p,%d,%lu EOF\n", - (void*) b, (void*) block, fd, (ulong) *foffs); + fprintf(stderr, "row_merge_write %p,%p,%d," ULINTPF " EOF\n", + (void*) b, (void*) block, fd, *foffs); } #endif /* UNIV_DEBUG */ @@ -2067,11 +2062,12 @@ row_merge_blocks( #ifdef UNIV_DEBUG if (row_merge_print_block) { fprintf(stderr, - "row_merge_blocks fd=%d ofs=%lu + fd=%d ofs=%lu" - " = fd=%d ofs=%lu\n", - file->fd, (ulong) *foffs0, - file->fd, (ulong) *foffs1, - of->fd, (ulong) of->offset); + "row_merge_blocks fd=%d ofs=" ULINTPF + " + fd=%d ofs=" ULINTPF + " = fd=%d ofs=" ULINTPF "\n", + file->fd, *foffs0, + file->fd, *foffs1, + of->fd, of->offset); } #endif /* UNIV_DEBUG */ @@ -2170,10 +2166,10 @@ row_merge_blocks_copy( #ifdef UNIV_DEBUG if (row_merge_print_block) { fprintf(stderr, - "row_merge_blocks_copy fd=%d ofs=%lu" - " = fd=%d ofs=%lu\n", - file->fd, (ulong) foffs0, - of->fd, (ulong) of->offset); + "row_merge_blocks_copy fd=%d ofs=" ULINTPF + " = fd=%d ofs=" ULINTPF "\n", + file->fd, *foffs0, + of->fd, of->offset); } #endif /* UNIV_DEBUG */ From e48ae21b0ea99a3d3cc16eebd414cc484fa4f38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 21 Apr 2017 16:22:46 +0300 Subject: [PATCH 069/148] Follow-up to MDEV-12534: Fix warnings on 32-bit systems --- storage/innobase/os/os0file.cc | 4 ++-- storage/innobase/srv/srv0srv.cc | 4 ++-- storage/xtradb/os/os0file.cc | 4 ++-- storage/xtradb/srv/srv0srv.cc | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index ff67c90eecf..d8cb44217bb 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -5647,8 +5647,8 @@ os_aio_print( os_n_file_writes, os_n_fsyncs); - const ulint n_reads = MONITOR_VALUE(MONITOR_OS_PENDING_READS); - const ulint n_writes = MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); + const ulint n_reads = ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS)); + const ulint n_writes = ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES)); if (n_reads != 0 || n_writes != 0) { fprintf(file, diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 58e69c3c9e7..067e32a83aa 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1409,10 +1409,10 @@ srv_export_innodb_status(void) mutex_enter(&srv_innodb_monitor_mutex); export_vars.innodb_data_pending_reads = - MONITOR_VALUE(MONITOR_OS_PENDING_READS); + ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS)); export_vars.innodb_data_pending_writes = - MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); + ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES)); export_vars.innodb_data_pending_fsyncs = fil_n_pending_log_flushes diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 48ae49f28e4..9632bb77df9 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -5820,8 +5820,8 @@ os_aio_print( os_n_file_writes, os_n_fsyncs); - const ulint n_reads = MONITOR_VALUE(MONITOR_OS_PENDING_READS); - const ulint n_writes = MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); + const ulint n_reads = ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS)); + const ulint n_writes = ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES)); if (n_reads != 0 || n_writes != 0) { fprintf(file, diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index c47119e63cf..5b3f86d8641 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -1735,10 +1735,10 @@ srv_export_innodb_status(void) mutex_enter(&srv_innodb_monitor_mutex); export_vars.innodb_data_pending_reads = - MONITOR_VALUE(MONITOR_OS_PENDING_READS); + ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS)); export_vars.innodb_data_pending_writes = - MONITOR_VALUE(MONITOR_OS_PENDING_WRITES); + ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES)); export_vars.innodb_data_pending_fsyncs = fil_n_pending_log_flushes From e056d1f1ca91ebe40467ed46be00be0add9cf247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 21 Apr 2017 17:39:12 +0300 Subject: [PATCH 070/148] Fix some InnoDB type mismatch On 64-bit Windows, sizeof(ulint)!=sizeof(ulong). --- storage/innobase/buf/buf0buf.cc | 25 ++++++++++++------------- storage/innobase/row/row0ftsort.cc | 7 +++---- storage/xtradb/buf/buf0buf.cc | 25 ++++++++++++------------- storage/xtradb/row/row0ftsort.cc | 7 +++---- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 73d061c4b20..0b305507271 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -5311,23 +5311,22 @@ buf_print_io_instance( pool_info->pages_written_rate); if (pool_info->n_page_get_delta) { - double hit_rate = ((1000 * pool_info->page_read_delta) - / pool_info->n_page_get_delta); + double hit_rate = double(pool_info->page_read_delta) + / pool_info->n_page_get_delta; - if (hit_rate > 1000) { - hit_rate = 1000; + if (hit_rate > 1) { + hit_rate = 1; } - hit_rate = 1000 - hit_rate; - fprintf(file, - "Buffer pool hit rate %lu / 1000," - " young-making rate %lu / 1000 not %lu / 1000\n", - (ulint) hit_rate, - (ulint) (1000 * pool_info->young_making_delta - / pool_info->n_page_get_delta), - (ulint) (1000 * pool_info->not_young_making_delta - / pool_info->n_page_get_delta)); + "Buffer pool hit rate " ULINTPF " / 1000," + " young-making rate " ULINTPF " / 1000 not " + ULINTPF " / 1000\n", + ulint(1000 * (1 - hit_rate)), + ulint(1000 * double(pool_info->young_making_delta) + / pool_info->n_page_get_delta), + ulint(1000 * double(pool_info->not_young_making_delta) + / pool_info->n_page_get_delta)); } else { fputs("No buffer pool page gets since the last printout\n", file); diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 4865c8e850a..5b8ed009a2a 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1248,10 +1248,9 @@ row_fts_build_sel_tree_level( int child_left; int child_right; ulint i; - ulint num_item; + ulint num_item = ulint(1) << level; - start = static_cast((1 << level) - 1); - num_item = static_cast(1 << level); + start = num_item - 1; for (i = 0; i < num_item; i++) { child_left = sel_tree[(start + i) * 2 + 1]; @@ -1320,7 +1319,7 @@ row_fts_build_sel_tree( treelevel++; } - start = (1 << treelevel) - 1; + start = (ulint(1) << treelevel) - 1; for (i = 0; i < (int) fts_sort_pll_degree; i++) { sel_tree[i + start] = i; diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index a5d8b661c35..07b84c60c76 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -5593,23 +5593,22 @@ buf_print_io_instance( pool_info->pages_written_rate); if (pool_info->n_page_get_delta) { - double hit_rate = ((1000 * pool_info->page_read_delta) - / pool_info->n_page_get_delta); + double hit_rate = double(pool_info->page_read_delta) + / pool_info->n_page_get_delta; - if (hit_rate > 1000) { - hit_rate = 1000; + if (hit_rate > 1) { + hit_rate = 1; } - hit_rate = 1000 - hit_rate; - fprintf(file, - "Buffer pool hit rate %lu / 1000," - " young-making rate %lu / 1000 not %lu / 1000\n", - (ulint) hit_rate, - (ulint) (1000 * pool_info->young_making_delta - / pool_info->n_page_get_delta), - (ulint) (1000 * pool_info->not_young_making_delta - / pool_info->n_page_get_delta)); + "Buffer pool hit rate " ULINTPF " / 1000," + " young-making rate " ULINTPF " / 1000 not " + ULINTPF " / 1000\n", + ulint(1000 * (1 - hit_rate)), + ulint(1000 * double(pool_info->young_making_delta) + / pool_info->n_page_get_delta), + ulint(1000 * double(pool_info->not_young_making_delta) + / pool_info->n_page_get_delta)); } else { fputs("No buffer pool page gets since the last printout\n", file); diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc index 134127c6adf..13877b8fe08 100644 --- a/storage/xtradb/row/row0ftsort.cc +++ b/storage/xtradb/row/row0ftsort.cc @@ -1251,10 +1251,9 @@ row_fts_build_sel_tree_level( int child_left; int child_right; ulint i; - ulint num_item; + ulint num_item = ulint(1) << level; - start = static_cast((1 << level) - 1); - num_item = static_cast(1 << level); + start = num_item - 1; for (i = 0; i < num_item; i++) { child_left = sel_tree[(start + i) * 2 + 1]; @@ -1323,7 +1322,7 @@ row_fts_build_sel_tree( treelevel++; } - start = (1 << treelevel) - 1; + start = (ulint(1) << treelevel) - 1; for (i = 0; i < (int) fts_sort_pll_degree; i++) { sel_tree[i + start] = i; From 26ed68dcaed5f5ca27fce21e7a7512e0523b2605 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 18 Apr 2017 16:28:14 +0200 Subject: [PATCH 071/148] fix "cmake -DWITH_PCRE=bundled" after building with system --- cmake/pcre.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/pcre.cmake b/cmake/pcre.cmake index 45d9bc01ddb..894bde38974 100644 --- a/cmake/pcre.cmake +++ b/cmake/pcre.cmake @@ -5,7 +5,7 @@ MACRO (CHECK_PCRE) IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto") CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE) ENDIF() - IF(NOT HAVE_PCRE) + IF(NOT HAVE_PCRE OR WITH_PCRE STREQUAL "bundled") IF (WITH_PCRE STREQUAL "system") MESSAGE(FATAL_ERROR "system pcre is not found or unusable") ENDIF() From 97fb1f26797828427ad850b0420aaafc74205e71 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 21 Apr 2017 14:34:24 -0700 Subject: [PATCH 072/148] Fixed bug mdev-10053. The implementation of the walk method for the class Item_in_subselect was missing. As a result the method never traversed the left operand of any IN subquery predicate. Item_exists_subselect::exists2in_processor() that performs the Exist-To-In transformation calls the walk method to collect info on outer references. As the walk method did not traverse the left operands of the IN subqueries the outer references there were not taken into account and some subqueries that were actually correlated were marked as uncorrelated. It could lead to an attempt of the materialization of such a subquery. Also added a cleanup for some test cases merged from 5.5. --- mysql-test/r/subselect_exists2in.result | 50 +++++++++++++++++++++++++ mysql-test/r/subselect_mat.result | 8 ++-- mysql-test/r/subselect_sj_mat.result | 8 ++-- mysql-test/t/subselect_exists2in.test | 28 ++++++++++++++ mysql-test/t/subselect_sj_mat.test | 12 ++++-- sql/item_subselect.h | 7 ++++ 6 files changed, 101 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/subselect_exists2in.result b/mysql-test/r/subselect_exists2in.result index 1d0732060b7..5deb2dfa9c5 100644 --- a/mysql-test/r/subselect_exists2in.result +++ b/mysql-test/r/subselect_exists2in.result @@ -884,5 +884,55 @@ a deallocate prepare stmt; drop view v1; drop table t1,t2; +# +#MDEV-10053: EXIST to IN transformation turned down +# +CREATE TABLE t1 ( +pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) +ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); +set @optimizer_switch_save=@@optimizer_switch; +set optimizer_switch='exists_to_in=off'; +explain extended SELECT STRAIGHT_JOIN sq1.f2 +FROM ( SELECT * FROM t1 ) AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where +3 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 100.00 +3 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) +4 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1276 Field or reference 'sq1.pk' of SELECT #3 was resolved in SELECT #1 +Note 1276 Field or reference 'sq1.f1' of SELECT #3 was resolved in SELECT #1 +Note 1003 select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <`test`.`t1`.`f1`,`test`.`t1`.`pk`>(exists(select 1 from `test`.`t1` `sq2` semi join (`test`.`t1`) where ((`test`.`sq2`.`f1` = `test`.`t1`.`f1`) and (`test`.`t1`.`pk` = `test`.`t1`.`f1`)))) +SELECT STRAIGHT_JOIN sq1.f2 +FROM ( SELECT * FROM t1 ) AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +f2 +foo +set optimizer_switch='exists_to_in=on'; +explain extended SELECT STRAIGHT_JOIN sq1.f2 +FROM ( SELECT * FROM t1 ) AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where +3 DEPENDENT SUBQUERY eq_ref distinct_key distinct_key 4 func 1 100.00 +3 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) +4 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1276 Field or reference 'sq1.pk' of SELECT #3 was resolved in SELECT #1 +Note 1276 Field or reference 'sq1.f1' of SELECT #3 was resolved in SELECT #1 +Note 1003 select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <`test`.`t1`.`f1`,`test`.`t1`.`pk`>((`test`.`t1`.`f1`,(select `test`.`sq2`.`f1` from `test`.`t1` `sq2` semi join (`test`.`t1`) where ((`test`.`t1`.`pk` = `test`.`t1`.`f1`) and ((`test`.`t1`.`f1`) = `test`.`sq2`.`f1`))))) +SELECT STRAIGHT_JOIN sq1.f2 +FROM ( SELECT * FROM t1 ) AS sq1 +WHERE EXISTS ( SELECT * FROM t1 AS sq2 +WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +f2 +foo +set optimizer_switch= @optimizer_switch_save; +DROP TABLE t1; # End of 10.0 tests set optimizer_switch=default; diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index f7fddf675ea..09223d36429 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -2166,7 +2166,6 @@ drop table t1; # # MDEV-12429: IN subquery used in WHERE of EXISTS subquery # -set optimizer_switch='exists_to_in=off'; CREATE TABLE t1 ( pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); @@ -2175,6 +2174,8 @@ WHERE EXISTS ( SELECT * FROM t1 AS sq2 WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); f2 foo +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch='exists_to_in=off'; EXPLAIN SELECT sq1.f2 FROM t1 AS sq1 WHERE EXISTS ( SELECT * FROM t1 AS sq2 @@ -2185,7 +2186,6 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) 3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 # this checks the result set above -set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch= 'materialization=off,semijoin=off'; SELECT sq1.f2 FROM t1 AS sq1 WHERE EXISTS ( SELECT * FROM t1 AS sq2 @@ -2197,13 +2197,14 @@ DROP TABLE t1; # # MDEV-12145: IN subquery used in WHERE of EXISTS subquery # -set optimizer_switch='exists_to_in=off'; CREATE TABLE t1 (f1 INT) ENGINE=MyISAM; INSERT INTO t1 VALUES (4),(6); CREATE TABLE t2 (i2 INT, KEY(i2)) ENGINE=MyISAM; INSERT INTO t2 VALUES (8),(7),(1); CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM; INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5); +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch='exists_to_in=off'; SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t2, t3 WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); @@ -2223,7 +2224,6 @@ Warnings: Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`f1` = `test`.`t3`.`f3`)))) # this checks the result set above -set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch= 'materialization=off,semijoin=off'; SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t2, t3 diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index 02c89b7d884..3f91b510c5b 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -2206,7 +2206,6 @@ drop table t1; # # MDEV-12429: IN subquery used in WHERE of EXISTS subquery # -set optimizer_switch='exists_to_in=off'; CREATE TABLE t1 ( pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); @@ -2215,6 +2214,8 @@ WHERE EXISTS ( SELECT * FROM t1 AS sq2 WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); f2 foo +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch='exists_to_in=off'; EXPLAIN SELECT sq1.f2 FROM t1 AS sq1 WHERE EXISTS ( SELECT * FROM t1 AS sq2 @@ -2225,7 +2226,6 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) 3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 # this checks the result set above -set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch= 'materialization=off,semijoin=off'; SELECT sq1.f2 FROM t1 AS sq1 WHERE EXISTS ( SELECT * FROM t1 AS sq2 @@ -2237,13 +2237,14 @@ DROP TABLE t1; # # MDEV-12145: IN subquery used in WHERE of EXISTS subquery # -set optimizer_switch='exists_to_in=off'; CREATE TABLE t1 (f1 INT) ENGINE=MyISAM; INSERT INTO t1 VALUES (4),(6); CREATE TABLE t2 (i2 INT, KEY(i2)) ENGINE=MyISAM; INSERT INTO t2 VALUES (8),(7),(1); CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM; INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5); +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch='exists_to_in=off'; SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t2, t3 WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); @@ -2263,7 +2264,6 @@ Warnings: Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`f1` = `test`.`t3`.`f3`)))) # this checks the result set above -set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch= 'materialization=off,semijoin=off'; SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t2, t3 diff --git a/mysql-test/t/subselect_exists2in.test b/mysql-test/t/subselect_exists2in.test index 9450ef71494..a4fdbe5c50b 100644 --- a/mysql-test/t/subselect_exists2in.test +++ b/mysql-test/t/subselect_exists2in.test @@ -758,6 +758,34 @@ deallocate prepare stmt; drop view v1; drop table t1,t2; +--echo # +--echo #MDEV-10053: EXIST to IN transformation turned down +--echo # + +CREATE TABLE t1 ( + pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) +ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); + +let $q= +SELECT STRAIGHT_JOIN sq1.f2 + FROM ( SELECT * FROM t1 ) AS sq1 + WHERE EXISTS ( SELECT * FROM t1 AS sq2 + WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); + +set @optimizer_switch_save=@@optimizer_switch; + +set optimizer_switch='exists_to_in=off'; +eval explain extended $q; +eval $q; +set optimizer_switch='exists_to_in=on'; +eval explain extended $q; +eval $q; + +set optimizer_switch= @optimizer_switch_save; + +DROP TABLE t1; + --echo # End of 10.0 tests #restore defaults diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test index 5276502190e..7b6c5818a04 100644 --- a/mysql-test/t/subselect_sj_mat.test +++ b/mysql-test/t/subselect_sj_mat.test @@ -1861,7 +1861,6 @@ drop table t1; --echo # MDEV-12429: IN subquery used in WHERE of EXISTS subquery --echo # -set optimizer_switch='exists_to_in=off'; CREATE TABLE t1 ( pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7); @@ -1870,17 +1869,20 @@ SELECT sq1.f2 FROM t1 AS sq1 WHERE EXISTS ( SELECT * FROM t1 AS sq2 WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); +set @save_optimizer_switch= @@optimizer_switch; + +set optimizer_switch='exists_to_in=off'; EXPLAIN SELECT sq1.f2 FROM t1 AS sq1 WHERE EXISTS ( SELECT * FROM t1 AS sq2 WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); --echo # this checks the result set above -set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch= 'materialization=off,semijoin=off'; SELECT sq1.f2 FROM t1 AS sq1 WHERE EXISTS ( SELECT * FROM t1 AS sq2 WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 ); + set optimizer_switch= @save_optimizer_switch; DROP TABLE t1; @@ -1889,7 +1891,6 @@ DROP TABLE t1; --echo # MDEV-12145: IN subquery used in WHERE of EXISTS subquery --echo # -set optimizer_switch='exists_to_in=off'; CREATE TABLE t1 (f1 INT) ENGINE=MyISAM; INSERT INTO t1 VALUES (4),(6); @@ -1899,6 +1900,9 @@ INSERT INTO t2 VALUES (8),(7),(1); CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM; INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5); +set @save_optimizer_switch= @@optimizer_switch; + +set optimizer_switch='exists_to_in=off'; SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t2, t3 WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); @@ -1908,11 +1912,11 @@ SELECT * FROM t1 WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); --echo # this checks the result set above -set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch= 'materialization=off,semijoin=off'; SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t2, t3 WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) ); + set optimizer_switch= @save_optimizer_switch; DROP TABLE t1,t2,t3; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index f457eb92e3e..492a3d7dda5 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -705,6 +705,13 @@ public: in_strategy= (SUBS_STRATEGY_CHOSEN | strategy); DBUG_VOID_RETURN; } + + bool walk(Item_processor processor, bool walk_subquery, uchar *arg) + { + return left_expr->walk(processor, walk_subquery, arg) || + Item_subselect::walk(processor, walk_subquery, arg); + } + bool exists2in_processor(uchar *opt_arg __attribute__((unused))) { return 0; From a091314d2775e0d33f2476953a7c5ab9647b2f37 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 22 Apr 2017 14:14:11 +0200 Subject: [PATCH 073/148] Fix MDEV-12520: Decimal values can be truncated for JDBC tables modified: storage/connect/jdbconn.cpp Fix bug. Date value was null when retrieved from a json expanded array. modified: storage/connect/tabjson.cpp --- storage/connect/jdbconn.cpp | 5 +++-- storage/connect/tabjson.cpp | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 02adff5d2c8..e8a260c8be9 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -1235,7 +1235,8 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) case 12: // VARCHAR case -1: // LONGVARCHAR case 1: // CHAR - if (jb) + case 3: // DECIMAL + if (jb && ctyp != 3) cn = (jstring)jb; else if (!gmID(g, chrfldid, "StringField", "(ILjava/lang/String;)Ljava/lang/String;")) cn = (jstring)env->CallObjectMethod(job, chrfldid, (jint)rank, jn); @@ -1261,7 +1262,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) break; case 8: // DOUBLE case 2: // NUMERIC - case 3: // DECIMAL +//case 3: // DECIMAL if (!gmID(g, dblfldid, "DoubleField", "(ILjava/lang/String;)D")) val->SetValue((double)env->CallDoubleMethod(job, dblfldid, rank, jn)); else diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 4b2ab4fd240..f451c73b665 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1171,6 +1171,7 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) case TYPE_INTG: case TYPE_BINT: case TYPE_DBL: + case TYPE_DATE: vp->SetValue_pval(val->GetValue()); break; case TYPE_BOOL: From fac2a7a85dab10ef6cc7628f635fe5a3736514a6 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 22 Apr 2017 22:51:43 +0400 Subject: [PATCH 074/148] MDEV-12495 Conditional jump depends on uninitialised value for: SELECT NULL UNION geom_expression --- mysql-test/r/gis.result | 13 +++++++++++++ mysql-test/t/gis.test | 13 +++++++++++++ sql/item.cc | 5 ++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 174088bf944..2bd492008bc 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1630,3 +1630,16 @@ SELECT ASTEXT(p) FROM v1; ASTEXT(p) POINT(1 1) DROP VIEW v1; +# +# Start of 10.0 tests +# +# +# MDEV-12495 Conditional jump depends on uninitialised value for: SELECT NULL UNION geom_expression +# +SELECT AsText(g) FROM (SELECT NULL AS g UNION SELECT Point(1,1)) AS t1; +AsText(g) +NULL +POINT(1 1) +# +# End 10.0 tests +# diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 9378ea55377..f689902533a 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -1492,3 +1492,16 @@ SELECT ASTEXT(p) FROM v1; DROP VIEW v1; # --echo End of 5.5 tests + +--echo # +--echo # Start of 10.0 tests +--echo # + +--echo # +--echo # MDEV-12495 Conditional jump depends on uninitialised value for: SELECT NULL UNION geom_expression +--echo # +SELECT AsText(g) FROM (SELECT NULL AS g UNION SELECT Point(1,1)) AS t1; + +--echo # +--echo # End 10.0 tests +--echo # diff --git a/sql/item.cc b/sql/item.cc index dbec742e4a2..ceb8d984d9e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9464,7 +9464,10 @@ void Item_cache_row::set_null() Item_type_holder::Item_type_holder(THD *thd, Item *item) - :Item(thd, item), enum_set_typelib(0), fld_type(get_real_type(item)) + :Item(thd, item), + enum_set_typelib(0), + fld_type(get_real_type(item)), + geometry_type(Field::GEOM_GEOMETRY) { DBUG_ASSERT(item->fixed); maybe_null= item->maybe_null; From 864548c4ecf904aeccce32cf6f569520a923e95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 24 Apr 2017 13:40:36 +0300 Subject: [PATCH 075/148] Add and adjust a test from MySQL: commit 12343617922cfd9c48ee84ad6ecf53068d822010 Author: Thirunarayanan Balathandayuthapani Date: Fri Jul 15 14:39:37 2016 +0530 Bug #23475211 COMBINING ALTER OPERATIONS TRIGGERS TABLE REBUILD The code fix is already present. --- .../r/innodb-index-online-norebuild.result | 26 +++++++ .../t/innodb-index-online-norebuild.opt | 1 + .../t/innodb-index-online-norebuild.test | 71 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 mysql-test/suite/innodb/r/innodb-index-online-norebuild.result create mode 100644 mysql-test/suite/innodb/t/innodb-index-online-norebuild.opt create mode 100644 mysql-test/suite/innodb/t/innodb-index-online-norebuild.test diff --git a/mysql-test/suite/innodb/r/innodb-index-online-norebuild.result b/mysql-test/suite/innodb/r/innodb-index-online-norebuild.result new file mode 100644 index 00000000000..b9077643870 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-index-online-norebuild.result @@ -0,0 +1,26 @@ +# INPLACE ALTER WITH INPLACE_IGNORE FLAG AND CHANGE CREATE OPTION +# CHANGE THE COLUMN DEFAULT (INPLACE_IGNORE) +# AND TABLE CHARSET(CHANGE CREATE) +CREATE TABLE t1( +id INT PRIMARY KEY, +f1 INT NOT NULL DEFAULT 0)ENGINE=INNODB; +INSERT INTO t1 VALUES(1, 2); +SET SQL_MODE='STRICT_ALL_TABLES'; +ALTER TABLE t1 MODIFY COLUMN f1 INT NOT NULL DEFAULT 0, +DEFAULT CHARSET=latin1, ALGORITHM=INPLACE; +DROP TABLE t1; +# CHANGE THE COMMENT OF COLUMN(INPLACE IGNORE) +# AND TABLE CHARSET(CHANGE CREATE) +CREATE TABLE t1(id INT COMMENT 'independence day')ENGINE=INNODB; +INSERT INTO t1 values(1); +ALTER TABLE t1 MODIFY COLUMN id INT COMMENT 'identifier', +DEFAULT CHARSET=latin1, ALGORITHM=INPLACE; +DROP TABLE t1; +# RENAME THE TABLE(INPLACE IGNORE) +# AND CHANGE TABLE CHARSET(CHANGE CREATE) +CREATE TABLE t1( +f1 INT NOT NULL, +f2 INT NOT NULL)ENGINE=INNODB; +INSERT INTO t1 VALUES(1, 2); +ALTER TABLE t1 RENAME t2, DEFAULT CHARSET=latin1, ALGORITHM=INPLACE; +DROP TABLE t2; diff --git a/mysql-test/suite/innodb/t/innodb-index-online-norebuild.opt b/mysql-test/suite/innodb/t/innodb-index-online-norebuild.opt new file mode 100644 index 00000000000..39b93371503 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-index-online-norebuild.opt @@ -0,0 +1 @@ +--loose-innodb-sys-tables diff --git a/mysql-test/suite/innodb/t/innodb-index-online-norebuild.test b/mysql-test/suite/innodb/t/innodb-index-online-norebuild.test new file mode 100644 index 00000000000..518b4efe1df --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-index-online-norebuild.test @@ -0,0 +1,71 @@ +--source include/have_innodb.inc + +--echo # INPLACE ALTER WITH INPLACE_IGNORE FLAG AND CHANGE CREATE OPTION + +--echo # CHANGE THE COLUMN DEFAULT (INPLACE_IGNORE) +--echo # AND TABLE CHARSET(CHANGE CREATE) + +CREATE TABLE t1( + id INT PRIMARY KEY, + f1 INT NOT NULL DEFAULT 0)ENGINE=INNODB; + +INSERT INTO t1 VALUES(1, 2); + +let id_before_alter =`SELECT table_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name="test/t1"`; + +# Allow the following operation to report errors. +SET SQL_MODE='STRICT_ALL_TABLES'; +ALTER TABLE t1 MODIFY COLUMN f1 INT NOT NULL DEFAULT 0, + DEFAULT CHARSET=latin1, ALGORITHM=INPLACE; + +let id_after_alter =`SELECT table_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name="test/t1"`; + +if ($id_before_alter != $id_after_alter) +{ + --echo "Table rebuild happened"; +} + +DROP TABLE t1; + +--echo # CHANGE THE COMMENT OF COLUMN(INPLACE IGNORE) +--echo # AND TABLE CHARSET(CHANGE CREATE) + +CREATE TABLE t1(id INT COMMENT 'independence day')ENGINE=INNODB; + +INSERT INTO t1 values(1); + +let id_before_alter =`SELECT table_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name="test/t1"`; + +ALTER TABLE t1 MODIFY COLUMN id INT COMMENT 'identifier', + DEFAULT CHARSET=latin1, ALGORITHM=INPLACE; + +let id_after_alter =`SELECT table_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name="test/t1"`; + +if ($id_before_alter != $id_after_alter) +{ + --echo "Table rebuild happened"; +} + +DROP TABLE t1; + +--echo # RENAME THE TABLE(INPLACE IGNORE) +--echo # AND CHANGE TABLE CHARSET(CHANGE CREATE) + +CREATE TABLE t1( + f1 INT NOT NULL, + f2 INT NOT NULL)ENGINE=INNODB; + +INSERT INTO t1 VALUES(1, 2); + +let id_before_alter =`SELECT table_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name="test/t1"`; + +ALTER TABLE t1 RENAME t2, DEFAULT CHARSET=latin1, ALGORITHM=INPLACE; + +let id_after_alter =`SELECT table_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name="test/t2"`; + +if ($id_before_alter != $id_after_alter) +{ + --echo "Table rebuild happened"; +} + +DROP TABLE t2; From 57fea99eeb80829828d43a048d31c46c30684738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 24 Apr 2017 16:42:35 +0300 Subject: [PATCH 076/148] Add and adjust a test from MySQL: commit 1198267c331b045b9cad26be72b1a5b4f8930a79 Author: Thirunarayanan Balathandayuthapani Date: Fri Aug 26 11:00:44 2016 +0530 Bug #20989615 INNODB AUTO_INCREMENT PRODUCES SAME VALUE TWICE The code fix is already present. --- .../suite/innodb/r/autoinc_debug.result | 90 +++++++++++++++++++ mysql-test/suite/innodb/t/autoinc_debug.test | 85 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 mysql-test/suite/innodb/r/autoinc_debug.result create mode 100644 mysql-test/suite/innodb/t/autoinc_debug.test diff --git a/mysql-test/suite/innodb/r/autoinc_debug.result b/mysql-test/suite/innodb/r/autoinc_debug.result new file mode 100644 index 00000000000..b4b5e23e057 --- /dev/null +++ b/mysql-test/suite/innodb/r/autoinc_debug.result @@ -0,0 +1,90 @@ +CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY)ENGINE=INNODB; +# SETTING auto_increment_increment IN CONNECTION DEFAULT +SET AUTO_INCREMENT_INCREMENT = 1; +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; +id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 +# SETTING auto_increment_increment IN CONNECTION1 +SET AUTO_INCREMENT_INCREMENT = 2; +SET DEBUG_SYNC= 'ib_after_row_insert SIGNAL opened WAIT_FOR flushed1'; +INSERT INTO t1 VALUES(NULL); +SET AUTO_INCREMENT_INCREMENT = 2; +SET DEBUG_SYNC= 'now WAIT_FOR opened'; +SET DEBUG_SYNC= 'ib_after_row_insert_step SIGNAL flushed1 WAIT_FOR opened1'; +insert into t1 values(NULL); +SELECT * FROM t1; +id +1 +3 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 +SET DEBUG_SYNC= 'now SIGNAL opened1'; +SELECT * FROM t1; +id +1 +3 +5 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY)ENGINE=INNODB; +# SETTING auto_increment_increment IN CONNECTION DEFAULT +SET AUTO_INCREMENT_INCREMENT = 1; +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; +id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 +SET DEBUG_SYNC = 'now SIGNAL flushed'; +# SETTING auto_increment_increment in connection1 +SET AUTO_INCREMENT_INCREMENT = 2; +SET DEBUG_SYNC= 'now WAIT_FOR flushed'; +SET DEBUG_SYNC= 'ib_after_row_insert SIGNAL opened WAIT_FOR flushed1'; +INSERT INTO t1 values(NULL); +SET DEBUG_SYNC= 'now WAIT_FOR opened'; +SET DEBUG_SYNC= 'ib_after_row_insert_step SIGNAL flushed1 WAIT_FOR opened1'; +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; +id +1 +3 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 +SET DEBUG_SYNC= 'now SIGNAL opened1'; +SELECT * FROM t1; +id +1 +3 +5 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET DEBUG_SYNC='RESET'; diff --git a/mysql-test/suite/innodb/t/autoinc_debug.test b/mysql-test/suite/innodb/t/autoinc_debug.test new file mode 100644 index 00000000000..2e662565490 --- /dev/null +++ b/mysql-test/suite/innodb/t/autoinc_debug.test @@ -0,0 +1,85 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/not_embedded.inc + +# Two parallel connection with autoinc column after restart. + +CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY)ENGINE=INNODB; + +--echo # SETTING auto_increment_increment IN CONNECTION DEFAULT +SET AUTO_INCREMENT_INCREMENT = 1; +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; +SHOW CREATE TABLE t1; + +--source include/restart_mysqld.inc + +--echo # SETTING auto_increment_increment IN CONNECTION1 +SET AUTO_INCREMENT_INCREMENT = 2; + +SET DEBUG_SYNC= 'ib_after_row_insert SIGNAL opened WAIT_FOR flushed1'; + +SEND INSERT INTO t1 VALUES(NULL); + +connect(con1, localhost, root,,); +SET AUTO_INCREMENT_INCREMENT = 2; +SET DEBUG_SYNC= 'now WAIT_FOR opened'; +SET DEBUG_SYNC= 'ib_after_row_insert_step SIGNAL flushed1 WAIT_FOR opened1'; +send insert into t1 values(NULL); + +connection default; +reap; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +SET DEBUG_SYNC= 'now SIGNAL opened1'; + +connection con1; +reap; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +connection default; +disconnect con1; + +DROP TABLE t1; + +# Two parallel connection with autoinc column without restart. + +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY)ENGINE=INNODB; + +--echo # SETTING auto_increment_increment IN CONNECTION DEFAULT +SET AUTO_INCREMENT_INCREMENT = 1; +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +SET DEBUG_SYNC = 'now SIGNAL flushed'; + +connect(con1, localhost, root,,); + +--echo # SETTING auto_increment_increment in connection1 +SET AUTO_INCREMENT_INCREMENT = 2; + +SET DEBUG_SYNC= 'now WAIT_FOR flushed'; +SET DEBUG_SYNC= 'ib_after_row_insert SIGNAL opened WAIT_FOR flushed1'; + +send INSERT INTO t1 values(NULL); + +connection default; + +SET DEBUG_SYNC= 'now WAIT_FOR opened'; +SET DEBUG_SYNC= 'ib_after_row_insert_step SIGNAL flushed1 WAIT_FOR opened1'; + +send INSERT INTO t1 VALUES(NULL); + +connection con1; +reap; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +SET DEBUG_SYNC= 'now SIGNAL opened1'; +disconnect con1; + +connection default; +reap; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET DEBUG_SYNC='RESET'; From 2e7ba70a94b5950a7d1d733c177d1b2a24916213 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 22 Apr 2017 10:30:55 -0700 Subject: [PATCH 077/148] Fixed the bug mdev-10693. The code that chooses between materialization of a non-correlated IN subquery and its transformation into an EXISTS correlated subquery assumes that the execution plan for the outer select has been already built. However it was not always so if subqueries occurred in the expressions used for ref access to tables of the outer select. A call of the function create_ref_for_key() in get_best_combination() could trigger a premature execution of the above mentioned code when the execution plan structures for the outer select were not fully built. This could cause a crash of the server. The fix postpones the calls of create_ref_for_key() until the structures for the execution plan is fully built. --- mysql-test/r/subselect_innodb.result | 14 ++++++++++++++ mysql-test/t/subselect_innodb.test | 22 ++++++++++++++++++++++ sql/sql_select.cc | 21 +++++++++++++++------ 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index 06cfb8b45d2..f92615f22cf 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -469,3 +469,17 @@ f1 f2 set join_cache_level = default; drop view v1; drop table t1,t2; +# +# MDEV-10693: cost-based choice between materialization and in-to-exists +# for a subquery from the expression used in ref access +# +CREATE TABLE t1 (i1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (i2 INT) ENGINE=InnoDB; +CREATE TABLE t3 (i3 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t3 VALUES (3); +SELECT * FROM t1 +WHERE NULL IN ( SELECT i2 FROM t2 +WHERE i1 IN ( i2 IN ( SELECT i3 FROM t3 ) ) AND i2 = 2 ); +i1 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index d764c435c82..3945c6b10b9 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -453,3 +453,25 @@ SELECT * FROM v1, t2 WHERE ( f1, f2 ) IN ( SELECT f1, f1 FROM t1 ); set join_cache_level = default; drop view v1; drop table t1,t2; + +--echo # +--echo # MDEV-10693: cost-based choice between materialization and in-to-exists +--echo # for a subquery from the expression used in ref access +--echo # + +--source include/have_innodb.inc + +CREATE TABLE t1 (i1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (i2 INT) ENGINE=InnoDB; + +CREATE TABLE t3 (i3 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t3 VALUES (3); + +SELECT * FROM t1 + WHERE NULL IN ( SELECT i2 FROM t2 + WHERE i1 IN ( i2 IN ( SELECT i3 FROM t3 ) ) AND i2 = 2 ); + +DROP TABLE t1,t2,t3; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d83e8e2bfce..c5f2a83fc01 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7728,8 +7728,6 @@ get_best_combination(JOIN *join) join->full_join=0; join->hash_join= FALSE; - used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read - fix_semijoin_strategies_for_picked_join_order(join); JOIN_TAB_RANGE *root_range; @@ -7791,7 +7789,6 @@ get_best_combination(JOIN *join) j->bush_root_tab= sjm_nest_root; form=join->table[tablenr]=j->table; - used_tables|= form->map; form->reginfo.join_tab=j; DBUG_PRINT("info",("type: %d", j->type)); if (j->type == JT_CONST) @@ -7818,9 +7815,6 @@ get_best_combination(JOIN *join) join->best_positions[tablenr].loosescan_picker.loosescan_key); j->index= join->best_positions[tablenr].loosescan_picker.loosescan_key; }*/ - - if (keyuse && create_ref_for_key(join, j, keyuse, TRUE, used_tables)) - DBUG_RETURN(TRUE); // Something went wrong if ((j->type == JT_REF || j->type == JT_EQ_REF) && is_hash_join_key_no(j->ref.key)) @@ -7845,6 +7839,21 @@ get_best_combination(JOIN *join) } root_range->end= j; + used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read + for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++) + { + if (j->bush_children) + j= j->bush_children->start; + + used_tables|= j->table->map; + if ((keyuse= join->best_positions[tablenr].key) && + create_ref_for_key(join, j, keyuse, TRUE, used_tables)) + DBUG_RETURN(TRUE); // Something went wrong + + if (j->last_leaf_in_bush) + j= j->bush_root_tab; + } + join->top_join_tab_count= join->join_tab_ranges.head()->end - join->join_tab_ranges.head()->start; /* From 63b7d9d1586336a61d6de7fbdcdfbc72e6117f93 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 29 Apr 2017 19:20:51 +0200 Subject: [PATCH 078/148] Fix MDEV-12631 valgrind warning for zipped tables modified: storage/connect/filamzip.cpp --- storage/connect/filamzip.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 1a27c974f30..66e628abb14 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -1,7 +1,7 @@ /*********** File AM Zip C++ Program Source Code File (.CPP) ***********/ /* PROGRAM NAME: FILAMZIP */ /* ------------- */ -/* Version 1.1 */ +/* Version 1.2 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -652,12 +652,18 @@ bool UNZIPUTL::openEntry(PGLOBAL g) } // endif rc size = finfo.uncompressed_size; - memory = new char[size + 1]; + + try { + memory = new char[size + 1]; + } catch (...) { + strcpy(g->Message, "Out of memory"); + return true; + } // end try/catch if ((rc = unzReadCurrentFile(zipfile, memory, size)) < 0) { sprintf(g->Message, "unzReadCurrentFile rc = %d", rc); unzCloseCurrentFile(zipfile); - free(memory); + delete[] memory; memory = NULL; entryopen = false; } else { @@ -682,7 +688,7 @@ void UNZIPUTL::closeEntry() } // endif entryopen if (memory) { - free(memory); + delete[] memory; memory = NULL; } // endif memory From dbe2c3c5f21fd479fbe0993b045c0c30493ca07a Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 30 Apr 2017 13:29:56 +1000 Subject: [PATCH 079/148] mysqld_safe_help - remove warning /home/travis/build/MariaDB/server/extra/mysqld_safe_helper.c:62:21: warning: too many arguments in call to 'do_usage' do_usage(argv[0]); ~~~~~~~~ ^ 1 warning generated. --- extra/mysqld_safe_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/mysqld_safe_helper.c b/extra/mysqld_safe_helper.c index 09e507c6e1c..2ccff20b910 100644 --- a/extra/mysqld_safe_helper.c +++ b/extra/mysqld_safe_helper.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) MY_INIT(argv[0]); if (argc < 3) - do_usage(argv[0]); + do_usage(); user_info= my_check_user(argv[1], MYF(0)); if (user_info ? my_set_user(argv[1], user_info, MYF(MY_WME)) From 14fca28ea44dabf62e75e2aa9a90d71bd7be45c0 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Tue, 2 May 2017 19:11:21 -0400 Subject: [PATCH 080/148] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ade2e129c54..68358acf754 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=56 +MYSQL_VERSION_PATCH=57 MYSQL_VERSION_EXTRA= From 1de6440a2e441e7aeffe85ee9c72e1e001fcf38d Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 3 May 2017 10:32:01 +0200 Subject: [PATCH 081/148] Fix MDEV-12587 MariaDB CONNECT DIR Type - Subfolder Option: SELECT Query Never Ends modified: storage/connect/tabmul.cpp modified: storage/connect/tabmul.h Work on MDEV-12667 Crash when using JSON tables modified: storage/connect/connect.cc modified: storage/connect/ha_connect.cc modified: storage/connect/ha_connect.h modified: storage/connect/plgdbutl.cpp Change Base offset for DIR tables on Linux modified: storage/connect/reldef.cpp --- storage/connect/connect.cc | 3 +- storage/connect/ha_connect.cc | 27 +++++++++------ storage/connect/ha_connect.h | 2 +- storage/connect/plgdbutl.cpp | 5 +-- storage/connect/reldef.cpp | 11 ++++-- storage/connect/tabjson.cpp | 6 ++-- storage/connect/tabmul.cpp | 65 ++++++++++++++++++++--------------- storage/connect/tabmul.h | 6 ++-- storage/connect/tabxml.cpp | 7 ++-- 9 files changed, 82 insertions(+), 50 deletions(-) diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 9ec93bfe1ba..5d5eca80275 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -117,7 +117,8 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname) handler); // Set the database path for this table - handler->SetDataPath(g, pathname); + if (handler->SetDataPath(g, pathname)) + return true; if (dbuserp->Catalog) { // ((MYCAT *)dbuserp->Catalog)->SetHandler(handler); done later diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 2cd581c5c64..9f0b62c73b3 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1739,9 +1739,9 @@ void ha_connect::AddColName(char *cp, Field *fp) /***********************************************************************/ /* This function sets the current database path. */ /***********************************************************************/ -void ha_connect::SetDataPath(PGLOBAL g, const char *path) +bool ha_connect::SetDataPath(PGLOBAL g, const char *path) { - datapath= SetPath(g, path); + return (!(datapath = SetPath(g, path))); } // end of SetDataPath /****************************************************************************/ @@ -2721,6 +2721,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (x) return NULL; + else + pb0 = pb1 = pb2 = ph0 = ph1 = ph2 = NULL; if (trace) htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(), @@ -4110,10 +4112,14 @@ int ha_connect::info(uint flag) } // endif xmod // This is necessary for getting file length - if (table) - SetDataPath(g, table->s->db.str); - else - DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen + if (table) { + if (SetDataPath(g, table->s->db.str)) { + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } // endif SetDataPath + + } else + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen if (!(tdbp= GetTDB(g))) DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen @@ -6563,9 +6569,10 @@ int ha_connect::create(const char *name, TABLE *table_arg, PDBUSER dup= PlgGetUser(g); PCATLG cat= (dup) ? dup->Catalog : NULL; - SetDataPath(g, table_arg->s->db.str); - - if (cat) { + if (SetDataPath(g, table_arg->s->db.str)) { + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + rc = HA_ERR_INTERNAL_ERROR; + } else if (cat) { // cat->SetDataPath(g, table_arg->s->db.str); #if defined(WITH_PARTITION_STORAGE_ENGINE) @@ -7137,6 +7144,6 @@ maria_declare_plugin(connect) NULL, /* status variables */ connect_system_variables, /* system variables */ "1.05.0003", /* string version */ - MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */ + MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 3d9ff967618..155bec3c966 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -199,7 +199,7 @@ public: bool IsUnique(uint n); char *GetDataPath(void) {return (char*)datapath;} - void SetDataPath(PGLOBAL g, const char *path); + bool SetDataPath(PGLOBAL g, const char *path); PTDB GetTDB(PGLOBAL g); int OpenTable(PGLOBAL g, bool del= false); bool CheckColumnList(PGLOBAL g); diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 299332f51b4..eef9fba44f5 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -412,8 +412,9 @@ char *SetPath(PGLOBAL g, const char *path) if (path) { size_t len= strlen(path) + (*path != '.' ? 4 : 1); - buf= (char*)PlugSubAlloc(g, NULL, len); - + if (!(buf = (char*)PlgDBSubAlloc(g, NULL, len))) + return NULL; + if (PlugIsAbsolutePath(path)) { strcpy(buf, path); return buf; diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 5bb7848ab1c..c0f3074769a 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -1,11 +1,11 @@ /************* RelDef CPP Program Source Code File (.CPP) **************/ /* PROGRAM NAME: RELDEF */ /* ------------- */ -/* Version 1.6 */ +/* Version 1.7 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2004-2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2004-2017 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -277,8 +277,13 @@ int TABDEF::GetColCatInfo(PGLOBAL g) // Take care of the column definitions i= poff= nof= nlg= 0; +#if defined(__WIN__) // Offsets of HTML and DIR tables start from 0, DBF at 1 - loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; + loff = (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; +#else // !__WIN__ + // Offsets of HTML tables start from 0, DIR and DBF at 1 + loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; +#endif // !__WIN__ while (true) { // Default Offset depends on table type diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index f451c73b665..e074232600b 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -117,8 +117,10 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) return NULL; } // endif Fn - tdp->Database = SetPath(g, db); - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + if (!(tdp->Database = SetPath(g, db))) + return NULL; + + tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp index 4128fea6afc..b5f07db8413 100644 --- a/storage/connect/tabmul.cpp +++ b/storage/connect/tabmul.cpp @@ -603,9 +603,10 @@ bool TDBMSD::InitFileNames(PGLOBAL g) bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR, int) { Desc = Fn = GetStringCatInfo(g, "Filename", NULL); - Incl = (GetIntCatInfo("Subdir", 0) != 0); - Huge = (GetIntCatInfo("Huge", 0) != 0); - return false; + Incl = GetBoolCatInfo("Subdir", false); + Huge = GetBoolCatInfo("Huge", false); + Nodir = GetBoolCatInfo("Nodir", true); + return false; } // end of DefineAM /***********************************************************************/ @@ -654,12 +655,14 @@ void TDBDIR::Init(void) TDBDIR::TDBDIR(PDIRDEF tdp) : TDBASE(tdp) { To_File = tdp->Fn; + Nodir = tdp->Nodir; Init(); } // end of TDBDIR standard constructor TDBDIR::TDBDIR(PSZ fpat) : TDBASE((PTABDEF)NULL) { To_File = fpat; + Nodir = true; Init(); } // end of TDBDIR constructor @@ -812,27 +815,32 @@ int TDBDIR::ReadDB(PGLOBAL g) int rc = RC_OK; #if defined(__WIN__) - if (hSearch == INVALID_HANDLE_VALUE) { - /*******************************************************************/ - /* Start searching files in the target directory. The use of the */ - /* Path function is required when called from TDBSDR. */ - /*******************************************************************/ - hSearch = FindFirstFile(Path(g), &FileData); + do { + if (hSearch == INVALID_HANDLE_VALUE) { + /*****************************************************************/ + /* Start searching files in the target directory. The use of */ + /* the Path function is required when called from TDBSDR. */ + /*****************************************************************/ + hSearch = FindFirstFile(Path(g), &FileData); - if (hSearch == INVALID_HANDLE_VALUE) - rc = RC_EF; - else - iFile++; + if (hSearch == INVALID_HANDLE_VALUE) { + rc = RC_EF; + break; + } else + iFile++; - } else { - if (!FindNextFile(hSearch, &FileData)) { - // Restore file name and type pattern - _splitpath(To_File, NULL, NULL, Fname, Ftype); - rc = RC_EF; - } else - iFile++; + } else { + if (!FindNextFile(hSearch, &FileData)) { + // Restore file name and type pattern + _splitpath(To_File, NULL, NULL, Fname, Ftype); + rc = RC_EF; + break; + } else + iFile++; - } // endif hSearch + } // endif hSearch + + } while (Nodir && FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); if (rc == RC_OK) _splitpath(FileData.cFileName, NULL, NULL, Fname, Ftype); @@ -1229,8 +1237,9 @@ int TDBSDR::ReadDB(PGLOBAL g) retry: do { if (Sub->H == INVALID_HANDLE_VALUE) { - _makepath(Fpath, Drive, Direc, "*", "."); - Sub->H = FindFirstFile(Fpath, &FileData); +// _makepath(Fpath, Drive, Direc, "*", "."); why was this made? + _makepath(Fpath, Drive, Direc, "*", NULL); + Sub->H = FindFirstFile(Fpath, &FileData); } else if (!FindNextFile(Sub->H, &FileData)) { FindClose(Sub->H); Sub->H = INVALID_HANDLE_VALUE; @@ -1238,8 +1247,9 @@ int TDBSDR::ReadDB(PGLOBAL g) break; } // endif findnext - } while(!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - || *FileData.cFileName== '.'); + } while (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || + (*FileData.cFileName == '.' && + (!FileData.cFileName[1] || FileData.cFileName[1] == '.'))); if (Sub->H == INVALID_HANDLE_VALUE) { // No more sub-directories. Are we in a sub-directory? @@ -1293,8 +1303,9 @@ int TDBSDR::ReadDB(PGLOBAL g) if (lstat(Fpath, &Fileinfo) < 0) { sprintf(g->Message, "%s: %s", Fpath, strerror(errno)); rc = RC_FX; - } else if (S_ISDIR(Fileinfo.st_mode) && *Entry->d_name != '.') { - // Look in the name sub-directory + } else if (S_ISDIR(Fileinfo.st_mode) && strcmp(Entry->d_name, ".") + && strcmp(Entry->d_name, "..")) { + // Look in the name sub-directory if (!Sub->Next) { PSUBDIR sup; diff --git a/storage/connect/tabmul.h b/storage/connect/tabmul.h index 3c0ab1a4aa5..f26d982d49b 100644 --- a/storage/connect/tabmul.h +++ b/storage/connect/tabmul.h @@ -119,7 +119,8 @@ class DllExport DIRDEF : public TABDEF { /* Directory listing table */ PSZ Fn; /* Path/Name of file search */ bool Incl; /* true to include sub-directories */ bool Huge; /* true if files can be larger than 2GB */ - }; // end of DIRDEF + bool Nodir; /* true to exclude directories */ +}; // end of DIRDEF /***********************************************************************/ /* This is the DIR Access Method class declaration for tables that */ @@ -175,7 +176,8 @@ public: char Direc[_MAX_DIR]; // Search path char Fname[_MAX_FNAME]; // File name char Ftype[_MAX_EXT]; // File extention - }; // end of class TDBDIR + bool Nodir; // Exclude directories from file list +}; // end of class TDBDIR /***********************************************************************/ /* This is the DIR Access Method class declaration for tables that */ diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index a895ffbd839..386d016d082 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -157,8 +157,11 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) tdp = new(g) XMLDEF; tdp->Fn = fn; - tdp->Database = SetPath(g, db); - tdp->Tabname = tab; + + if (!(tdp->Database = SetPath(g, db))) + return NULL; + + tdp->Tabname = tab; tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); From 6525dc63366f751fcfa45a586f378a1c81458657 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 3 May 2017 12:05:05 +0200 Subject: [PATCH 082/148] Disable json tests --- storage/connect/mysql-test/connect/disabled.def | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/connect/mysql-test/connect/disabled.def b/storage/connect/mysql-test/connect/disabled.def index 5e15e0806ba..4e07b5c0576 100644 --- a/storage/connect/mysql-test/connect/disabled.def +++ b/storage/connect/mysql-test/connect/disabled.def @@ -9,7 +9,7 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -#jdbc : Variable settings depend on machine configuration -#jdbc_new : Variable settings depend on machine configuration +jdbc : Variable settings depend on machine configuration +jdbc_new : Variable settings depend on machine configuration jdbc_oracle : Variable settings depend on machine configuration jdbc_postgresql : Variable settings depend on machine configuration From a7c5fd6b4eab72025fae04a87d6ef087dd7c827a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 3 May 2017 15:49:19 +0200 Subject: [PATCH 083/148] restore dependencies, removed in f2dc04abea otherwise make didn't know it needs to regenerate lex_hash.h when gen_lex_hash (that is sql_yacc.h, that is sql_yacc.yy) changes. --- sql/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 5cdf597301f..2e581b1acbe 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -46,6 +46,7 @@ ENDIF() ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h COMMAND gen_lex_token > lex_token.h + DEPENDS gen_lex_token ) ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER) @@ -294,6 +295,7 @@ ENDIF() ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h COMMAND gen_lex_hash > lex_hash.h + DEPENDS gen_lex_hash ) MYSQL_ADD_EXECUTABLE(mysql_tzinfo_to_sql tztime.cc COMPONENT Server) @@ -418,7 +420,7 @@ IF(WIN32) ${CMAKE_CURRENT_BINARY_DIR}/my_bootstrap.sql mysql_bootstrap_sql.c WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${my_bootstrap_sql} + DEPENDS comp_sql ${my_bootstrap_sql} ) MYSQL_ADD_EXECUTABLE(mysql_install_db From a2af3c0d44d919051c08b63cb10bed546d5f92a3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 4 May 2017 18:51:19 +0200 Subject: [PATCH 084/148] Fix MDEV-12653 Cannot add index for ZIP CONNECT table modified: storage/connect/filamzip.cpp modified: storage/connect/ha_connect.cc modified: storage/connect/tabdos.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/xindex.cpp --- storage/connect/filamzip.cpp | 8 +++++++- storage/connect/ha_connect.cc | 10 ++++++---- storage/connect/tabdos.cpp | 4 ++-- storage/connect/tabfmt.cpp | 2 +- storage/connect/tabjson.cpp | 2 +- storage/connect/xindex.cpp | 4 ++-- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 66e628abb14..17ca84d9d5c 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -740,7 +740,13 @@ int UNZFAM::Cardinality(PGLOBAL g) int card = -1; int len = GetFileLength(g); - card = (len / (int)Lrecl) * 2; // Estimated ??? + if (len) { + // Estimated ??? + card = (len / (int)Lrecl) * 2; + card = card ? card : 10; // Lrecl can be too big + } else + card = 0; + return card; } // end of Cardinality diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 9f0b62c73b3..5245b2559c5 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -4601,10 +4601,12 @@ int ha_connect::external_lock(THD *thd, int lock_type) DBUG_RETURN(0); } else if (g->Xchk) { if (!tdbp) { - if (!(tdbp= GetTDB(g))) - DBUG_RETURN(HA_ERR_INTERNAL_ERROR); - else if (!tdbp->GetDef()->Indexable()) { - sprintf(g->Message, "external_lock: Table %s is not indexable", tdbp->GetName()); + if (!(tdbp = GetTDB(g))) { +// DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); + DBUG_RETURN(0); + } else if (!tdbp->GetDef()->Indexable()) { + sprintf(g->Message, "external_lock: Table %s is not indexable", tdbp->GetName()); // DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); DBUG_RETURN(0); diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 02d3fc176ce..d6651fb21a9 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -353,7 +353,7 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode) if (Zipped) { #if defined(ZIP_SUPPORT) if (Recfm == RECFM_VAR) { - if (mode == MODE_READ || mode == MODE_ANY) { + if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) { txfp = new(g) UNZFAM(this); } else if (mode == MODE_INSERT) { txfp = new(g) ZIPFAM(this); @@ -364,7 +364,7 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode) tdbp = new(g) TDBDOS(this, txfp); } else { - if (mode == MODE_READ || mode == MODE_ANY) { + if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) { txfp = new(g) UZXFAM(this); } else if (mode == MODE_INSERT) { txfp = new(g) ZPXFAM(this); diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index be288b3858d..ac85165d99f 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -517,7 +517,7 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode) /*******************************************************************/ if (Zipped) { #if defined(ZIP_SUPPORT) - if (mode == MODE_READ || mode == MODE_ANY) { + if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) { txfp = new(g) UNZFAM(this); } else if (mode == MODE_INSERT) { txfp = new(g) ZIPFAM(this); diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index e074232600b..9450f8d76aa 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -443,7 +443,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) if (Zipped) { #if defined(ZIP_SUPPORT) - if (m == MODE_READ || m == MODE_UPDATE) { + if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { txfp = new(g) UNZFAM(this); } else if (m == MODE_INSERT) { txfp = new(g) ZIPFAM(this); diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index a2ddf468e5a..48edd12b3d8 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -969,8 +969,8 @@ bool XINDEX::Init(PGLOBAL g) // For DBF tables, Cardinality includes bad or soft deleted lines // that are not included in the index, and can be larger then the // index size. - estim = (Tdbp->Ftype == RECFM_DBF); - n = Tdbp->Cardinality(g); // n is exact table size + estim = (Tdbp->Ftype == RECFM_DBF || Tdbp->Txfp->GetAmType() == TYPE_AM_ZIP); + n = Tdbp->Cardinality(g); // n is exact table size } else { // Variable table not optimized estim = true; // n is an estimate of the size From 15f9931f6d2b0eb4006fdc42072c2905fd67c1aa Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 4 May 2017 22:45:32 -0700 Subject: [PATCH 085/148] Fixed the bug mdev-12673. This patch corrects the fix for the bug mdev-10693. It is critical for the function get_best_combination() not to call create_ref_for_key() for constant tables. This bug could manifest itself only in multi-table subqueries where one of the tables is accessed by a constant primary key. --- mysql-test/r/subselect_mat_cost_bugs.result | 42 +++++++++++++++++++++ mysql-test/t/subselect_mat_cost_bugs.test | 39 +++++++++++++++++++ sql/sql_select.cc | 12 +++--- 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result index 24640154c59..9bfd5bd67b5 100644 --- a/mysql-test/r/subselect_mat_cost_bugs.result +++ b/mysql-test/r/subselect_mat_cost_bugs.result @@ -400,3 +400,45 @@ id select_type table type possible_keys key key_len ref rows Extra select * from t1 where c1 = 'a2' and (c1, c2) not in (select * from t2); c1 c2 drop table t1, t2; +# +# MDEV-12673: cost-based choice between materialization and in-to-exists +# +CREATE TABLE t1 ( +pk1 int, a1 varchar(3), b1 varchar(3), PRIMARY KEY (pk1), KEY(a1), KEY(b1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,'foo','bar'),(2,'bar','foo'); +CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 VARCHAR(3), KEY(a2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,'abc'),(2,'xyz'),(3,'foo'); +SELECT 'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); +'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) +0 +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); +'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) +1 +EXPLAIN +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used +2 SUBQUERY t2 const PRIMARY,a2 PRIMARY 4 const 1 +2 SUBQUERY t1 ref a1,b1 b1 6 const 1 Using where +DROP TABLE t1,t2; +CREATE TABLE t1 (i1 INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (i2 int, c2 varchar(3), KEY(i2,c2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,'abc'),(2,'foo'); +CREATE TABLE t3 (pk3 int PRIMARY KEY, c3 varchar(3)) ENGINE=MyISAM; +INSERT INTO t3 VALUES (1,'foo'),(2,'bar'); +SELECT * FROM t1 WHERE i1 NOT IN ( +SELECT i2 FROM t2 RIGHT JOIN t3 ON (c3 = c2) WHERE pk3 = i1 +); +i1 +1 +EXPLAIN +SELECT * FROM t1 WHERE i1 NOT IN ( +SELECT i2 FROM t2 RIGHT JOIN t3 ON (c3 = c2) WHERE pk3 = i1 +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY t3 const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 index NULL i2 11 NULL 2 Using where; Using index +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/subselect_mat_cost_bugs.test b/mysql-test/t/subselect_mat_cost_bugs.test index 8205e94b203..316ac707bef 100644 --- a/mysql-test/t/subselect_mat_cost_bugs.test +++ b/mysql-test/t/subselect_mat_cost_bugs.test @@ -424,3 +424,42 @@ explain select * from t1 where c1 = 'a2' and (c1, c2) not in (select * from t2); select * from t1 where c1 = 'a2' and (c1, c2) not in (select * from t2); drop table t1, t2; + +--echo # +--echo # MDEV-12673: cost-based choice between materialization and in-to-exists +--echo # + +CREATE TABLE t1 ( + pk1 int, a1 varchar(3), b1 varchar(3), PRIMARY KEY (pk1), KEY(a1), KEY(b1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,'foo','bar'),(2,'bar','foo'); + +CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 VARCHAR(3), KEY(a2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,'abc'),(2,'xyz'),(3,'foo'); + +SELECT 'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); +EXPLAIN +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); + +DROP TABLE t1,t2; + +CREATE TABLE t1 (i1 INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (i2 int, c2 varchar(3), KEY(i2,c2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,'abc'),(2,'foo'); + +CREATE TABLE t3 (pk3 int PRIMARY KEY, c3 varchar(3)) ENGINE=MyISAM; +INSERT INTO t3 VALUES (1,'foo'),(2,'bar'); + +SELECT * FROM t1 WHERE i1 NOT IN ( + SELECT i2 FROM t2 RIGHT JOIN t3 ON (c3 = c2) WHERE pk3 = i1 +); + +EXPLAIN +SELECT * FROM t1 WHERE i1 NOT IN ( + SELECT i2 FROM t2 RIGHT JOIN t3 ON (c3 = c2) WHERE pk3 = i1 +); + +DROP TABLE t1,t2,t3; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c5f2a83fc01..09e6ece7807 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7844,12 +7844,14 @@ get_best_combination(JOIN *join) { if (j->bush_children) j= j->bush_children->start; - + used_tables|= j->table->map; - if ((keyuse= join->best_positions[tablenr].key) && - create_ref_for_key(join, j, keyuse, TRUE, used_tables)) - DBUG_RETURN(TRUE); // Something went wrong - + if (j->type != JT_CONST && j->type != JT_SYSTEM) + { + if ((keyuse= join->best_positions[tablenr].key) && + create_ref_for_key(join, j, keyuse, TRUE, used_tables)) + DBUG_RETURN(TRUE); // Something went wrong + } if (j->last_leaf_in_bush) j= j->bush_root_tab; } From bc5c1d99708cf336d632b657ca730955b52df418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 5 May 2017 14:04:18 +0300 Subject: [PATCH 086/148] MDEV-12635 innodb.log_file_size fails when run with Valgrind In MariaDB Server before 10.2, InnoDB will not be shut down properly if startup fails. So, Valgrind failures are to be expected. Disable the test under Valgrind. In 10.2, it should pass with Valgrind. --- mysql-test/suite/innodb/r/log_file_size.result | 3 +++ mysql-test/suite/innodb/t/log_file_size.test | 1 + 2 files changed, 4 insertions(+) diff --git a/mysql-test/suite/innodb/r/log_file_size.result b/mysql-test/suite/innodb/r/log_file_size.result index 67794f293aa..621176d7879 100644 --- a/mysql-test/suite/innodb/r/log_file_size.result +++ b/mysql-test/suite/innodb/r/log_file_size.result @@ -1,3 +1,6 @@ +call mtr.add_suppression("mysqld got signal 11"); +call mtr.add_suppression("Attempting backtrace"); +FLUSH TABLES; CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; BEGIN; INSERT INTO t1 VALUES (42); diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index bf307123734..4bae93957e8 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -31,6 +31,7 @@ call mtr.add_suppression("InnoDB: Only one log file found"); call mtr.add_suppression("InnoDB: Log file .*ib_logfile[01].* size"); call mtr.add_suppression("InnoDB: Unable to open .*ib_logfile0. to check native AIO read support"); # InnoDB shutdown after refused startup is not clean in 10.0 or 10.1! +--source include/not_valgrind.inc call mtr.add_suppression("mysqld got signal 11"); call mtr.add_suppression("Attempting backtrace"); FLUSH TABLES; From e3521ab904866f16fcdf4bdf930634195b4de5e6 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 5 May 2017 13:03:41 +0300 Subject: [PATCH 087/148] Fixed some bugs in fork_big.pl which caused some tests to die early - Changed to 'strict' - Fixed scope of variables - Made timing smaller for of repair, check, flush and alter to get them to trigger earlier --- tests/fork_big.pl | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/tests/fork_big.pl b/tests/fork_big.pl index 6e78e779d11..ec1f131d453 100755 --- a/tests/fork_big.pl +++ b/tests/fork_big.pl @@ -1,4 +1,5 @@ #!/usr/bin/perl -w +use strict; # Copyright (c) 2001, 2006 MySQL AB # Use is subject to license terms @@ -21,7 +22,7 @@ # # Tested a lot with: --threads=30 -$opt_loop_count=500000; # Change this to make test harder/easier +my $opt_loop_count=500000; # Change this to make test harder/easier ##################### Standard benchmark inits ############################## @@ -31,6 +32,13 @@ use Benchmark; package main; +our ($opt_skip_create,$opt_skip_in,$opt_verbose,$opt_fast_insert); +our ($opt_lock_tables,$opt_debug,$opt_skip_delete,$opt_fast,$opt_force); +our ($opt_threads); +our ($opt_host,$opt_user,$opt_password,$opt_db); +my (@testtables, $abort_table, $numtables, $start_time, $end_time); +my ($dbh); + $opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert= $opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0; $opt_threads=5; @@ -94,6 +102,8 @@ $|= 1; # Autoflush #### Start the tests #### +my ($i, $pid, %work); + for ($i=0 ; $i < $opt_threads ; $i ++) { test_insert() if (($pid=fork()) == 0); $work{$pid}="insert"; @@ -118,10 +128,13 @@ test_alter() if (($pid=fork()) == 0); $work{$pid}="alter"; print "Started " . ($opt_threads*2+4) . " threads\n"; +my ($errors, $running_insert_threads); + $errors=0; $running_insert_threads=$opt_threads+$numtables; while (($pid=wait()) != -1) { + my ($ret); $ret=$?/256; print "thread '" . $work{$pid} . "' finished with exit code $ret\n"; if ($work{$pid} =~ /^insert/) @@ -203,7 +216,7 @@ sub test_insert sub test_select { - my ($dbh, $i, $j, $count, $loop); + my ($dbh, $i, $j, $count, $loop, $count_query, $row_counts); $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host", $opt_user, $opt_password, @@ -270,7 +283,7 @@ sub test_select_count sub test_join { - my ($dbh, $i, $j, $count, $loop); + my ($dbh, $i, $j, $count, $loop, $count_query, $row_counts); $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host", $opt_user, $opt_password, @@ -389,7 +402,7 @@ sub test_update sub test_check { - my ($dbh, $row, $i, $j, $type, $table); + my ($dbh, $sth, $row, $i, $j, $type, $table); $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host", $opt_user, $opt_password, { PrintError => 0}) || die $DBI::errstr; @@ -397,7 +410,7 @@ sub test_check $type= "check"; for ($i=$j=0 ; !test_if_abort($dbh) ; $i++) { - sleep(1000); + sleep(200); $table=$testtables[$j]->[0]; $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n"; $sth->execute || die $DBI::errstr; @@ -426,7 +439,7 @@ sub test_check sub test_repair { - my ($dbh, $row, $i, $type, $table); + my ($dbh, $sth, $row, $i, $type, $table); $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host", $opt_user, $opt_password, { PrintError => 0}) || die $DBI::errstr; @@ -434,7 +447,7 @@ sub test_repair $type= "repair"; for ($i=0 ; !test_if_abort($dbh) ; $i++) { - sleep(2000); + sleep(100); $table=$testtables[0]->[0]; $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n"; $sth->execute || die $DBI::errstr; @@ -470,7 +483,7 @@ sub test_flush $count=0; while (!test_if_abort($dbh)) { - sleep(3000); + sleep(300); $dbh->do("flush tables $tables") || die "Got error on flush $DBI::errstr\n"; $count++; @@ -488,7 +501,7 @@ sub test_flush sub test_database { my ($database) = @_; - my ($dbh, $row, $i, $type, $tables); + my ($dbh, $sth, $row, $i, $type, $tables); $dbh = DBI->connect("DBI:mysql:$database:$opt_host", $opt_user, $opt_password, { PrintError => 0}) || die $DBI::errstr; @@ -521,7 +534,7 @@ sub test_database sub test_alter { - my ($dbh, $row, $i, $type, $table); + my ($dbh, $sth, $row, $i, $type, $table); $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host", $opt_user, $opt_password, { PrintError => 0}) || die $DBI::errstr; @@ -559,6 +572,7 @@ sub signal_abort sub test_if_abort() { my ($dbh)=@_; + my ($row); $row=simple_query($dbh,"select * from $opt_db.$abort_table"); return (defined($row) && defined($row->[0]) != 0) ? 1 : 0; } @@ -567,7 +581,7 @@ sub test_if_abort() sub make_count_query { my ($table_count)= @_; - my ($tables, $count_query, $i, $tables_def); + my ($tables, $count_query, $i, $table_def); $tables=""; $count_query="select high_priority "; $table_count--; From fc25437aff119adcfe5bc831e9f1af28cfa0b8a3 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 5 May 2017 13:08:23 +0300 Subject: [PATCH 088/148] MDEV-10104 Table lock race condition with replication Problem was two race condtion in Aria page cache: - find_block() didn't inform free_block() that it had released requests - free_block() didn't handle pinned blocks, which could happen if free_block() was called as part of flush. This is fixed by not freeing blocks that are pinned. This is safe as when maria_close() is called when last thread is using a table, there can be no pinned blocks. For other flush calls it's safe to ignore pinned blocks. --- storage/maria/ma_pagecache.c | 59 ++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 50439785eca..34daf1dcf83 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -493,7 +493,8 @@ error: #define FLUSH_CACHE 2000 /* sort this many blocks at once */ -static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block); +static my_bool free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, + my_bool abort_if_pinned); static void unlink_hash(PAGECACHE *pagecache, PAGECACHE_HASH_LINK *hash_link); #ifndef DBUG_OFF static void test_key_cache(PAGECACHE *pagecache, @@ -1939,7 +1940,7 @@ restart: removed from the cache as we set the PCBLOCK_REASSIGNED flag (see the code below that handles reading requests). */ - free_block(pagecache, block); + free_block(pagecache, block, 0); return 0; } /* Wait until the page is flushed on disk */ @@ -1950,7 +1951,7 @@ restart: /* Invalidate page in the block if it has not been done yet */ DBUG_ASSERT(block->status); /* Should always be true */ if (block->status) - free_block(pagecache, block); + free_block(pagecache, block, 0); return 0; } @@ -1975,8 +1976,13 @@ restart: } else { - DBUG_ASSERT(hash_link->requests > 0); - hash_link->requests--; + /* + When we come here either PCBLOCK_REASSIGNED or PCBLOCK_IN_SWITCH are + active. In both cases wqueue_release_queue() is called when the + state changes. + */ + DBUG_ASSERT(block->hash_link == hash_link); + remove_reader(block); KEYCACHE_DBUG_PRINT("find_block", ("request waiting for old page to be saved")); { @@ -3635,7 +3641,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache, DBUG_ASSERT(block->hash_link->requests > 0); page_link->requests--; /* See NOTE for pagecache_unlock() about registering requests. */ - free_block(pagecache, block); + free_block(pagecache, block, 0); dec_counter_for_resize_op(pagecache); return 0; @@ -4227,7 +4233,8 @@ end: and add it to the free list. */ -static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block) +static my_bool free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, + my_bool abort_if_pinned) { uint status= block->status; KEYCACHE_THREAD_TRACE("free block"); @@ -4241,11 +4248,27 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block) /* While waiting for readers to finish, new readers might request the block. But since we set block->status|= PCBLOCK_REASSIGNED, they - will wait on block->wqueue[COND_FOR_SAVED]. They must be signalled + will wait on block->wqueue[COND_FOR_SAVED]. They must be signaled later. */ block->status|= PCBLOCK_REASSIGNED; wait_for_readers(pagecache, block); + if (unlikely(abort_if_pinned) && unlikely(block->pins)) + { + /* + Block got pinned while waiting for readers. + This can only happens when called from flush_pagecache_blocks_int() + when flushing blocks as part of prepare for maria_close() or from + flush_cached_blocks() + */ + block->status&= ~PCBLOCK_REASSIGNED; + unreg_request(pagecache, block, 0); + + /* All pending requests for this page must be resubmitted. */ + if (block->wqueue[COND_FOR_SAVED].last_thread) + wqueue_release_queue(&block->wqueue[COND_FOR_SAVED]); + return 1; + } unlink_hash(pagecache, block->hash_link); } @@ -4296,6 +4319,8 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block) /* All pending requests for this page must be resubmitted. */ if (block->wqueue[COND_FOR_SAVED].last_thread) wqueue_release_queue(&block->wqueue[COND_FOR_SAVED]); + + return 0; } @@ -4431,9 +4456,16 @@ static int flush_cached_blocks(PAGECACHE *pagecache, if (! (type == FLUSH_KEEP || type == FLUSH_KEEP_LAZY || type == FLUSH_FORCE_WRITE)) { - pagecache->blocks_changed--; - pagecache->global_blocks_changed--; - free_block(pagecache, block); + if (!free_block(pagecache, block, 1)) + { + pagecache->blocks_changed--; + pagecache->global_blocks_changed--; + } + else + { + block->status&= ~PCBLOCK_IN_FLUSH; + link_to_file_list(pagecache, block, file, 1); + } } else { @@ -4671,7 +4703,7 @@ restart: /* It's a temporary file */ pagecache->blocks_changed--; pagecache->global_blocks_changed--; - free_block(pagecache, block); + free_block(pagecache, block, 0); } } else if (type != FLUSH_KEEP_LAZY) @@ -4741,11 +4773,12 @@ restart: #endif next= block->next_changed; if (block->hash_link->file.file == file->file && + !block->pins && (! (block->status & PCBLOCK_CHANGED) || type == FLUSH_IGNORE_CHANGED)) { reg_requests(pagecache, block, 1); - free_block(pagecache, block); + free_block(pagecache, block, 1); } } } From 531698e0da307943dff5ee6830a241d6829345cd Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 6 May 2017 00:08:20 +0200 Subject: [PATCH 089/148] Fix MDEV-12603 Insert replaces values in ZIP file modified: storage/connect/filamzip.cpp modified: storage/connect/filamzip.h Fix MDEV-12686 Handle null in json Fix MDEV-12688 Insert does not handle type TINYINT modified: storage/connect/json.cpp modified: storage/connect/tabjson.cpp --- storage/connect/filamzip.cpp | 65 +++++++++++++++++++++++++++++++++--- storage/connect/filamzip.h | 3 +- storage/connect/json.cpp | 24 ++++++------- storage/connect/tabjson.cpp | 9 ++--- 4 files changed, 80 insertions(+), 21 deletions(-) diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 17ca84d9d5c..92de5117638 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -1,7 +1,7 @@ /*********** File AM Zip C++ Program Source Code File (.CPP) ***********/ /* PROGRAM NAME: FILAMZIP */ /* ------------- */ -/* Version 1.2 */ +/* Version 1.3 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -633,6 +633,28 @@ bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn) return false; } // end of OpenTableFile +/***********************************************************************/ +/* Insert only if the entry does not exist. */ +/***********************************************************************/ +bool UNZIPUTL::IsInsertOk(PGLOBAL g, char *fn) +{ + bool ok = true, b = open(g, fn); + + if (!b) { + if (!target || *target == 0) { + unz_global_info64 ginfo; + int err = unzGetGlobalInfo64(zipfile, &ginfo); + + ok = !(err == UNZ_OK && ginfo.number_entry > 0); + } else // Check if the target exist + ok = (unzLocateFile(zipfile, target, 0) != UNZ_OK); + + unzClose(zipfile); + } // endif b + + return ok; +} // end of IsInsertOk + /***********************************************************************/ /* Open target in zip file. */ /***********************************************************************/ @@ -1006,6 +1028,25 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g) { char filename[_MAX_PATH]; MODE mode = Tdbp->GetMode(); + int len = TXTFAM::GetFileLength(g); + + // We used the file name relative to recorded datapath + PlugSetPath(filename, To_File, Tdbp->GetPath()); + + if (len < 0) + return true; + else if (!append && len > 0) { + strcpy(g->Message, "No insert into existing zip file"); + return true; + } else if (append && len > 0) { + UNZIPUTL *zutp = new(g) UNZIPUTL(target, false); + + if (!zutp->IsInsertOk(g, filename)) { + strcpy(g->Message, "No insert into existing entry"); + return true; + } // endif Ok + + } // endif's /*********************************************************************/ /* Allocate the ZIP utility class. */ @@ -1065,15 +1106,31 @@ ZPXFAM::ZPXFAM(PDOSDEF tdp) : FIXFAM(tdp) target = tdp->GetEntry(); append = tdp->GetAppend(); //Lrecl = tdp->GetLrecl(); -} // end of UZXFAM standard constructor +} // end of ZPXFAM standard constructor /***********************************************************************/ /* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ /***********************************************************************/ bool ZPXFAM::OpenTableFile(PGLOBAL g) { - char filename[_MAX_PATH]; - MODE mode = Tdbp->GetMode(); + char filename[_MAX_PATH]; + MODE mode = Tdbp->GetMode(); + int len = TXTFAM::GetFileLength(g); + + if (len < 0) + return true; + else if (!append && len > 0) { + strcpy(g->Message, "No insert into existing zip file"); + return true; + } else if (append && len > 0) { + UNZIPUTL *zutp = new(g) UNZIPUTL(target, false); + + if (!zutp->IsInsertOk(g, filename)) { + strcpy(g->Message, "No insert into existing entry"); + return true; + } // endif Ok + + } // endif's /*********************************************************************/ /* Allocate the ZIP utility class. */ diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h index 2f9e491f621..ba1d8658dc4 100644 --- a/storage/connect/filamzip.h +++ b/storage/connect/filamzip.h @@ -1,5 +1,5 @@ /************** filamzip H Declares Source Code File (.H) **************/ -/* Name: filamzip.h Version 1.1 */ +/* Name: filamzip.h Version 1.2 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2016-2017 */ /* */ @@ -77,6 +77,7 @@ class DllExport UNZIPUTL : public BLOCK { bool WildMatch(PSZ pat, PSZ str); int findEntry(PGLOBAL g, bool next); int nextEntry(PGLOBAL g); + bool IsInsertOk(PGLOBAL g, char *fn); // Members unzFile zipfile; // The ZIP container file diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index 6817439a635..2aca1377d69 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -370,16 +370,16 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty) PJVAL jvp = new(g) JVALUE; for (; i < len; i++) - switch (s[i]) { - case '\n': - pty[0] = pty[1] = false; - case '\r': - case ' ': - case '\t': - break; - default: - goto suite; - } // endswitch + switch (s[i]) { + case '\n': + pty[0] = pty[1] = false; + case '\r': + case ' ': + case '\t': + break; + default: + goto suite; + } // endswitch suite: switch (s[i]) { @@ -1432,7 +1432,7 @@ void JVALUE::SetTiny(PGLOBAL g, char n) { Value = AllocateValue(g, &n, TYPE_TINY); Jsp = NULL; -} // end of SetInteger +} // end of SetTiny /***********************************************************************/ /* Set the Value's value as the given big integer. */ @@ -1466,6 +1466,6 @@ void JVALUE::SetString(PGLOBAL g, PSZ s, short c) /***********************************************************************/ bool JVALUE::IsNull(void) { - return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsZero() : true; + return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true; } // end of IsNull diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 9450f8d76aa..22f9b592952 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1193,11 +1193,11 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) // } // endif Type default: - vp->Reset(); - } // endswitch Type + vp->SetNull(true); + } // endswitch Type } else - vp->Reset(); + vp->SetNull(true); } // end of SetJsonValue @@ -1211,7 +1211,7 @@ void JSONCOL::ReadColumn(PGLOBAL g) // Set null when applicable if (Nullable) - Value->SetNull(Value->IsZero()); + Value->SetNull(Value->IsNull()); } // end of ReadColumn @@ -1548,6 +1548,7 @@ void JSONCOL::WriteColumn(PGLOBAL g) // Passthru case TYPE_DATE: case TYPE_INT: + case TYPE_TINY: case TYPE_SHORT: case TYPE_BIGINT: case TYPE_DOUBLE: From 6b97fe067db1b1d8e8dee56508e6d78a36e92481 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 9 May 2017 00:41:45 -0700 Subject: [PATCH 090/148] Fixed the bugs mdev-12670 and mdev-12675. The code that blocked conversion of a IN subselect pedicate to a semi-join if it occurred in the ON expression of an outer join did not do it correctly. As a result, the conversion was blocked for IN subselect predicates encountered in ON expressions of INNER joins or in WHERE conditions of mergeable views / derived tables. This patch fixes this problem. --- mysql-test/r/derived_view.result | 38 ++++++++++++ mysql-test/r/limit_rows_examined.result | 5 +- mysql-test/r/subselect_sj.result | 41 ++++++++++++- mysql-test/r/subselect_sj_jcl6.result | 41 ++++++++++++- mysql-test/t/derived_view.test | 30 +++++++++ mysql-test/t/subselect_sj.test | 32 ++++++++++ sql/item_subselect.cc | 2 +- sql/item_subselect.h | 10 ++- sql/opt_subselect.cc | 81 ++++++++++++++++++++++++- 9 files changed, 269 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index d993086299e..8af8db15319 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2579,5 +2579,43 @@ Handler_read_rnd_deleted 0 Handler_read_rnd_next 27 deallocate prepare stmt1; drop table t1,t2; +# +# Bug mdev-12670: mergeable derived / view with subqueries +# subject to semi-join optimizations +# (actually this is a 5.3 bug.) +# +create table t1 (a int) engine=myisam; +insert into t1 values (5),(3),(2),(7),(2),(5),(1); +create table t2 (b int, index idx(b)) engine=myisam; +insert into t2 values (2),(3),(2),(1),(3),(4); +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +analyze table t1,t2; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +explain select a from t1 where a in (select b from t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where +1 PRIMARY t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1) +explain select * from (select a from t1 where a in (select b from t2)) t; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where +1 SIMPLE t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1) +create view v1 as select a from t1 where a in (select b from t2); +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where +1 SIMPLE t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1) +drop view v1; +drop table t1,t2; set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/r/limit_rows_examined.result b/mysql-test/r/limit_rows_examined.result index a51798a5883..4e13e04f961 100644 --- a/mysql-test/r/limit_rows_examined.result +++ b/mysql-test/r/limit_rows_examined.result @@ -426,7 +426,7 @@ c1 bb cc Warnings: -Warning 1931 Query execution was interrupted. The query examined at least 18 rows, which exceeds LIMIT ROWS EXAMINED (16). The query result may be incomplete. +Warning 1931 Query execution was interrupted. The query examined at least 17 rows, which exceeds LIMIT ROWS EXAMINED (16). The query result may be incomplete. select * from v1 LIMIT ROWS EXAMINED 11; c1 bb @@ -439,7 +439,8 @@ from (select * from t1 where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0)) as tmp LIMIT ROWS EXAMINED 11; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +1 SIMPLE eq_ref distinct_key distinct_key 2 func 1 3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where select * from (select * from t1 diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 50a70a6614a..c14b82f274e 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -1650,9 +1650,9 @@ CREATE VIEW v1 AS SELECT 1; EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1); id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) -2 MATERIALIZED system NULL NULL NULL NULL 1 3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1); a a @@ -3060,4 +3060,43 @@ project_number aaa drop table t1, t2, t3; set optimizer_switch= @tmp_mdev6859; +# +# MDEV-12675: subquery subject to semi-join optimizations +# in ON expression of INNER JOIN +# +set @tmp_mdev12675=@@optimizer_switch; +set optimizer_switch=default; +create table t1 (a int) engine=myisam; +insert into t1 values (5),(3),(2),(7),(2),(5),(1); +create table t2 (b int, index idx(b)) engine=myisam; +insert into t2 values (2),(3),(2),(1),(3),(4); +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +analyze table t1,t2; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +explain +select a from t1, t2 where b between 1 and 2 and a in (select b from t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where +1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1) +1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join) +explain +select a from t1 join t2 on b between 1 and 2 and a in (select b from t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where +1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1) +1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join) +drop table t1,t2; +set optimizer_switch= @tmp_mdev12675; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index ccf348fa311..33fd4c519ff 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -1663,9 +1663,9 @@ CREATE VIEW v1 AS SELECT 1; EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1); id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) -2 MATERIALIZED system NULL NULL NULL NULL 1 3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1); a a @@ -3074,6 +3074,45 @@ project_number aaa drop table t1, t2, t3; set optimizer_switch= @tmp_mdev6859; +# +# MDEV-12675: subquery subject to semi-join optimizations +# in ON expression of INNER JOIN +# +set @tmp_mdev12675=@@optimizer_switch; +set optimizer_switch=default; +create table t1 (a int) engine=myisam; +insert into t1 values (5),(3),(2),(7),(2),(5),(1); +create table t2 (b int, index idx(b)) engine=myisam; +insert into t2 values (2),(3),(2),(1),(3),(4); +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +analyze table t1,t2; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +explain +select a from t1, t2 where b between 1 and 2 and a in (select b from t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where +1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1) +1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join) +explain +select a from t1 join t2 on b between 1 and 2 and a in (select b from t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where +1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1) +1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join) +drop table t1,t2; +set optimizer_switch= @tmp_mdev12675; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index d017f847af9..cdddaf8f9d8 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1881,6 +1881,36 @@ deallocate prepare stmt1; drop table t1,t2; +--echo # +--echo # Bug mdev-12670: mergeable derived / view with subqueries +--echo # subject to semi-join optimizations +--echo # (actually this is a 5.3 bug.) +--echo # + +create table t1 (a int) engine=myisam; +insert into t1 values (5),(3),(2),(7),(2),(5),(1); +create table t2 (b int, index idx(b)) engine=myisam; +insert into t2 values (2),(3),(2),(1),(3),(4); +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +analyze table t1,t2; + +explain select a from t1 where a in (select b from t2); +explain select * from (select a from t1 where a in (select b from t2)) t; +create view v1 as select a from t1 where a in (select b from t2); +explain select * from v1; + +drop view v1; +drop table t1,t2; + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 51bed53be17..5e9a2c88f22 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2769,5 +2769,37 @@ WHERE ( SELECT z.country drop table t1, t2, t3; set optimizer_switch= @tmp_mdev6859; +--echo # +--echo # MDEV-12675: subquery subject to semi-join optimizations +--echo # in ON expression of INNER JOIN +--echo # + +set @tmp_mdev12675=@@optimizer_switch; +set optimizer_switch=default; +create table t1 (a int) engine=myisam; +insert into t1 values (5),(3),(2),(7),(2),(5),(1); +create table t2 (b int, index idx(b)) engine=myisam; +insert into t2 values (2),(3),(2),(1),(3),(4); +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +insert into t2 select b+10 from t2; +analyze table t1,t2; + +explain +select a from t1, t2 where b between 1 and 2 and a in (select b from t2); +explain +select a from t1 join t2 on b between 1 and 2 and a in (select b from t2); + +drop table t1,t2; +set optimizer_switch= @tmp_mdev12675; + # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 78dcfc4215c..12337ec2b1c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1366,7 +1366,7 @@ Item_in_subselect::Item_in_subselect(Item * left_exp, Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), optimizer(0), pushed_cond_guards(NULL), emb_on_expr_nest(NULL), - is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), + do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE), upper_item(0) diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 2f166c83e8f..75822ff8c6b 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -466,6 +466,8 @@ public: NULL - for all other locations */ TABLE_LIST *emb_on_expr_nest; + /* May be TRUE only for the candidates to semi-join conversion */ + bool do_not_convert_to_sj; /* Types of left_expr and subquery's select list allow to perform subquery materialization. Currently, we set this to FALSE when it as well could @@ -554,9 +556,9 @@ public: Item_in_subselect() :Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE), abort_on_null(0), in_strategy(SUBS_NOT_TRANSFORMED), optimizer(0), - pushed_cond_guards(NULL), func(NULL), emb_on_expr_nest(NULL), - is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), - upper_item(0) + pushed_cond_guards(NULL), func(NULL), emb_on_expr_nest(NULL), + do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), + is_jtbm_const_tab(FALSE), upper_item(0) {} void cleanup(); subs_type substype() { return IN_SUBS; } @@ -617,6 +619,8 @@ public: emb_on_expr_nest= embedding; } + void block_conversion_to_sj () { do_not_convert_to_sj= TRUE; } + bool test_strategy(uchar strategy) { return test(in_strategy & strategy); } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 5137d8a0986..645afa6744a 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -678,6 +678,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join) !((join->select_options | // 10 select_lex->outer_select()->join->select_options) // 10 & SELECT_STRAIGHT_JOIN)) // 10 + { DBUG_PRINT("info", ("Subquery is semi-join conversion candidate")); @@ -1000,6 +1001,25 @@ bool check_for_outer_joins(List *join_list) } +void find_and_block_conversion_to_sj(Item *to_find, + List_iterator_fast &li) +{ + if (to_find->type() != Item::SUBSELECT_ITEM || + ((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS) + return; + Item_in_subselect *in_subq; + li.rewind(); + while ((in_subq= li++)) + { + if (in_subq == to_find) + { + in_subq->block_conversion_to_sj(); + return; + } + } +} + + /* Convert semi-join subquery predicates into semi-join join nests @@ -1052,7 +1072,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) Query_arena *arena, backup; Item_in_subselect *in_subq; THD *thd= join->thd; - List_iterator ti(join->select_lex->leaf_tables); DBUG_ENTER("convert_join_subqueries_to_semijoins"); if (join->select_lex->sj_subselects.is_empty()) @@ -1070,6 +1089,60 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) subq_sel->update_used_tables(); } + /* + Check all candidates to semi-join conversion that occur + in ON expressions of outer join. Set the flag blocking + this conversion for them. + */ + TABLE_LIST *tbl; + List_iterator ti(join->select_lex->leaf_tables); + while ((tbl= ti++)) + { + TABLE_LIST *embedded; + TABLE_LIST *embedding= tbl; + do + { + embedded= embedding; + if (test(embedded->outer_join)) + { + Item *cond= embedded->on_expr; + if (!cond) + ; + else if (cond->type() != Item::COND_ITEM) + find_and_block_conversion_to_sj(cond, li); + else if (((Item_cond*) cond)->functype() == + Item_func::COND_AND_FUNC) + { + Item *item; + List_iterator it(*(((Item_cond*) cond)->argument_list())); + while ((item= it++)) + { + find_and_block_conversion_to_sj(item, li); + } + } + } + embedding= embedded->embedding; + } + while (embedding && + embedding->nested_join->join_list.head() == embedded); + } + + /* + Block conversion to semi-joins for those candidates that + are encountered in the WHERE condition of the multi-table view + with CHECK OPTION if this view is used in UPDATE/DELETE. + (This limitation can be, probably, easily lifted.) + */ + li.rewind(); + while ((in_subq= li++)) + { + if (in_subq->emb_on_expr_nest != NO_JOIN_NEST && + in_subq->emb_on_expr_nest->effective_with_check) + { + in_subq->block_conversion_to_sj(); + } + } + li.rewind(); /* First, convert child join's subqueries. We proceed bottom-up here */ while ((in_subq= li++)) @@ -1088,8 +1161,10 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) if (convert_join_subqueries_to_semijoins(child_join)) DBUG_RETURN(TRUE); + + in_subq->sj_convert_priority= - test(in_subq->emb_on_expr_nest != NO_JOIN_NEST) * MAX_TABLES * 2 + + test(in_subq->do_not_convert_to_sj) * MAX_TABLES * 2 + in_subq->is_correlated * MAX_TABLES + child_join->outer_tables; } @@ -1122,7 +1197,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) bool remove_item= TRUE; /* Stop processing if we've reached a subquery that's attached to the ON clause */ - if (in_subq->emb_on_expr_nest != NO_JOIN_NEST) + if (in_subq->do_not_convert_to_sj) break; if (in_subq->is_flattenable_semijoin) From 1c88b9a8d3200bdf554ece09316cacf2146877ee Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 11 May 2017 21:57:21 +0200 Subject: [PATCH 091/148] Fix wrong value of JSON column When null and the column is NOT NULL the value was not reset. modified: storage/connect/tabjson.cpp Fix converting bstr_t string to set error message modified: storage/connect/domdoc.cpp Fix MDEV-12768: -Wformat-overflow compile warnings modified: storage/connect/global.h modified: storage/connect/jsonudf.cpp modified: storage/connect/plugutil.cpp modified: storage/connect/tabvct.cpp Typo (in external_lock) modified: storage/connect/ha_connect.cc Remove some warnings modified: storage/connect/odbconn.cpp modified: storage/connect/tabmysql.cpp Add MEM_RESERVE flag to virtualAlloc modified: storage/connect/plgdbutl.cpp Fix MDEV-12573: Accept=1 may show incorrect value for NULL column in CONNECT TBL modified: storage/connect/tabutil.cpp Fix wrong setting of key size when greater than 2G modified: storage/connect/xindex.cpp Fixing MDEV-12149: compile errors on Windows with /Zc:strictStrings Introduce typedef PCSZ and replace PSZ by it where it matters All done on CONNECT but compile still fails because of an included system file modified: storage/connect/array.cpp modified: storage/connect/catalog.h modified: storage/connect/colblk.cpp modified: storage/connect/colblk.h modified: storage/connect/connect.cc modified: storage/connect/domdoc.cpp modified: storage/connect/domdoc.h modified: storage/connect/filamdbf.cpp modified: storage/connect/filamdbf.h modified: storage/connect/filamfix.cpp modified: storage/connect/filamgz.cpp modified: storage/connect/filamtxt.h modified: storage/connect/filamvct.cpp modified: storage/connect/filamvct.h modified: storage/connect/filamzip.cpp modified: storage/connect/filamzip.h modified: storage/connect/ha_connect.cc modified: storage/connect/ha_connect.h modified: storage/connect/jdbccat.h modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/json.cpp modified: storage/connect/json.h modified: storage/connect/jsonudf.cpp modified: storage/connect/jsonudf.h modified: storage/connect/libdoc.cpp modified: storage/connect/macutil.cpp modified: storage/connect/myconn.cpp modified: storage/connect/myutil.cpp modified: storage/connect/myutil.h modified: storage/connect/odbccat.h modified: storage/connect/odbconn.cpp modified: storage/connect/odbconn.h modified: storage/connect/os.h modified: storage/connect/plgdbsem.h modified: storage/connect/plgdbutl.cpp modified: storage/connect/plgxml.cpp modified: storage/connect/plgxml.h modified: storage/connect/plugutil.cpp modified: storage/connect/preparse.h modified: storage/connect/reldef.cpp modified: storage/connect/reldef.h modified: storage/connect/tabdos.cpp modified: storage/connect/tabdos.h modified: storage/connect/tabext.cpp modified: storage/connect/tabext.h modified: storage/connect/tabfix.cpp modified: storage/connect/tabfix.h modified: storage/connect/tabfmt.cpp modified: storage/connect/tabfmt.h modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h modified: storage/connect/tabjson.cpp modified: storage/connect/tabjson.h modified: storage/connect/table.cpp modified: storage/connect/tabmac.cpp modified: storage/connect/tabmul.cpp modified: storage/connect/tabmul.h modified: storage/connect/tabmysql.cpp modified: storage/connect/tabmysql.h modified: storage/connect/tabodbc.cpp modified: storage/connect/tabodbc.h modified: storage/connect/tabpivot.cpp modified: storage/connect/tabpivot.h modified: storage/connect/tabsys.cpp modified: storage/connect/tabsys.h modified: storage/connect/tabutil.cpp modified: storage/connect/tabutil.h modified: storage/connect/tabvir.cpp modified: storage/connect/tabvir.h modified: storage/connect/tabwmi.cpp modified: storage/connect/tabwmi.h modified: storage/connect/tabxml.cpp modified: storage/connect/tabxml.h modified: storage/connect/tabzip.cpp modified: storage/connect/tabzip.h modified: storage/connect/valblk.cpp modified: storage/connect/valblk.h modified: storage/connect/value.cpp modified: storage/connect/value.h modified: storage/connect/xindex.cpp modified: storage/connect/xobject.cpp modified: storage/connect/xobject.h modified: storage/connect/xtable.h Fix MDEV-12603 Insert replaces values in ZIP file modified: storage/connect/filamzip.cpp modified: storage/connect/filamzip.h Fix MDEV-12686 Handle null in json Fix MDEV-12688 Insert does not handle type TINYINT modified: storage/connect/json.cpp modified: storage/connect/tabjson.cpp Fix MDEV-12653 Cannot add index for ZIP CONNECT table modified: storage/connect/filamzip.cpp modified: storage/connect/ha_connect.cc modified: storage/connect/tabdos.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/xindex.cpp --- storage/connect/array.cpp | 18 +- storage/connect/blkfil.cpp | 4 - storage/connect/catalog.h | 17 +- storage/connect/colblk.cpp | 22 +- storage/connect/colblk.h | 8 +- storage/connect/connect.cc | 553 +++++------- storage/connect/connect.h | 2 +- storage/connect/domdoc.cpp | 20 +- storage/connect/domdoc.h | 8 +- storage/connect/filamdbf.cpp | 6 +- storage/connect/filamdbf.h | 4 +- storage/connect/filamfix.cpp | 3 +- storage/connect/filamgz.cpp | 4 +- storage/connect/filamtxt.cpp | 31 +- storage/connect/filamtxt.h | 2 +- storage/connect/filamvct.cpp | 96 +-- storage/connect/filamvct.h | 6 +- storage/connect/filamzip.cpp | 30 +- storage/connect/filamzip.h | 44 +- storage/connect/filter.cpp | 12 - storage/connect/filter.h | 2 +- storage/connect/global.h | 2 +- storage/connect/ha_connect.cc | 1425 +++++++++++++++---------------- storage/connect/ha_connect.h | 36 +- storage/connect/inihandl.c | 2 +- storage/connect/ioapi.c | 21 +- storage/connect/ioapi.h | 5 +- storage/connect/jdbccat.h | 20 +- storage/connect/jdbconn.cpp | 42 +- storage/connect/jdbconn.h | 30 +- storage/connect/json.cpp | 325 +++---- storage/connect/json.h | 20 +- storage/connect/jsonudf.cpp | 390 ++++----- storage/connect/jsonudf.h | 2 +- storage/connect/libdoc.cpp | 27 +- storage/connect/macutil.cpp | 2 +- storage/connect/mycat.cc | 37 +- storage/connect/mycat.h | 7 +- storage/connect/myconn.cpp | 11 +- storage/connect/myutil.cpp | 8 +- storage/connect/myutil.h | 8 +- storage/connect/odbccat.h | 18 +- storage/connect/odbconn.cpp | 111 +-- storage/connect/odbconn.h | 32 +- storage/connect/os.h | 3 + storage/connect/plgdbsem.h | 19 +- storage/connect/plgdbutl.cpp | 180 ++-- storage/connect/plgxml.cpp | 4 +- storage/connect/plgxml.h | 12 +- storage/connect/plugutil.cpp | 29 +- storage/connect/preparse.h | 4 +- storage/connect/reldef.cpp | 43 +- storage/connect/reldef.h | 18 +- storage/connect/tabdos.cpp | 63 +- storage/connect/tabdos.h | 20 +- storage/connect/tabext.cpp | 65 +- storage/connect/tabext.h | 36 +- storage/connect/tabfix.cpp | 38 +- storage/connect/tabfix.h | 4 +- storage/connect/tabfmt.cpp | 22 +- storage/connect/tabfmt.h | 6 +- storage/connect/tabjdbc.cpp | 68 +- storage/connect/tabjdbc.h | 14 +- storage/connect/tabjson.cpp | 132 ++- storage/connect/tabjson.h | 58 +- storage/connect/table.cpp | 4 +- storage/connect/tabmac.cpp | 2 +- storage/connect/tabmul.cpp | 28 +- storage/connect/tabmul.h | 10 +- storage/connect/tabmysql.cpp | 150 ++-- storage/connect/tabmysql.h | 24 +- storage/connect/tabodbc.cpp | 55 +- storage/connect/tabodbc.h | 16 +- storage/connect/tabpivot.cpp | 343 ++++---- storage/connect/tabpivot.h | 18 +- storage/connect/tabsys.cpp | 40 +- storage/connect/tabsys.h | 6 +- storage/connect/tabutil.cpp | 18 +- storage/connect/tabutil.h | 4 +- storage/connect/tabvct.cpp | 18 +- storage/connect/tabvir.cpp | 6 +- storage/connect/tabvir.h | 2 +- storage/connect/tabwmi.cpp | 4 +- storage/connect/tabwmi.h | 2 +- storage/connect/tabxml.cpp | 82 +- storage/connect/tabxml.h | 12 +- storage/connect/tabzip.cpp | 4 +- storage/connect/tabzip.h | 6 +- storage/connect/user_connect.cc | 2 +- storage/connect/user_connect.h | 2 +- storage/connect/valblk.cpp | 58 +- storage/connect/valblk.h | 24 +- storage/connect/value.cpp | 330 ++----- storage/connect/value.h | 51 +- storage/connect/xindex.cpp | 22 +- storage/connect/xobject.cpp | 27 +- storage/connect/xobject.h | 10 +- storage/connect/xtable.h | 70 +- storage/connect/zip.c | 14 +- 99 files changed, 2384 insertions(+), 3391 deletions(-) diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index beb58baa107..8eaeeea2d8a 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -519,11 +519,7 @@ bool ARRAY::FilTest(PGLOBAL g, PVAL valp, OPVAL opc, int opm) } else if (opc != OP_EXIST) { sprintf(g->Message, MSG(MISSING_ARG), opc); -#if defined(USE_TRY) throw TYPE_ARRAY; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_ARRAY); -#endif // !USE_TRY } else // OP_EXIST return Nval > 0; @@ -685,22 +681,14 @@ void ARRAY::SetPrecision(PGLOBAL g, int p) { if (Vblp == NULL) { strcpy(g->Message, MSG(PREC_VBLP_NULL)); -#if defined(USE_TRY) throw TYPE_ARRAY; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_ARRAY); -#endif // !USE_TRY } // endif Vblp bool was = Vblp->IsCi(); if (was && !p) { strcpy(g->Message, MSG(BAD_SET_CASE)); -#if defined(USE_TRY) throw TYPE_ARRAY; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_ARRAY); -#endif // !USE_TRY } // endif Vblp if (was || !p) @@ -711,11 +699,7 @@ void ARRAY::SetPrecision(PGLOBAL g, int p) if (!was && Type == TYPE_STRING) // Must be resorted to eliminate duplicate strings if (Sort(g)) -#if defined(USE_TRY) throw TYPE_ARRAY; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_ARRAY); -#endif // !USE_TRY } // end of SetPrecision @@ -993,7 +977,7 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) size_t z, len = 2; if (Type == TYPE_LIST) - return "(?" "?" "?)"; // To be implemented + return (PSZ)("(?" "?" "?)"); // To be implemented z = MY_MAX(24, GetTypeSize(Type, Len) + 4); tp = (char*)PlugSubAlloc(g, NULL, z); diff --git a/storage/connect/blkfil.cpp b/storage/connect/blkfil.cpp index 4e5c7484057..e438e185e5d 100644 --- a/storage/connect/blkfil.cpp +++ b/storage/connect/blkfil.cpp @@ -595,11 +595,7 @@ BLKFILIN::BLKFILIN(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp) if (Colp->GetResultType() != Type) { sprintf(g->Message, "BLKFILIN: %s", MSG(VALTYPE_NOMATCH)); -#if defined(USE_TRY) throw g->Message; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 99); -#endif // !USE_TRY } else if (Colp->GetValue()->IsCi()) Arap->SetPrecision(g, 1); // Case insensitive diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h index 5fa38277832..48347d7519e 100644 --- a/storage/connect/catalog.h +++ b/storage/connect/catalog.h @@ -36,7 +36,7 @@ typedef struct _curtab { /* Defines the structure used to get column catalog info. */ /***********************************************************************/ typedef struct _colinfo { - char *Name; + PCSZ Name; int Type; int Offset; int Length; @@ -45,9 +45,9 @@ typedef struct _colinfo { int Scale; int Opt; int Freq; - char *Remark; - char *Datefmt; - char *Fieldfmt; + PCSZ Remark; + PCSZ Datefmt; + PCSZ Fieldfmt; ushort Flags; // Used by MariaDB CONNECT handlers } COLINFO, *PCOLINFO; @@ -68,17 +68,15 @@ class DllExport CATALOG { bool GetDefHuge(void) {return DefHuge;} void SetDefHuge(bool b) {DefHuge = b;} char *GetCbuf(void) {return Cbuf;} -//char *GetDataPath(void) {return (char*)DataPath;} // Methods virtual void Reset(void) {} -//virtual void SetDataPath(PGLOBAL g, const char *path) {} virtual bool CheckName(PGLOBAL, char*) {return true;} virtual bool ClearName(PGLOBAL, PSZ) {return true;} virtual PRELDEF MakeOneTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;} virtual PRELDEF GetTableDescEx(PGLOBAL, PTABLE) {return NULL;} - /*virtual PRELDEF GetTableDesc(PGLOBAL, LPCSTR, LPCSTR, - PRELDEF* = NULL) {return NULL;}*/ + //virtual PRELDEF GetTableDesc(PGLOBAL, LPCSTR, LPCSTR, + // PRELDEF* = NULL) {return NULL;} virtual PRELDEF GetFirstTable(PGLOBAL) {return NULL;} virtual PRELDEF GetNextTable(PGLOBAL) {return NULL;} virtual bool TestCond(PGLOBAL, const char*, const char*) {return true;} @@ -95,14 +93,13 @@ class DllExport CATALOG { protected: virtual bool ClearSection(PGLOBAL, const char*, const char*) {return true;} - /*virtual PRELDEF MakeTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;}*/ + //virtual PRELDEF MakeTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;} // Members char *Cbuf; /* Buffer used for col section */ int Cblen; /* Length of suballoc. buffer */ CURTAB Ctb; /* Used to enumerate tables */ bool DefHuge; /* true: tables default to huge */ -//LPCSTR DataPath; /* Is the Path of DB data dir */ }; // end of class CATALOG #endif // __CATALOG__H diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp index a1169296a89..fa205b493a2 100644 --- a/storage/connect/colblk.cpp +++ b/storage/connect/colblk.cpp @@ -195,13 +195,9 @@ int COLBLK::GetLengthEx(void) /* corresponding to this column and convert it to buffer type. */ /***********************************************************************/ void COLBLK::ReadColumn(PGLOBAL g) - { +{ sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn"); -#if defined(USE_TRY) throw TYPE_COLBLK; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_COLBLK); -#endif // !USE_TRY } // end of ReadColumn /***********************************************************************/ @@ -210,13 +206,9 @@ void COLBLK::ReadColumn(PGLOBAL g) /* corresponding to this column from the column buffer and type. */ /***********************************************************************/ void COLBLK::WriteColumn(PGLOBAL g) - { +{ sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn"); -#if defined(USE_TRY) throw TYPE_COLBLK; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_COLBLK); -#endif // !USE_TRY } // end of WriteColumn /***********************************************************************/ @@ -268,13 +260,9 @@ SPCBLK::SPCBLK(PCOLUMN cp) /* corresponding to this column from the column buffer and type. */ /***********************************************************************/ void SPCBLK::WriteColumn(PGLOBAL g) - { +{ sprintf(g->Message, MSG(SPCOL_READONLY), Name); -#if defined(USE_TRY) throw TYPE_COLBLK; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_COLBLK); -#endif // !USE_TRY } // end of WriteColumn /***********************************************************************/ @@ -389,7 +377,7 @@ PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp) void PRTBLK::ReadColumn(PGLOBAL g) { if (Pname == NULL) { - char *p; + const char *p; Pname = To_Tdb->GetDef()->GetStringCatInfo(g, "partname", "?"); p = strrchr(Pname, '#'); @@ -419,7 +407,7 @@ SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp) void SIDBLK::ReadColumn(PGLOBAL) { //if (Sname == NULL) { - Sname = (char*)To_Tdb->GetServer(); + Sname = To_Tdb->GetServer(); Value->SetValue_psz(Sname); // } // endif Sname diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h index c64f9d95129..02c4f2361b7 100644 --- a/storage/connect/colblk.h +++ b/storage/connect/colblk.h @@ -154,7 +154,7 @@ class DllExport FIDBLK : public SPCBLK { virtual void ReadColumn(PGLOBAL g); protected: - PSZ Fn; // The current To_File of the table + PCSZ Fn; // The current To_File of the table OPVAL Op; // The file part operator }; // end of class FIDBLK @@ -178,7 +178,7 @@ class DllExport TIDBLK : public SPCBLK { TIDBLK(void) {} // Members - PSZ Tname; // The current table name + PCSZ Tname; // The current table name }; // end of class TIDBLK /***********************************************************************/ @@ -201,7 +201,7 @@ class DllExport PRTBLK : public SPCBLK { PRTBLK(void) {} // Members - PSZ Pname; // The current partition name + PCSZ Pname; // The current partition name }; // end of class PRTBLK /***********************************************************************/ @@ -224,7 +224,7 @@ class DllExport SIDBLK : public SPCBLK { SIDBLK(void) {} // Members - PSZ Sname; // The current server name + PCSZ Sname; // The current server name }; // end of class SIDBLK #endif // __COLBLK__H diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 5d5eca80275..e15cc724b85 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -12,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /***********************************************************************/ /* Author Olivier BERTRAND bertrandop@gmail.com 2004-2017 */ @@ -121,8 +121,6 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname) return true; if (dbuserp->Catalog) { -// ((MYCAT *)dbuserp->Catalog)->SetHandler(handler); done later -// ((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname); return false; // Nothing else to do } // endif Catalog @@ -139,9 +137,6 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname) if (!(dbuserp->Catalog= new MYCAT(handler))) return true; -//((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname); -//dbuserp->UseTemp= TMP_AUTO; - /*********************************************************************/ /* All is correct. */ /*********************************************************************/ @@ -173,7 +168,7 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info) // info->mean_rec_length= tdbp->GetLrecl(); info->mean_rec_length= 0; - info->data_file_name= (b) ? NULL : tdbp->GetFile(g); + info->data_file_name= (b) ? NULL : (char*)tdbp->GetFile(g); return true; } else { info->data_file_length= 0; @@ -201,50 +196,31 @@ PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h) if (!cat) return NULL; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return NULL; - } // endif jump_level + // Get table object from the catalog + tabp = new(g) XTAB(name); - if (setjmp(g->jumper[++g->jump_level])) { - tdbp = NULL; - goto err; - } // endif rc -#endif // !USE_TRY + if (trace) + printf("CntGetTDB: tabp=%p\n", tabp); - // Get table object from the catalog - tabp = new(g) XTAB(name); + // Perhaps this should be made thread safe + ((MYCAT*)cat)->SetHandler(h); - if (trace) - printf("CntGetTDB: tabp=%p\n", tabp); + if (!(tdbp = cat->GetTable(g, tabp, mode))) + printf("CntGetTDB: %s\n", g->Message); - // Perhaps this should be made thread safe - ((MYCAT*)cat)->SetHandler(h); - - if (!(tdbp = cat->GetTable(g, tabp, mode))) - printf("CntGetTDB: %s\n", g->Message); - -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); } catch (const char *msg) { strcpy(g->Message, msg); } // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY if (trace) printf("Returning tdbp=%p mode=%d\n", tdbp, mode); return tdbp; - } // end of CntGetTDB +} // end of CntGetTDB /***********************************************************************/ /* OPENTAB: Open a Table. */ @@ -268,161 +244,116 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, return true; } // endif tdbp -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return true; - } // endif jump_level + if (!c1) { + if (mode == MODE_INSERT) + // Allocate all column blocks for that table + tdbp->ColDB(g, NULL, 0); - if (setjmp(g->jumper[++g->jump_level])) { - goto err; - } // endif rc -#endif // !USE_TRY + } else for (p = c1; *p; p += n) { + // Allocate only used column blocks + if (trace) + printf("Allocating column %s\n", p); - if (!c1) { - if (mode == MODE_INSERT) - // Allocate all column blocks for that table - tdbp->ColDB(g, NULL, 0); + g->Message[0] = 0; // To check whether ColDB made an error message + colp = tdbp->ColDB(g, p, 0); - } else for (p= c1; *p; p+= n) { - // Allocate only used column blocks - if (trace) - printf("Allocating column %s\n", p); + if (!colp && !(mode == MODE_INSERT && tdbp->IsSpecial(p))) { + if (g->Message[0] == 0) + sprintf(g->Message, MSG(COL_ISNOT_TABLE), p, tdbp->GetName()); - g->Message[0] = 0; // To check whether ColDB made an error message - colp= tdbp->ColDB(g, p, 0); + throw 1; + } // endif colp - if (!colp && !(mode == MODE_INSERT && tdbp->IsSpecial(p))) { - if (g->Message[0] == 0) - sprintf(g->Message, MSG(COL_ISNOT_TABLE), p, tdbp->GetName()); + n = strlen(p) + 1; + } // endfor p -#if defined(USE_TRY) - throw 1; -#else // !USE_TRY - goto err; -#endif // !USE_TRY - } // endif colp + for (i = 0, colp = tdbp->GetColumns(); colp; i++, colp = colp->GetNext()) { + if (colp->InitValue(g)) + throw 2; - n= strlen(p) + 1; - } // endfor p + if (mode == MODE_INSERT) + // Allow type conversion + if (colp->SetBuffer(g, colp->GetValue(), true, false)) + throw 3; - for (i= 0, colp= tdbp->GetColumns(); colp; i++, colp= colp->GetNext()) { - if (colp->InitValue(g)) -#if defined(USE_TRY) - throw 2; -#else // !USE_TRY - goto err; -#endif // !USE_TRY + colp->AddColUse(U_P); // For PLG tables + } // endfor colp - if (mode == MODE_INSERT) - // Allow type conversion - if (colp->SetBuffer(g, colp->GetValue(), true, false)) -#if defined(USE_TRY) - throw 3; -#else // !USE_TRY - goto err; -#endif // !USE_TRY + /*******************************************************************/ + /* In Update mode, the updated column blocks must be distinct from */ + /* the read column blocks. So make a copy of the TDB and allocate */ + /* its column blocks in mode write (required by XML tables). */ + /*******************************************************************/ + if (mode == MODE_UPDATE) { + PTDBASE utp; - colp->AddColUse(U_P); // For PLG tables - } // endfor colp + if (!(utp = (PTDBASE)tdbp->Duplicate(g))) { + sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName()); + throw 4; + } // endif tp - /*********************************************************************/ - /* In Update mode, the updated column blocks must be distinct from */ - /* the read column blocks. So make a copy of the TDB and allocate */ - /* its column blocks in mode write (required by XML tables). */ - /*********************************************************************/ - if (mode == MODE_UPDATE) { - PTDBASE utp; + if (!c2) + // Allocate all column blocks for that table + utp->ColDB(g, NULL, 0); + else for (p = c2; *p; p += n) { + // Allocate only used column blocks + colp = utp->ColDB(g, p, 0); + n = strlen(p) + 1; + } // endfor p - if (!(utp= (PTDBASE)tdbp->Duplicate(g))) { - sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName()); -#if defined(USE_TRY) - throw 4; -#else // !USE_TRY - goto err; -#endif // !USE_TRY - } // endif tp + for (i = 0, colp = utp->GetColumns(); colp; i++, colp = colp->GetNext()) { + if (colp->InitValue(g)) + throw 5; - if (!c2) - // Allocate all column blocks for that table - utp->ColDB(g, NULL, 0); - else for (p= c2; *p; p+= n) { - // Allocate only used column blocks - colp= utp->ColDB(g, p, 0); - n= strlen(p) + 1; - } // endfor p + if (colp->SetBuffer(g, colp->GetValue(), true, false)) + throw 6; - for (i= 0, colp= utp->GetColumns(); colp; i++, colp= colp->GetNext()) { - if (colp->InitValue(g)) -#if defined(USE_TRY) - throw 5; -#else // !USE_TRY - goto err; -#endif // !USE_TRY + } // endfor colp - if (colp->SetBuffer(g, colp->GetValue(), true, false)) -#if defined(USE_TRY) - throw 6; -#else // !USE_TRY - goto err; -#endif // !USE_TRY + // Attach the updated columns list to the main table + tdbp->SetSetCols(utp->GetColumns()); + } else if (tdbp && mode == MODE_INSERT) + tdbp->SetSetCols(tdbp->GetColumns()); - } // endfor colp + // Now do open the physical table + if (trace) + printf("Opening table %s in mode %d tdbp=%p\n", + tdbp->GetName(), mode, tdbp); - // Attach the updated columns list to the main table - tdbp->SetSetCols(utp->GetColumns()); - } else if (tdbp && mode == MODE_INSERT) - tdbp->SetSetCols(tdbp->GetColumns()); + //tdbp->SetMode(mode); - // Now do open the physical table - if (trace) - printf("Opening table %s in mode %d tdbp=%p\n", - tdbp->GetName(), mode, tdbp); - -//tdbp->SetMode(mode); - - if (del/* && (tdbp->GetFtype() != RECFM_NAF*/) { - // To avoid erasing the table when doing a partial delete - // make a fake Next + if (del/* && (tdbp->GetFtype() != RECFM_NAF*/) { + // To avoid erasing the table when doing a partial delete + // make a fake Next // PDOSDEF ddp= new(g) DOSDEF; // PTDB tp= new(g) TDBDOS(ddp, NULL); - tdbp->SetNext((PTDB)1); - dup->Check &= ~CHK_DELETE; - } // endif del + tdbp->SetNext((PTDB)1); + dup->Check &= ~CHK_DELETE; + } // endif del - if (trace) - printf("About to open the table: tdbp=%p\n", tdbp); + if (trace) + printf("About to open the table: tdbp=%p\n", tdbp); - if (mode != MODE_ANY && mode != MODE_ALTER) { - if (tdbp->OpenDB(g)) { - printf("%s\n", g->Message); -#if defined(USE_TRY) - throw 7; -#else // !USE_TRY - goto err; -#endif // !USE_TRY - } else - tdbp->SetNext(NULL); + if (mode != MODE_ANY && mode != MODE_ALTER) { + if (tdbp->OpenDB(g)) { + printf("%s\n", g->Message); + throw 7; + } else + tdbp->SetNext(NULL); - } // endif mode + } // endif mode - rcop= false; + rcop = false; -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); } catch (const char *msg) { strcpy(g->Message, msg); } // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY + return rcop; } // end of CntOpenTable @@ -442,65 +373,40 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp) /* Evaluate all columns after a record is read. */ /***********************************************************************/ RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool reset, bool mrr) - { +{ RCODE rc= RC_OK; PCOL colp; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - if (trace) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - printf("EvalColumns: %s\n", g->Message); - } // endif + for (colp = tdbp->GetColumns(); rc == RC_OK && colp; + colp = colp->GetNext()) { + if (reset) + colp->Reset(); - return RC_FX; - } // endif jump_level + // Virtual columns are computed by MariaDB + if (!colp->GetColUse(U_VIRTUAL) && (!mrr || colp->GetKcol())) + if (colp->Eval(g)) + rc = RC_FX; - if (setjmp(g->jumper[++g->jump_level]) != 0) { + } // endfor colp + + } catch (int n) { if (trace) - printf("Error reading columns: %s\n", g->Message); + printf("Error %d reading columns: %s\n", n, g->Message); rc = RC_FX; - goto err; - } // endif rc -#endif // !USE_TRY + } catch (const char *msg) { + strcpy(g->Message, msg); + } // end catch - for (colp= tdbp->GetColumns(); rc == RC_OK && colp; - colp= colp->GetNext()) { - if (reset) - colp->Reset(); - - // Virtual columns are computed by MariaDB - if (!colp->GetColUse(U_VIRTUAL) && (!mrr || colp->GetKcol())) - if (colp->Eval(g)) - rc= RC_FX; - - } // endfor colp - -#if defined(USE_TRY) -} catch (int n) { - if (trace) - printf("Error %d reading columns: %s\n", n, g->Message); - - rc = RC_FX; -} catch (const char *msg) { - strcpy(g->Message, msg); -} // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY return rc; - } // end of EvalColumns +} // end of EvalColumns /***********************************************************************/ /* ReadNext: Read next record sequentially. */ /***********************************************************************/ RCODE CntReadNext(PGLOBAL g, PTDB tdbp) - { +{ RCODE rc; if (!tdbp) @@ -515,103 +421,66 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp) ((PTDBASE)tdbp)->ResetKindex(g, NULL); } // endif index -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return RC_FX; - } // endif jump_level + // Do it now to avoid double eval when filtering + for (PCOL colp = tdbp->GetColumns(); colp; colp = colp->GetNext()) + colp->Reset(); - if ((setjmp(g->jumper[++g->jump_level])) != 0) { - rc = RC_FX; - goto err; - } // endif rc -#endif // !USE_TRY + do { + if ((rc = (RCODE)tdbp->ReadDB(g)) == RC_OK) + if (!ApplyFilter(g, tdbp->GetFilter())) + rc = RC_NF; - // Do it now to avoid double eval when filtering - for (PCOL colp= tdbp->GetColumns(); colp; colp= colp->GetNext()) - colp->Reset(); + } while (rc == RC_NF); - do { - if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK) - if (!ApplyFilter(g, tdbp->GetFilter())) - rc= RC_NF; + if (rc == RC_OK) + rc = EvalColumns(g, tdbp, false); - } while (rc == RC_NF); - - if (rc == RC_OK) - rc= EvalColumns(g, tdbp, false); - -#if defined(USE_TRY) - } catch (int) { + } catch (int) { rc = RC_FX; } catch (const char *msg) { strcpy(g->Message, msg); rc = RC_FX; } // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY + return rc; - } // end of CntReadNext +} // end of CntReadNext /***********************************************************************/ /* WriteRow: Insert a new row into a table. */ /***********************************************************************/ RCODE CntWriteRow(PGLOBAL g, PTDB tdbp) - { - RCODE rc; - PCOL colp; -//PTDBASE tp= (PTDBASE)tdbp; +{ + RCODE rc; + PCOL colp; + //PTDBASE tp= (PTDBASE)tdbp; - if (!tdbp) - return RC_FX; - -#if defined(USE_TRY) - try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); + if (!tdbp) return RC_FX; - } // endif jump_level - if (setjmp(g->jumper[++g->jump_level]) != 0) { - printf("%s\n", g->Message); + try { + // Store column values in table write buffer(s) + for (colp = tdbp->GetSetCols(); colp; colp = colp->GetNext()) + if (!colp->GetColUse(U_VIRTUAL)) + colp->WriteColumn(g); + + if (tdbp->IsIndexed()) + // Index values must be sorted before updating + rc = (RCODE)((PTDBDOS)tdbp)->GetTxfp()->StoreValues(g, true); + else + // Return result code from write operation + rc = (RCODE)tdbp->WriteDB(g); + + } catch (int n) { + printf("Exception %d: %s\n", n, g->Message); rc = RC_FX; - goto err; - } // endif rc -#endif // !USE_TRY + } catch (const char *msg) { + strcpy(g->Message, msg); + rc = RC_FX; + } // end catch - // Store column values in table write buffer(s) - for (colp= tdbp->GetSetCols(); colp; colp= colp->GetNext()) - if (!colp->GetColUse(U_VIRTUAL)) - colp->WriteColumn(g); - - if (tdbp->IsIndexed()) - // Index values must be sorted before updating - rc= (RCODE)((PTDBDOS)tdbp)->GetTxfp()->StoreValues(g, true); - else - // Return result code from write operation - rc= (RCODE)tdbp->WriteDB(g); - -#if defined(USE_TRY) -} catch (int n) { - printf("Exception %d: %s\n", n, g->Message); - rc = RC_FX; -} catch (const char *msg) { - strcpy(g->Message, msg); - rc = RC_FX; -} // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY - return rc; - } // end of CntWriteRow + return rc; +} // end of CntWriteRow /***********************************************************************/ /* UpdateRow: Update a row into a table. */ @@ -659,98 +528,78 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all) /* CLOSETAB: Close a table. */ /***********************************************************************/ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort) - { - int rc= RC_OK; -//TDBASE *tbxp= (PTDBASE)tdbp; +{ + int rc = RC_OK; + //TDBASE *tbxp= (PTDBASE)tdbp; - if (!tdbp) - return rc; // Nothing to do - else if (tdbp->GetUse() != USE_OPEN) { - if (tdbp->GetAmType() == TYPE_AM_XML) - tdbp->CloseDB(g); // Opened by GetMaxSize + if (!tdbp) + return rc; // Nothing to do + else if (tdbp->GetUse() != USE_OPEN) { + if (tdbp->GetAmType() == TYPE_AM_XML) + tdbp->CloseDB(g); // Opened by GetMaxSize - return rc; - } // endif !USE_OPEN + return rc; + } // endif !USE_OPEN - if (trace) - printf("CntCloseTable: tdbp=%p mode=%d nox=%d abort=%d\n", - tdbp, tdbp->GetMode(), nox, abort); + if (trace) + printf("CntCloseTable: tdbp=%p mode=%d nox=%d abort=%d\n", + tdbp, tdbp->GetMode(), nox, abort); - if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN) { - if (tdbp->IsIndexed()) - rc= ((PTDBDOS)tdbp)->GetTxfp()->DeleteSortedRows(g); + if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN) { + if (tdbp->IsIndexed()) + rc = ((PTDBDOS)tdbp)->GetTxfp()->DeleteSortedRows(g); - if (!rc) - rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine + if (!rc) + rc = tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine - } else if (tdbp->GetMode() == MODE_UPDATE && tdbp->IsIndexed()) - rc= ((PTDBDOX)tdbp)->Txfp->UpdateSortedRows(g); + } else if (tdbp->GetMode() == MODE_UPDATE && tdbp->IsIndexed()) + rc = ((PTDBDOX)tdbp)->Txfp->UpdateSortedRows(g); - switch(rc) { - case RC_FX: - abort= true; - break; - case RC_INFO: - PushWarning(g, tdbp); - break; - } // endswitch rc + switch (rc) { + case RC_FX: + abort = true; + break; + case RC_INFO: + PushWarning(g, tdbp); + break; + } // endswitch rc -#if defined(USE_TRY) try { -#else // !USE_TRY - // Prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - rc = RC_FX; - goto err; - } // endif + // This will close the table file(s) and also finalize write + // operations such as Insert, Update, or Delete. + tdbp->SetAbort(abort); + tdbp->CloseDB(g); + tdbp->SetAbort(false); - if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) { - rc = RC_FX; - goto err; - } // endif -#endif // !USE_TRY - - // This will close the table file(s) and also finalize write - // operations such as Insert, Update, or Delete. - tdbp->SetAbort(abort); - tdbp->CloseDB(g); - tdbp->SetAbort(false); - - if (trace > 1) - printf("Table %s closed\n", tdbp->GetName()); - - if (!nox && tdbp->GetMode() != MODE_READ && tdbp->GetMode() != MODE_ANY) { if (trace > 1) - printf("About to reset opt\n"); + printf("Table %s closed\n", tdbp->GetName()); - if (!tdbp->IsRemote()) { - // Make all the eventual indexes - PTDBDOX tbxp = (PTDBDOX)tdbp; - tbxp->ResetKindex(g, NULL); - tbxp->SetKey_Col(NULL); - rc = tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1); - } // endif remote + if (!nox && tdbp->GetMode() != MODE_READ && tdbp->GetMode() != MODE_ANY) { + if (trace > 1) + printf("About to reset opt\n"); - } // endif nox + if (!tdbp->IsRemote()) { + // Make all the eventual indexes + PTDBDOX tbxp = (PTDBDOX)tdbp; + tbxp->ResetKindex(g, NULL); + tbxp->SetKey_Col(NULL); + rc = tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1); + } // endif remote -#if defined(USE_TRY) -} catch (int) { - rc = RC_FX; -} catch (const char *msg) { - strcpy(g->Message, msg); - rc = RC_FX; -} // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY + } // endif nox - if (trace > 1) - htrc("Done rc=%d\n", rc); + } catch (int) { + rc = RC_FX; + } catch (const char *msg) { + strcpy(g->Message, msg); + rc = RC_FX; + } // end catch - return (rc == RC_OK || rc == RC_INFO) ? 0 : rc; - } // end of CntCloseTable + if (trace > 1) + htrc("Done rc=%d\n", rc); + + return (rc == RC_OK || rc == RC_INFO) ? 0 : rc; +} // end of CntCloseTable /***********************************************************************/ /* Load and initialize the use of an index. */ diff --git a/storage/connect/connect.h b/storage/connect/connect.h index ce4cf9bf8b9..128561b80f3 100644 --- a/storage/connect/connect.h +++ b/storage/connect/connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /**************** Cnt H Declares Source Code File (.H) *****************/ /* Name: CONNECT.H Version 2.4 */ diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp index 1622ec16c68..e24e10835c1 100644 --- a/storage/connect/domdoc.cpp +++ b/storage/connect/domdoc.cpp @@ -58,13 +58,15 @@ void CloseXMLFile(PGLOBAL g, PFBLOCK fp, bool all) if (xp && xp->Count > 1 && !all) { xp->Count--; } else if (xp && xp->Count > 0) { - try { + try { if (xp->Docp) xp->Docp->Release(); - } catch(_com_error e) { - sprintf(g->Message, "%s %s", MSG(COM_ERROR), e.Description()); - } catch(...) {} + } catch(_com_error e) { + char *p = _com_util::ConvertBSTRToString(e.Description()); + sprintf(g->Message, "%s %s", MSG(COM_ERROR), p); + delete[] p; + } catch(...) {} CoUninitialize(); xp->Count = 0; @@ -89,7 +91,7 @@ DOMDOC::DOMDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp) /******************************************************************/ /* Initialize XML parser and check library compatibility. */ /******************************************************************/ -bool DOMDOC::Initialize(PGLOBAL g, char *entry, bool zipped) +bool DOMDOC::Initialize(PGLOBAL g, PCSZ entry, bool zipped) { if (zipped && InitZip(g, entry)) return true; @@ -155,7 +157,7 @@ PFBLOCK DOMDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn) /******************************************************************/ /* Create the XML node. */ /******************************************************************/ -bool DOMDOC::NewDoc(PGLOBAL g, char *ver) +bool DOMDOC::NewDoc(PGLOBAL g, PCSZ ver) { char buf[64]; MSXML2::IXMLDOMProcessingInstructionPtr pip; @@ -490,9 +492,9 @@ PXATTR DOMNODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap) /******************************************************************/ /* Add a new element child node to this node and return it. */ /******************************************************************/ -PXNODE DOMNODE::AddChildNode(PGLOBAL g, char *name, PXNODE np) +PXNODE DOMNODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np) { - char *p, *pn; + const char *p, *pn; // char *p, *pn, *epf, *pf = NULL; MSXML2::IXMLDOMNodePtr ep; // _bstr_t uri((wchar_t*)NULL); @@ -585,7 +587,7 @@ PXATTR DOMNODE::AddProperty(PGLOBAL g, char *name, PXATTR ap) /******************************************************************/ /* Add a new text node to this node. */ /******************************************************************/ -void DOMNODE::AddText(PGLOBAL g, char *txtp) +void DOMNODE::AddText(PGLOBAL g, PCSZ txtp) { MSXML2::IXMLDOMTextPtr tp= Docp->createTextNode((_bstr_t)txtp); diff --git a/storage/connect/domdoc.h b/storage/connect/domdoc.h index 7f269002d59..dd8936097e2 100644 --- a/storage/connect/domdoc.h +++ b/storage/connect/domdoc.h @@ -37,9 +37,9 @@ class DOMDOC : public XMLDOCUMENT { virtual void SetNofree(bool b) {} // Only libxml2 // Methods - virtual bool Initialize(PGLOBAL g, char *entry, bool zipped); + virtual bool Initialize(PGLOBAL g, PCSZ entry, bool zipped); virtual bool ParseFile(PGLOBAL g, char *fn); - virtual bool NewDoc(PGLOBAL g, char *ver); + virtual bool NewDoc(PGLOBAL g, PCSZ ver); virtual void AddComment(PGLOBAL g, char *com); virtual PXNODE GetRoot(PGLOBAL g); virtual PXNODE NewRoot(PGLOBAL g, char *name); @@ -78,9 +78,9 @@ class DOMNODE : public XMLNODE { virtual PXLIST SelectNodes(PGLOBAL g, char *xp, PXLIST lp); virtual PXNODE SelectSingleNode(PGLOBAL g, char *xp, PXNODE np); virtual PXATTR GetAttribute(PGLOBAL g, char *name, PXATTR ap); - virtual PXNODE AddChildNode(PGLOBAL g, char *name, PXNODE np); + virtual PXNODE AddChildNode(PGLOBAL g, PCSZ name, PXNODE np); virtual PXATTR AddProperty(PGLOBAL g, char *name, PXATTR ap); - virtual void AddText(PGLOBAL g, char *txtp); + virtual void AddText(PGLOBAL g, PCSZ txtp); virtual void DeleteChild(PGLOBAL g, PXNODE dnp); protected: diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 9feb61d7d61..8878f2c922b 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -128,7 +128,7 @@ typedef struct _descriptor { /* Moves file pointer to byte 32; fills buffer at buf with */ /* first 32 bytes of file. */ /****************************************************************************/ -static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf) +static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf) { char endmark[2]; int dbc = 2, rc = RC_OK; @@ -186,7 +186,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf) /* DBFColumns: constructs the result blocks containing the description */ /* of all the columns of a DBF file that will be retrieved by #GetData. */ /****************************************************************************/ -PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info) +PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info) { int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; @@ -393,7 +393,7 @@ DBFBASE::DBFBASE(DBFBASE *txfp) /* and header length. Set Records, check that Reclen is equal to lrecl and */ /* return the header length or 0 in case of error. */ /****************************************************************************/ -int DBFBASE::ScanHeader(PGLOBAL g, PSZ fn, int lrecl, int *rln, char *defpath) +int DBFBASE::ScanHeader(PGLOBAL g, PCSZ fn, int lrecl, int *rln, PCSZ defpath) { int rc; char filename[_MAX_PATH]; diff --git a/storage/connect/filamdbf.h b/storage/connect/filamdbf.h index 66458a10eaa..640fc349b4c 100644 --- a/storage/connect/filamdbf.h +++ b/storage/connect/filamdbf.h @@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM; /****************************************************************************/ /* Functions used externally. */ /****************************************************************************/ -PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info); +PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info); /****************************************************************************/ /* This is the base class for dBASE file access methods. */ @@ -31,7 +31,7 @@ class DllExport DBFBASE { DBFBASE(PDBF txfp); // Implementation - int ScanHeader(PGLOBAL g, PSZ fname, int lrecl, int *rlen, char *defpath); + int ScanHeader(PGLOBAL g, PCSZ fname, int lrecl, int *rlen, PCSZ defpath); protected: // Default constructor, not to be used diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp index cd25429318a..962a4516bf2 100644 --- a/storage/connect/filamfix.cpp +++ b/storage/connect/filamfix.cpp @@ -761,7 +761,8 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) htrc("after write req=%d brc=%d nbw=%d\n", req, brc, nbw); if (!brc || nbw != len) { - char buf[256], *fn = (h == Hfile) ? To_File : "Tempfile"; + char buf[256]; + PCSZ fn = (h == Hfile) ? To_File : "Tempfile"; if (brc) strcpy(buf, MSG(BAD_BYTE_NUM)); diff --git a/storage/connect/filamgz.cpp b/storage/connect/filamgz.cpp index dc6f277ee27..df366ef15f9 100644 --- a/storage/connect/filamgz.cpp +++ b/storage/connect/filamgz.cpp @@ -920,8 +920,8 @@ int ZLBFAM::GetFileLength(PGLOBAL g) /***********************************************************************/ bool ZLBFAM::AllocateBuffer(PGLOBAL g) { - char *msg; - int n, zrc; + PCSZ msg; + int n, zrc; #if 0 if (!Optimized && Tdbp->NeedIndexing(g)) { diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp index 99b51632dc9..382af51aae4 100644 --- a/storage/connect/filamtxt.cpp +++ b/storage/connect/filamtxt.cpp @@ -71,8 +71,23 @@ TXTFAM::TXTFAM(PDOSDEF tdp) { Tdbp = NULL; To_Fb = NULL; - To_File = tdp->Fn; - Lrecl = tdp->Lrecl; + + if (tdp) { + To_File = tdp->Fn; + Lrecl = tdp->Lrecl; + Eof = tdp->Eof; + Ending = tdp->Ending; + } else { + To_File = NULL; + Lrecl = 0; + Eof = false; +#if defined(__WIN__) + Ending = 2; +#else + Ending = 1; +#endif + } // endif tdp + Placed = false; IsRead = true; Blocked = false; @@ -103,8 +118,6 @@ TXTFAM::TXTFAM(PDOSDEF tdp) Blksize = 0; Fpos = Spos = Tpos = 0; Padded = false; - Eof = tdp->Eof; - Ending = tdp->Ending; Abort = false; CrLf = (char*)(Ending == 1 ? "\n" : "\r\n"); } // end of TXTFAM standard constructor @@ -973,7 +986,7 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc) } else { /*****************************************************************/ - /* Move of eventual preceding lines is not required here. */ + /* Move of eventual preceding lines is not required here. */ /* Set the target file as being the source file itself. */ /* Set the future Tpos, and give Spos a value to block copying. */ /*****************************************************************/ @@ -1161,20 +1174,12 @@ int DOSFAM::RenameTempFile(PGLOBAL g) if (rename(filename, filetemp)) { // Save file for security sprintf(g->Message, MSG(RENAME_ERROR), filename, filetemp, strerror(errno)); -#if defined(USE_TRY) throw 51; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 51); -#endif // !USE_TRY } else if (rename(tempname, filename)) { sprintf(g->Message, MSG(RENAME_ERROR), tempname, filename, strerror(errno)); rc = rename(filetemp, filename); // Restore saved file -#if defined(USE_TRY) throw 52; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 52); -#endif // !USE_TRY } else if (remove(filetemp)) { sprintf(g->Message, MSG(REMOVE_ERROR), filetemp, strerror(errno)); diff --git a/storage/connect/filamtxt.h b/storage/connect/filamtxt.h index ae8f74a9830..1fdae8fcd37 100644 --- a/storage/connect/filamtxt.h +++ b/storage/connect/filamtxt.h @@ -80,7 +80,7 @@ class DllExport TXTFAM : public BLOCK { protected: // Members PTDBDOS Tdbp; // To table class - PSZ To_File; // Points to table file name + PCSZ To_File; // Points to table file name PFBLOCK To_Fb; // Pointer to file block PPARM To_Pos; // Pointer to position list PPARM To_Sos; // Pointer to start position list diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp index 8e5c31d6b49..9b4ef43eb8b 100755 --- a/storage/connect/filamvct.cpp +++ b/storage/connect/filamvct.cpp @@ -143,9 +143,9 @@ int VCTFAM::GetFileLength(PGLOBAL g) { if (Split) { // Get the total file length - char filename[_MAX_PATH]; - char *savfile = To_File; - int i, len = 0; + char filename[_MAX_PATH]; + PCSZ savfile = To_File; + int i, len = 0; // Initialize the array of file structures if (!Colfn) { @@ -313,8 +313,8 @@ int VCTFAM::Cardinality(PGLOBAL g) // and Last must be set from the file cardinality. // Only happens when called by sub classes. char filename[_MAX_PATH]; - PSZ savfn = To_File; - int len, clen, card = -1; + PCSZ savfn = To_File; + int len, clen, card = -1; PCOLDEF cdp = Tdbp->GetDef()->GetCols(); if (!Colfn) { @@ -368,7 +368,7 @@ int VCTFAM::GetRowID(void) /***********************************************************************/ /* VCT Create an empty file for Vector formatted tables. */ /***********************************************************************/ -bool VCTFAM::MakeEmptyFile(PGLOBAL g, char *fn) +bool VCTFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn) { // Vector formatted file: this will create an empty file of the // required length if it does not exists yet. @@ -559,7 +559,7 @@ bool VCTFAM::AllocateBuffer(PGLOBAL g) /* Do initial action when inserting. */ /***********************************************************************/ bool VCTFAM::InitInsert(PGLOBAL g) - { +{ bool rc = false; // We come here in MODE_INSERT only @@ -575,26 +575,11 @@ bool VCTFAM::InitInsert(PGLOBAL g) CurBlk = Block - 1; CurNum = Last; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return true; - } // endif + // Last block must be updated by new values + for (; cp; cp = (PVCTCOL)cp->Next) + cp->ReadBlock(g); - if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) { - g->jump_level--; - return true; - } // endif -#endif // !USE_TRY - - // Last block must be updated by new values - for (; cp; cp = (PVCTCOL)cp->Next) - cp->ReadBlock(g); - -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -603,9 +588,7 @@ bool VCTFAM::InitInsert(PGLOBAL g) strcpy(g->Message, msg); rc = true; } // end catch -#else // !USE_TRY - g->jump_level--; -#endif // !USE_TRY + } // endif Last if (!rc) @@ -897,8 +880,9 @@ int VCTFAM::DeleteRecords(PGLOBAL g, int irc) /***********************************************************************/ bool VCTFAM::OpenTempFile(PGLOBAL g) { - char *opmode, tempname[_MAX_PATH]; - bool rc = false; + PCSZ opmode; + char tempname[_MAX_PATH]; + bool rc = false; /*********************************************************************/ /* Open the temporary file, Spos is at the beginning of file. */ @@ -1126,11 +1110,7 @@ void VCTFAM::CloseTableFile(PGLOBAL g, bool abort) } else if (AddBlock) { // Last block was not written rc = ResetTableSize(g, CurBlk, Nrec); -#if defined(USE_TRY) throw 44; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 44); -#endif // !USE_TRY } // endif } else if (mode == MODE_UPDATE) { @@ -1550,7 +1530,7 @@ bool VCMFAM::AllocateBuffer(PGLOBAL g) /* Do initial action when inserting. */ /***********************************************************************/ bool VCMFAM::InitInsert(PGLOBAL g) - { +{ bool rc = false; volatile PVCTCOL cp = (PVCTCOL)Tdbp->GetColumns(); @@ -1565,27 +1545,12 @@ bool VCMFAM::InitInsert(PGLOBAL g) CurNum = Last; } // endif Last -#if defined(USE_TRY) try { -#else // !USE_TRY - // Prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return true; - } // endif + // Initialize the column block pointer + for (; cp; cp = (PVCTCOL)cp->Next) + cp->ReadBlock(g); - if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) { - g->jump_level--; - return true; - } // endif -#endif // !USE_TRY - - // Initialize the column block pointer - for (; cp; cp = (PVCTCOL)cp->Next) - cp->ReadBlock(g); - -#if defined(USE_TRY) - } catch (int n) { + } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); rc = true; @@ -1593,11 +1558,9 @@ bool VCMFAM::InitInsert(PGLOBAL g) strcpy(g->Message, msg); rc = true; } // end catch -#else // !USE_TRY - g->jump_level--; -#endif // !USE_TRY + return rc; - } // end of InitInsert +} // end of InitInsert /***********************************************************************/ /* Data Base write routine for VMP access method. */ @@ -2036,7 +1999,7 @@ bool VECFAM::OpenTableFile(PGLOBAL g) /***********************************************************************/ /* Open the file corresponding to one column. */ /***********************************************************************/ -bool VECFAM::OpenColumnFile(PGLOBAL g, char *opmode, int i) +bool VECFAM::OpenColumnFile(PGLOBAL g, PCSZ opmode, int i) { char filename[_MAX_PATH]; PDBUSER dup = PlgGetUser(g); @@ -2541,11 +2504,7 @@ void VECFAM::CloseTableFile(PGLOBAL g, bool abort) if (wrc != RC_FX) rc = ResetTableSize(g, Block, Last); else -#if defined(USE_TRY) throw 44; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 44); -#endif // !USE_TRY } else if (mode == MODE_UPDATE) { if (UseTemp && !InitUpdate && !Abort) { @@ -3185,7 +3144,8 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) htrc("after write req=%d brc=%d nbw=%d\n", req, brc, nbw); if (!brc || nbw != len) { - char buf[256], *fn = (h == Hfile) ? To_File : "Tempfile"; + char buf[256]; + PCSZ fn = (h == Hfile) ? To_File : "Tempfile"; if (brc) strcpy(buf, MSG(BAD_BYTE_NUM)); @@ -3361,7 +3321,7 @@ bool BGVFAM::SetBlockInfo(PGLOBAL g) /***********************************************************************/ /* VEC Create an empty file for new Vector formatted tables. */ /***********************************************************************/ -bool BGVFAM::MakeEmptyFile(PGLOBAL g, char *fn) +bool BGVFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn) { // Vector formatted file this will create an empty file of the // required length if it does not exists yet. @@ -3371,7 +3331,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, char *fn) PlugSetPath(filename, fn, Tdbp->GetPath()); #if defined(__WIN__) - char *p; + PCSZ p; DWORD rc; bool brc; LARGE_INTEGER of; @@ -4206,11 +4166,7 @@ void BGVFAM::CloseTableFile(PGLOBAL g, bool abort) } else if (AddBlock) { // Last block was not written rc = ResetTableSize(g, CurBlk, Nrec); -#if defined(USE_TRY) throw 44; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 44); -#endif // !USE_TRY } // endif } else if (mode == MODE_UPDATE) { diff --git a/storage/connect/filamvct.h b/storage/connect/filamvct.h index be66232acfb..85982403270 100644 --- a/storage/connect/filamvct.h +++ b/storage/connect/filamvct.h @@ -61,7 +61,7 @@ class DllExport VCTFAM : public FIXFAM { virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp); protected: - virtual bool MakeEmptyFile(PGLOBAL g, char *fn); + virtual bool MakeEmptyFile(PGLOBAL g, PCSZ fn); virtual bool OpenTempFile(PGLOBAL g); virtual bool MoveLines(PGLOBAL g) {return false;} virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL); @@ -160,7 +160,7 @@ class DllExport VECFAM : public VCTFAM { virtual bool MoveLines(PGLOBAL g); virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL); virtual int RenameTempFile(PGLOBAL g); - bool OpenColumnFile(PGLOBAL g, char *opmode, int i); + bool OpenColumnFile(PGLOBAL g, PCSZ opmode, int i); // Members FILE* *Streams; // Points to Dos file structure array @@ -235,7 +235,7 @@ class BGVFAM : public VCTFAM { bool BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, bool b = false); bool BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req); bool BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req); - virtual bool MakeEmptyFile(PGLOBAL g, char *fn); + virtual bool MakeEmptyFile(PGLOBAL g, PCSZ fn); virtual bool OpenTempFile(PGLOBAL g); virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL); virtual bool CleanUnusedSpace(PGLOBAL g); diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 92de5117638..81511214bfe 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -45,12 +45,12 @@ #define WRITEBUFFERSIZE (16384) -bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool mul); +bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul); /***********************************************************************/ /* Compress a file in zip when creating a table. */ /***********************************************************************/ -static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, char *fn, char *entry, char *buf) +static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, PCSZ fn, PCSZ entry, char *buf) { int rc = RC_OK, size_read, size_buf = WRITEBUFFERSIZE; FILE *fin; @@ -88,7 +88,7 @@ static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, char *fn, char *entry, char *buf) /***********************************************************************/ /* Find and Compress several files in zip when creating a table. */ /***********************************************************************/ -static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, char *pat, char *buf) +static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) { char filename[_MAX_PATH]; int rc; @@ -203,7 +203,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, char *pat, char *buf) /***********************************************************************/ /* Load and Compress a file in zip when creating a table. */ /***********************************************************************/ -bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool mul) +bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul) { char *buf; bool err; @@ -228,7 +228,7 @@ bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool /***********************************************************************/ /* Constructors. */ /***********************************************************************/ -ZIPUTIL::ZIPUTIL(PSZ tgt) +ZIPUTIL::ZIPUTIL(PCSZ tgt) { zipfile = NULL; target = tgt; @@ -269,7 +269,7 @@ void ZIPUTIL::getTime(tm_zip& tmZip) /* append: set true to append the zip file */ /* return: true if open, false otherwise. */ /***********************************************************************/ -bool ZIPUTIL::open(PGLOBAL g, char *filename, bool append) +bool ZIPUTIL::open(PGLOBAL g, PCSZ filename, bool append) { if (!zipfile && !(zipfile = zipOpen64(filename, append ? APPEND_STATUS_ADDINZIP @@ -295,7 +295,7 @@ void ZIPUTIL::close() /***********************************************************************/ /* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ /***********************************************************************/ -bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn, bool append) +bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, PCSZ fn, bool append) { /*********************************************************************/ /* The file will be compressed. */ @@ -338,7 +338,7 @@ bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn, bool append) /***********************************************************************/ /* Add target in zip file. */ /***********************************************************************/ -bool ZIPUTIL::addEntry(PGLOBAL g, char *entry) +bool ZIPUTIL::addEntry(PGLOBAL g, PCSZ entry) { //?? we dont need the stinking time zip_fileinfo zi = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -382,7 +382,7 @@ void ZIPUTIL::closeEntry() /***********************************************************************/ /* Constructors. */ /***********************************************************************/ -UNZIPUTL::UNZIPUTL(PSZ tgt, bool mul) +UNZIPUTL::UNZIPUTL(PCSZ tgt, bool mul) { zipfile = NULL; target = tgt; @@ -439,8 +439,8 @@ UNZIPUTL::UNZIPUTL(PZIPUTIL zutp) /* This code is the copyright property of Alessandro Felice Cantatore. */ /* http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html */ /***********************************************************************/ -bool UNZIPUTL::WildMatch(PSZ pat, PSZ str) { - PSZ s, p; +bool UNZIPUTL::WildMatch(PCSZ pat, PCSZ str) { + PCSZ s, p; bool star = FALSE; loopStart: @@ -474,7 +474,7 @@ starCheck: /* param: filename path and the filename of the zip file to open. */ /* return: true if open, false otherwise. */ /***********************************************************************/ -bool UNZIPUTL::open(PGLOBAL g, char *filename) +bool UNZIPUTL::open(PGLOBAL g, PCSZ filename) { if (!zipfile && !(zipfile = unzOpen64(filename))) sprintf(g->Message, "Zipfile open error on %s", filename); @@ -564,7 +564,7 @@ int UNZIPUTL::nextEntry(PGLOBAL g) /***********************************************************************/ /* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ /***********************************************************************/ -bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn) +bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, PCSZ fn) { /*********************************************************************/ /* The file will be decompressed into virtual memory. */ @@ -602,7 +602,7 @@ bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn) if (openEntry(g)) return true; - if (size > 0) { + if (size > 0) { /*******************************************************************/ /* Link a Fblock. This make possible to automatically close it */ /* in case of error g->jump. */ @@ -636,7 +636,7 @@ bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn) /***********************************************************************/ /* Insert only if the entry does not exist. */ /***********************************************************************/ -bool UNZIPUTL::IsInsertOk(PGLOBAL g, char *fn) +bool UNZIPUTL::IsInsertOk(PGLOBAL g, PCSZ fn) { bool ok = true, b = open(g, fn); diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h index ba1d8658dc4..be17d954728 100644 --- a/storage/connect/filamzip.h +++ b/storage/connect/filamzip.h @@ -27,16 +27,13 @@ typedef class ZPXFAM *PZPXFAM; class DllExport ZIPUTIL : public BLOCK { public: // Constructor - ZIPUTIL(PSZ tgt); + ZIPUTIL(PCSZ tgt); //ZIPUTIL(ZIPUTIL *zutp); - // Implementation - //PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UNZFAM(this); } - // Methods - bool OpenTable(PGLOBAL g, MODE mode, char *fn, bool append); - bool open(PGLOBAL g, char *fn, bool append); - bool addEntry(PGLOBAL g, char *entry); + bool OpenTable(PGLOBAL g, MODE mode, PCSZ fn, bool append); + bool open(PGLOBAL g, PCSZ fn, bool append); + bool addEntry(PGLOBAL g, PCSZ entry); void close(void); void closeEntry(void); int writeEntry(PGLOBAL g, char *buf, int len); @@ -44,16 +41,10 @@ class DllExport ZIPUTIL : public BLOCK { // Members zipFile zipfile; // The ZIP container file - PSZ target; // The target file name - PSZ pwd; // The ZIP file password -//unz_file_info finfo; // The current file info + PCSZ target; // The target file name + PCSZ pwd; // The ZIP file password PFBLOCK fp; -//char *memory; -//uint size; -//int multiple; // Multiple targets bool entryopen; // True when open current entry -//char fn[FILENAME_MAX]; // The current entry file name -//char mapCaseTable[256]; }; // end of ZIPUTIL /***********************************************************************/ @@ -62,27 +53,27 @@ class DllExport ZIPUTIL : public BLOCK { class DllExport UNZIPUTL : public BLOCK { public: // Constructor - UNZIPUTL(PSZ tgt, bool mul); + UNZIPUTL(PCSZ tgt, bool mul); UNZIPUTL(PDOSDEF tdp); // Implementation //PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UNZFAM(this); } // Methods - bool OpenTable(PGLOBAL g, MODE mode, char *fn); - bool open(PGLOBAL g, char *fn); + bool OpenTable(PGLOBAL g, MODE mode, PCSZ fn); + bool open(PGLOBAL g, PCSZ fn); bool openEntry(PGLOBAL g); void close(void); void closeEntry(void); - bool WildMatch(PSZ pat, PSZ str); + bool WildMatch(PCSZ pat, PCSZ str); int findEntry(PGLOBAL g, bool next); int nextEntry(PGLOBAL g); - bool IsInsertOk(PGLOBAL g, char *fn); + bool IsInsertOk(PGLOBAL g, PCSZ fn); // Members unzFile zipfile; // The ZIP container file - PSZ target; // The target file name - PSZ pwd; // The ZIP file password + PCSZ target; // The target file name + PCSZ pwd; // The ZIP file password unz_file_info finfo; // The current file info PFBLOCK fp; char *memory; @@ -123,8 +114,6 @@ class DllExport UNZFAM : public MAPFAM { // Members UNZIPUTL *zutp; PDOSDEF tdfp; -//PSZ target; -//bool mul; }; // end of UNZFAM /***********************************************************************/ @@ -152,8 +141,6 @@ class DllExport UZXFAM : public MPXFAM { // Members UNZIPUTL *zutp; PDOSDEF tdfp; -//PSZ target; -//bool mul; }; // end of UZXFAM /***********************************************************************/ @@ -180,8 +167,9 @@ class DllExport ZIPFAM : public DOSFAM { protected: // Members ZIPUTIL *zutp; - PSZ target; + PCSZ target; bool append; +//bool replace; }; // end of ZIPFAM /***********************************************************************/ @@ -205,7 +193,7 @@ class DllExport ZPXFAM : public FIXFAM { protected: // Members ZIPUTIL *zutp; - PSZ target; + PCSZ target; bool append; }; // end of ZPXFAM diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp index db96647f634..0c38d10a578 100644 --- a/storage/connect/filter.cpp +++ b/storage/connect/filter.cpp @@ -87,11 +87,7 @@ BYTE OpBmp(PGLOBAL g, OPVAL opc) case OP_EXIST: bt = 0x00; break; default: sprintf(g->Message, MSG(BAD_FILTER_OP), opc); -#if defined(USE_TRY) throw TYPE_ARRAY; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_ARRAY); -#endif // !USE_TRY } // endswitch opc return bt; @@ -1715,11 +1711,7 @@ PFIL PrepareFilter(PGLOBAL g, PFIL fp, bool having) break; // Remove eventual ending separator(s) // if (fp->Convert(g, having)) -//#if defined(USE_TRY) // throw TYPE_ARRAY; -//#else // !USE_TRY -// longjmp(g->jumper[g->jump_level], TYPE_FILTER); -//#endif // !USE_TRY filp = fp; fp = fp->Next; @@ -1752,11 +1744,7 @@ DllExport bool ApplyFilter(PGLOBAL g, PFIL filp) // return TRUE; if (filp->Eval(g)) -#if defined(USE_TRY) throw TYPE_FILTER; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_FILTER); -#endif // !USE_TRY if (trace > 1) htrc("PlugFilter filp=%p result=%d\n", diff --git a/storage/connect/filter.h b/storage/connect/filter.h index 15730e2cc44..f4835d23a7c 100644 --- a/storage/connect/filter.h +++ b/storage/connect/filter.h @@ -61,7 +61,7 @@ class DllExport FILTER : public XOBJECT { /* Filter description block */ //virtual PXOB CheckSubQuery(PGLOBAL, PSQL); //virtual bool CheckLocal(PTDB); //virtual int CheckSpcCol(PTDB tdbp, int n); - virtual void Print(PGLOBAL g, FILE *f, uint n); + virtual void Print(PGLOBAL g, FILE *f, uint n); virtual void Print(PGLOBAL g, char *ps, uint z); // PFIL Linearize(bool nosep); // PFIL Link(PGLOBAL g, PFIL fil2); diff --git a/storage/connect/global.h b/storage/connect/global.h index 5579e8bd248..a2030fdb5d0 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -59,7 +59,7 @@ #define NO_IVAL -95684275 /* Used by GetIntegerOption */ #define VMLANG 370 /* Size of olf VM lang blocks */ #define MAX_JUMP 24 /* Maximum jump level number */ -#define MAX_STR 1024 /* Maximum string length */ +#define MAX_STR 4160 /* Maximum message length */ #define STR_SIZE 501 /* Length of char strings. */ #define STD_INPUT 0 /* Standard language input */ #define STD_OUTPUT 1 /* Standard language output */ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 5245b2559c5..240625d03fb 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /** @file ha_connect.cc @@ -172,9 +172,9 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.05.0003 March 7, 2017"; + char version[]= "Version 1.06.0001 April 17, 2017"; #if defined(__WIN__) - char compver[]= "Version 1.05.0003 " __DATE__ " " __TIME__; + char compver[]= "Version 1.06.0001 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -209,14 +209,15 @@ pthread_mutex_t parmut = PTHREAD_MUTEX_INITIALIZER; /***********************************************************************/ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); PQRYRES VirColumns(PGLOBAL g, bool info); -PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info); +PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info); PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info); int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v); void PushWarning(PGLOBAL g, THD *thd, int level); -bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host, - const char *db, char *tab, const char *src, int port); -bool ZipLoadFile(PGLOBAL, char*, char*, char*, bool, bool); +bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, PCSZ db, + PCSZ tab, PCSZ src, int port); +bool ZipLoadFile(PGLOBAL, PCSZ, PCSZ, PCSZ, bool, bool); bool ExactInfo(void); +void mongo_init(bool); USETEMP UseTemp(void); int GetConvSize(void); TYPCONV GetTypeConv(void); @@ -670,7 +671,7 @@ static int connect_init_func(void *p) sql_print_information("CONNECT: %s", version); #endif // !__WIN__ -#ifdef LIBXML2_SUPPORT +#if defined(LIBXML2_SUPPORT) XmlInitParserLib(); #endif // LIBXML2_SUPPORT @@ -1018,15 +1019,14 @@ ulonglong ha_connect::table_flags() const /****************************************************************************/ /* Return the value of an option specified in an option list. */ /****************************************************************************/ -char *GetListOption(PGLOBAL g, const char *opname, - const char *oplist, const char *def) +PCSZ GetListOption(PGLOBAL g, PCSZ opname, PCSZ oplist, PCSZ def) { if (!oplist) return (char*)def; char key[16], val[256]; char *pk, *pv, *pn; - char *opval= (char*)def; + PCSZ opval= def; int n; for (pk= (char*)oplist; pk; pk= ++pn) { @@ -1062,9 +1062,9 @@ char *GetListOption(PGLOBAL g, const char *opname, /****************************************************************************/ /* Return the value of a string option or NULL if not specified. */ /****************************************************************************/ -char *GetStringTableOption(PGLOBAL g, PTOS options, char *opname, char *sdef) +PCSZ GetStringTableOption(PGLOBAL g, PTOS options, PCSZ opname, PCSZ sdef) { - const char *opval= NULL; + PCSZ opval= NULL; if (!options) return sdef; @@ -1107,10 +1107,10 @@ char *GetStringTableOption(PGLOBAL g, PTOS options, char *opname, char *sdef) /****************************************************************************/ /* Return the value of a Boolean option or bdef if not specified. */ /****************************************************************************/ -bool GetBooleanTableOption(PGLOBAL g, PTOS options, char *opname, bool bdef) +bool GetBooleanTableOption(PGLOBAL g, PTOS options, PCSZ opname, bool bdef) { - bool opval= bdef; - char *pv; + bool opval= bdef; + PCSZ pv; if (!options) return bdef; @@ -1138,7 +1138,7 @@ bool GetBooleanTableOption(PGLOBAL g, PTOS options, char *opname, bool bdef) /****************************************************************************/ /* Return the value of an integer option or NO_IVAL if not specified. */ /****************************************************************************/ -int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef) +int GetIntegerTableOption(PGLOBAL g, PTOS options, PCSZ opname, int idef) { ulonglong opval= (ulonglong) NO_IVAL; @@ -1160,10 +1160,10 @@ int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef) opval= (options->compressed); if ((ulonglong) opval == (ulonglong)NO_IVAL) { - char *pv; + PCSZ pv; if ((pv= GetListOption(g, opname, options->oplist))) - opval= CharToNumber(pv, strlen(pv), ULONGLONG_MAX, true); + opval= CharToNumber((char*)pv, strlen(pv), ULONGLONG_MAX, true); else return idef; @@ -1188,7 +1188,7 @@ PTOS ha_connect::GetTableOptionStruct(TABLE_SHARE *s) /****************************************************************************/ /* Return the string eventually formatted with partition name. */ /****************************************************************************/ -char *ha_connect::GetRealString(const char *s) +char *ha_connect::GetRealString(PCSZ s) { char *sv; @@ -1205,10 +1205,10 @@ char *ha_connect::GetRealString(const char *s) /****************************************************************************/ /* Return the value of a string option or sdef if not specified. */ /****************************************************************************/ -char *ha_connect::GetStringOption(char *opname, char *sdef) +PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef) { - char *opval= NULL; - PTOS options= GetTableOptionStruct(); + PCSZ opval= NULL; + PTOS options= GetTableOptionStruct(); if (!stricmp(opname, "Connect")) { LEX_STRING cnc= (tshp) ? tshp->connect_string @@ -1267,7 +1267,7 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) /****************************************************************************/ /* Return the value of a Boolean option or bdef if not specified. */ /****************************************************************************/ -bool ha_connect::GetBooleanOption(char *opname, bool bdef) +bool ha_connect::GetBooleanOption(PCSZ opname, bool bdef) { bool opval; PTOS options= GetTableOptionStruct(); @@ -1284,7 +1284,7 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef) /* Set the value of the opname option (does not work for oplist options) */ /* Currently used only to set the Sepindex value. */ /****************************************************************************/ -bool ha_connect::SetBooleanOption(char *opname, bool b) +bool ha_connect::SetBooleanOption(PCSZ opname, bool b) { PTOS options= GetTableOptionStruct(); @@ -1302,7 +1302,7 @@ bool ha_connect::SetBooleanOption(char *opname, bool b) /****************************************************************************/ /* Return the value of an integer option or NO_IVAL if not specified. */ /****************************************************************************/ -int ha_connect::GetIntegerOption(char *opname) +int ha_connect::GetIntegerOption(PCSZ opname) { int opval; PTOS options= GetTableOptionStruct(); @@ -1322,7 +1322,7 @@ int ha_connect::GetIntegerOption(char *opname) /* Set the value of the opname option (does not work for oplist options) */ /* Currently used only to set the Lrecl value. */ /****************************************************************************/ -bool ha_connect::SetIntegerOption(char *opname, int n) +bool ha_connect::SetIntegerOption(PCSZ opname, int n) { PTOS options= GetTableOptionStruct(); @@ -1522,7 +1522,7 @@ PXOS ha_connect::GetIndexOptionStruct(KEY *kp) /****************************************************************************/ /* Return a Boolean index option or false if not specified. */ /****************************************************************************/ -bool ha_connect::GetIndexOption(KEY *kp, char *opname) +bool ha_connect::GetIndexOption(KEY *kp, PCSZ opname) { bool opval= false; PXOS options= GetIndexOptionStruct(kp); @@ -1534,7 +1534,7 @@ bool ha_connect::GetIndexOption(KEY *kp, char *opname) opval= options->mapped; } else if (kp->comment.str && kp->comment.length) { - char *pv, *oplist= strz(xp->g, kp->comment); + PCSZ pv, oplist= strz(xp->g, kp->comment); if ((pv= GetListOption(xp->g, opname, oplist))) opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0); @@ -1739,9 +1739,9 @@ void ha_connect::AddColName(char *cp, Field *fp) /***********************************************************************/ /* This function sets the current database path. */ /***********************************************************************/ -bool ha_connect::SetDataPath(PGLOBAL g, const char *path) +bool ha_connect::SetDataPath(PGLOBAL g, const char *path) { - return (!(datapath = SetPath(g, path))); + return (!(datapath= SetPath(g, path))); } // end of SetDataPath /****************************************************************************/ @@ -1901,41 +1901,21 @@ bool ha_connect::CheckColumnList(PGLOBAL g) Field* fp; MY_BITMAP *map= table->read_set; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return true; - } // endif jump_level - - if (!setjmp(g->jumper[++g->jump_level])) { -#endif // !USE_TRY for (field= table->field; fp= *field; field++) if (bitmap_is_set(map, fp->field_index)) { if (!(colp= tdbp->ColDB(g, (PSZ)fp->field_name, 0))) { sprintf(g->Message, "Column %s not found in %s", fp->field_name, tdbp->GetName()); -#if defined(USE_TRY) throw 1; -#else // !USE_TRY - brc = true; - goto fin; -#endif // !USE_TRY } // endif colp if ((brc= colp->InitValue(g))) -#if defined(USE_TRY) throw 2; -#else // !USE_TRY - goto fin; -#endif // !USE_TRY colp->AddColUse(U_P); // For PLG tables } // endif -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -1944,13 +1924,7 @@ bool ha_connect::CheckColumnList(PGLOBAL g) strcpy(g->Message, msg); brc = true; } // end catch -#else // !USE_TRY - } else - brc = true; - fin: - g->jump_level--; -#endif // !USE_TRY return brc; } // end of CheckColumnList @@ -1987,7 +1961,8 @@ int ha_connect::CloseTable(PGLOBAL g) /***********************************************************************/ int ha_connect::MakeRecord(char *buf) { - char *p, *fmt, val[32]; + PCSZ fmt; + char *p, val[32]; int rc= 0; Field* *field; Field *fp; @@ -2123,7 +2098,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *) { char attr_buffer[1024]; char data_buffer[1024]; - char *fmt; + PCSZ fmt; int rc= 0; PCOL colp; PVAL value, sdvalin; @@ -2297,7 +2272,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, const uchar *ptr; //uint i, rem, len, klen, stlen; uint i, rem, len, stlen; - bool nq, both, oom= false; + bool nq, both, oom; OPVAL op; Field *fp; const key_range *ranges[2]; @@ -2325,9 +2300,9 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, continue; if (both && i > 0) - oom|= qry->Append(") AND ("); + qry->Append(") AND ("); else - oom|= qry->Append(" WHERE ("); + qry->Append(" WHERE ("); // klen= len= ranges[i]->length; len= ranges[i]->length; @@ -2340,14 +2315,14 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, nq= fp->str_needs_quotes(); if (kpart != kfp->key_part) - oom|= qry->Append(" AND "); + qry->Append(" AND "); if (q) { - oom|= qry->Append(q); - oom|= qry->Append((PSZ)fp->field_name); - oom|= qry->Append(q); + qry->Append(q); + qry->Append((PSZ)fp->field_name); + qry->Append(q); } else - oom|= qry->Append((PSZ)fp->field_name); + qry->Append((PSZ)fp->field_name); switch (ranges[i]->flag) { case HA_READ_KEY_EXACT: @@ -2372,10 +2347,10 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, goto err; } // endswitch flag - oom|= qry->Append((PSZ)GetValStr(op, false)); + qry->Append((PSZ)GetValStr(op, false)); if (nq) - oom|= qry->Append('\''); + qry->Append('\''); if (kpart->key_part_flag & HA_VAR_LENGTH_PART) { String varchar; @@ -2383,17 +2358,17 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, varchar.set_quick((char*)ptr + HA_KEY_BLOB_LENGTH, var_length, &my_charset_bin); - oom|= qry->Append(varchar.ptr(), varchar.length(), nq); + qry->Append(varchar.ptr(), varchar.length(), nq); } else { char strbuff[MAX_FIELD_WIDTH]; String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res; res= fp->val_str(&str, ptr); - oom|= qry->Append(res->ptr(), res->length(), nq); + qry->Append(res->ptr(), res->length(), nq); } // endif flag if (nq) - oom |= qry->Append('\''); + qry->Append('\''); if (stlen >= len) break; @@ -2408,7 +2383,9 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, } // endfor i - if ((oom|= qry->Append(")"))) + qry->Append(')'); + + if ((oom= qry->IsTruncated())) strcpy(g->Message, "Out of memory"); dbug_tmp_restore_column_map(table->write_set, old_map); @@ -2722,7 +2699,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (x) return NULL; else - pb0 = pb1 = pb2 = ph0 = ph1 = ph2 = NULL; + pb0= pb1= pb2= ph0= ph1= ph2= NULL; if (trace) htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(), @@ -3086,59 +3063,56 @@ const COND *ha_connect::cond_push(const COND *cond) tty == TYPE_AM_PLG || tty == TYPE_AM_JDBC || x); // This should never happen but is done to avoid crashing -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - DBUG_RETURN(cond); - } // endif jump_level + if (b) { + PCFIL filp; + int rc; - if (setjmp(g->jumper[++g->jump_level])) - goto fin; -#endif // !USE_TRY + if ((filp = tdbp->GetCondFil()) && tdbp->GetCond() == cond && + filp->Idx == active_index && filp->Type == tty) + goto fin; - if (b) { - PCFIL filp; - int rc; + filp = new(g) CONDFIL(active_index, tty); + rc = filp->Init(g, this); - if ((filp= tdbp->GetCondFil()) && filp->Cond == cond && - filp->Idx == active_index && filp->Type == tty) - goto fin; + if (rc == RC_INFO) { + filp->Having = (char*)PlugSubAlloc(g, NULL, 256); + *filp->Having = 0; + } else if (rc == RC_FX) + goto fin; - filp= new(g) CONDFIL(cond, active_index, tty); - rc = filp->Init(g, this); + filp->Body = (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0); + *filp->Body = 0; - if (rc == RC_INFO) { - filp->Having = (char*)PlugSubAlloc(g, NULL, 256); - *filp->Having = 0; - } else if (rc == RC_FX) - goto fin; + if (CheckCond(g, filp, cond)) { + if (filp->Having && strlen(filp->Having) > 255) + goto fin; // Memory collapse - filp->Body = (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0); - *filp->Body = 0; + if (trace) + htrc("cond_push: %s\n", filp->Body); - if (CheckCond(g, filp, cond)) { - if (filp->Having && strlen(filp->Having) > 255) - goto fin; // Memory collapse + tdbp->SetCond(cond); - if (trace) - htrc("cond_push: %s\n", filp->Body); + if (!x) + PlugSubAlloc(g, NULL, strlen(filp->Body) + 1); + else + cond = NULL; // Does this work? - if (!x) - PlugSubAlloc(g, NULL, strlen(filp->Body) + 1); - else - cond= NULL; // Does this work? + tdbp->SetCondFil(filp); + } else if (x && cond) + tdbp->SetCondFil(filp); // Wrong filter - tdbp->SetCondFil(filp); - } else if (x && cond) - tdbp->SetCondFil(filp); // Wrong filter + } else if (tdbp->CanBeFiltered()) { + if (!tdbp->GetCond() || tdbp->GetCond() != cond) { + tdbp->SetFilter(CondFilter(g, (Item *)cond)); - } else if (tty != TYPE_AM_JSN && tty != TYPE_AM_JSON) - tdbp->SetFilter(CondFilter(g, (Item *)cond)); + if (tdbp->GetFilter()) + tdbp->SetCond(cond); + + } // endif cond + + } // endif tty -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -3147,10 +3121,6 @@ const COND *ha_connect::cond_push(const COND *cond) } // end catch fin:; -#else // !USE_TRY - fin: - g->jump_level--; -#endif // !USE_TRY } // endif tdbp // Let MySQL do the filtering @@ -3301,44 +3271,28 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT*) PGLOBAL& g= xp->g; PDBUSER dup= PlgGetUser(g); -#if defined(USE_TRY) try { -#else // !USE_TRY - // Prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif + // Ignore error on the opt file + dup->Check &= ~CHK_OPT; + tdbp = GetTDB(g); + dup->Check |= CHK_OPT; - if (setjmp(g->jumper[++g->jump_level])) { - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif setjmp -#endif // !USE_TRY + if (tdbp && !tdbp->IsRemote()) { + bool dop = IsTypeIndexable(GetRealType(NULL)); + bool dox = (tdbp->GetDef()->Indexable() == 1); - // Ignore error on the opt file - dup->Check &= ~CHK_OPT; - tdbp= GetTDB(g); - dup->Check |= CHK_OPT; + if ((rc = ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) { + if (rc == RC_INFO) { + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); + rc = 0; + } else + rc = HA_ERR_INTERNAL_ERROR; - if (tdbp && !tdbp->IsRemote()) { - bool dop= IsTypeIndexable(GetRealType(NULL)); - bool dox= (tdbp->GetDef()->Indexable() == 1); + } // endif rc - if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) { - if (rc == RC_INFO) { - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - rc= 0; - } else - rc= HA_ERR_INTERNAL_ERROR; + } else if (!tdbp) + rc = HA_ERR_INTERNAL_ERROR; - } // endif rc - - } else if (!tdbp) - rc= HA_ERR_INTERNAL_ERROR; - -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -3347,10 +3301,6 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT*) strcpy(g->Message, msg); rc = HA_ERR_INTERNAL_ERROR; } // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY return rc; } // end of optimize @@ -4045,8 +3995,12 @@ int ha_connect::rnd_pos(uchar *buf, uchar *pos) tdbp->SetFilter(NULL); rc= rnd_next(buf); - } else - rc= HA_ERR_KEY_NOT_FOUND; + } else { + PGLOBAL g = GetPlug((table) ? table->in_use : NULL, xp); + strcpy(g->Message, "Not supported by this table type"); + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + rc= HA_ERR_INTERNAL_ERROR; + } // endif SetRecpos DBUG_RETURN(rc); } // end of rnd_pos @@ -4112,14 +4066,14 @@ int ha_connect::info(uint flag) } // endif xmod // This is necessary for getting file length - if (table) { + if (table) { if (SetDataPath(g, table->s->db.str)) { my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } // endif SetDataPath } else - DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen if (!(tdbp= GetTDB(g))) DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen @@ -4268,35 +4222,35 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick) case TAB_INI: case TAB_VEC: case TAB_JSON: - if (options->filename && *options->filename) { - if (!quick) { - char *s, path[FN_REFLEN], dbpath[FN_REFLEN]; + if (options->filename && *options->filename) { + if (!quick) { + char path[FN_REFLEN], dbpath[FN_REFLEN]; + + strcpy(dbpath, mysql_real_data_home); + + if (db) #if defined(__WIN__) - s= "\\"; + strcat(strcat(dbpath, db), "\\"); #else // !__WIN__ - s= "/"; + strcat(strcat(dbpath, db), "/"); #endif // !__WIN__ - strcpy(dbpath, mysql_real_data_home); - if (db) - strcat(strcat(dbpath, db), s); + (void)fn_format(path, options->filename, dbpath, "", + MY_RELATIVE_PATH | MY_UNPACK_FILENAME); - (void) fn_format(path, options->filename, dbpath, "", - MY_RELATIVE_PATH | MY_UNPACK_FILENAME); - - if (!is_secure_file_path(path)) { - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); - return true; - } // endif path - } - } else + if (!is_secure_file_path(path)) { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); + return true; + } // endif path + } + } else return false; /* Fall through to check FILE_ACL */ case TAB_ODBC: case TAB_JDBC: case TAB_MYSQL: - case TAB_DIR: + case TAB_DIR: case TAB_MAC: case TAB_WMI: case TAB_ZIP: @@ -4606,7 +4560,7 @@ int ha_connect::external_lock(THD *thd, int lock_type) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); DBUG_RETURN(0); } else if (!tdbp->GetDef()->Indexable()) { - sprintf(g->Message, "external_lock: Table %s is not indexable", tdbp->GetName()); + sprintf(g->Message, "external_lock: Table %s is not indexable", tdbp->GetName()); // DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); DBUG_RETURN(0); @@ -4689,7 +4643,9 @@ int ha_connect::external_lock(THD *thd, int lock_type) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); rc= 0; - } // endif MakeIndex + //my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + //rc= HA_ERR_INTERNAL_ERROR; + } // endif MakeIndex } else if (tdbp->GetDef()->Indexable() == 3) { if (CheckVirtualIndex(NULL)) { @@ -4710,9 +4666,12 @@ int ha_connect::external_lock(THD *thd, int lock_type) // Make it a warning to avoid crash push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); rc= 0; - } // endif Close + //my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + //rc = HA_ERR_INTERNAL_ERROR; + } // endif Close locked= 0; +// m_lock_type= lock_type; xmod= MODE_ANY; // For info commands DBUG_RETURN(rc); } // endif MODE_ANY @@ -5070,8 +5029,8 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key, } // end of records_in_range // Used to check whether a MYSQL table is created on itself -bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host, - const char *db, char *tab, const char *src, int port) +bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, + PCSZ db, PCSZ tab, PCSZ src, int port) { if (src) return false; @@ -5307,41 +5266,41 @@ static int connect_assisted_discovery(handlerton *, THD* thd, TABLE_SHARE *table_s, HA_CREATE_INFO *create_info) { - char v=0; - const char *fncn= "?"; - const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src; - const char *col, *ocl, *rnk, *pic, *fcl, *skc, *zfn; - char *tab, *dsn, *shm, *dpath; + char v=0; + PCSZ fncn= "?"; + PCSZ user, fn, db, host, pwd, sep, tbl, src; + PCSZ col, ocl, rnk, pic, fcl, skc, zfn; + char *tab, *dsn, *shm, *dpath; #if defined(__WIN__) - char *nsp= NULL, *cls= NULL; + PCSZ nsp= NULL, cls= NULL; #endif // __WIN__ -//int hdr, mxe; - int port = 0, mxr = 0, rc = 0, mul = 0, lrecl = 0; +//int hdr, mxe; + int port = 0, mxr = 0, rc = 0, mul = 0, lrecl = 0; #if defined(ODBC_SUPPORT) - POPARM sop= NULL; - char *ucnc= NULL; - bool cnc= false; - int cto= -1, qto= -1; + POPARM sop= NULL; + PCSZ ucnc= NULL; + bool cnc= false; + int cto= -1, qto= -1; #endif // ODBC_SUPPORT #if defined(JDBC_SUPPORT) - PJPARM sjp= NULL; - char *driver= NULL; - char *url= NULL; -//char *prop= NULL; - char *tabtyp= NULL; + PJPARM sjp= NULL; + PCSZ driver= NULL; + char *url= NULL; +//char *prop= NULL; + PCSZ tabtyp= NULL; #endif // JDBC_SUPPORT - uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); - bool bif, ok= false, dbf= false; - TABTYPE ttp= TAB_UNDEF; - PQRYRES qrp= NULL; - PCOLRES crp; - PCONNECT xp= NULL; - PGLOBAL g= GetPlug(thd, xp); - PDBUSER dup= PlgGetUser(g); - PCATLG cat= (dup) ? dup->Catalog : NULL; - PTOS topt= table_s->option_struct; - char buf[1024]; - String sql(buf, sizeof(buf), system_charset_info); + uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); + bool bif, ok= false, dbf= false; + TABTYPE ttp= TAB_UNDEF; + PQRYRES qrp= NULL; + PCOLRES crp; + PCONNECT xp= NULL; + PGLOBAL g= GetPlug(thd, xp); + PDBUSER dup= PlgGetUser(g); + PCATLG cat= (dup) ? dup->Catalog : NULL; + PTOS topt= table_s->option_struct; + char buf[1024]; + String sql(buf, sizeof(buf), system_charset_info); sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); @@ -5409,547 +5368,492 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (!(shm= (char*)db)) db= table_s->db.str; // Default value -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - goto jer; - } // endif jump_level + // Check table type + if (ttp == TAB_UNDEF) { + topt->type = (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; + ttp = GetTypeID(topt->type); + sprintf(g->Message, "No table_type. Was set to %s", topt->type); + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); + } else if (ttp == TAB_NIY) { + sprintf(g->Message, "Unsupported table type %s", topt->type); + rc = HA_ERR_INTERNAL_ERROR; + goto err; + } // endif ttp - if (setjmp(g->jumper[++g->jump_level]) != 0) { - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif rc -#endif // !USE_TRY + if (!tab) { + if (ttp == TAB_TBL) { + // Make tab the first table of the list + char *p; - // Check table type - if (ttp == TAB_UNDEF) { - topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; - ttp= GetTypeID(topt->type); - sprintf(g->Message, "No table_type. Was set to %s", topt->type); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - } else if (ttp == TAB_NIY) { - sprintf(g->Message, "Unsupported table type %s", topt->type); - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif ttp - - if (!tab) { - if (ttp == TAB_TBL) { - // Make tab the first table of the list - char *p; - - if (!tbl) { - strcpy(g->Message, "Missing table list"); - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif tbl - - tab= PlugDup(g, tbl); - - if ((p= strchr(tab, ','))) - *p= 0; - - if ((p=strchr(tab, '.'))) { - *p= 0; - db= tab; - tab= p + 1; - } // endif p - - } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL))) - tab= table_s->table_name.str; // Default value - - } // endif tab - - switch (ttp) { -#if defined(ODBC_SUPPORT) - case TAB_ODBC: - dsn= strz(g, create_info->connect_string); - - if (fnc & (FNC_DSN | FNC_DRIVER)) { - ok= true; -#if defined(PROMPT_OK) - } else if (!stricmp(thd->main_security_ctx.host, "localhost") - && cop == 1) { - if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) { - thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn)); - ok= true; - } // endif dsn -#endif // PROMPT_OK - - } else if (!dsn) { - sprintf(g->Message, "Missing %s connection string", topt->type); - } else { - // Store ODBC additional parameters - sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM)); - sop->User= (char*)user; - sop->Pwd= (char*)pwd; - sop->Cto= cto; - sop->Qto= qto; - sop->UseCnc= cnc; - ok= true; - } // endif's - - supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER); - break; -#endif // ODBC_SUPPORT -#if defined(JDBC_SUPPORT) - case TAB_JDBC: - if (fnc & FNC_DRIVER) { - ok= true; - } else if (!(url= strz(g, create_info->connect_string))) { - strcpy(g->Message, "Missing URL"); - } else { - // Store JDBC additional parameters - int rc; - PJDBCDEF jdef= new(g) JDBCDEF(); - - jdef->SetName(create_info->alias); - sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); - sjp->Driver= driver; -// sjp->Properties = prop; - sjp->Fsize= 0; - sjp->Scrollable= false; - - if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) { - sjp->Url= url; - sjp->User= (char*)user; - sjp->Pwd= (char*)pwd; - ok= true; - } else if (rc == RC_NF) { - if (jdef->GetTabname()) - tab= jdef->GetTabname(); - - ok= jdef->SetParms(sjp); - } // endif rc - - } // endif's - - supfnc |= (FNC_DRIVER | FNC_TABLE); - break; -#endif // JDBC_SUPPORT - case TAB_DBF: - dbf= true; - // Passthru - case TAB_CSV: - if (!fn && fnc != FNC_NO) - sprintf(g->Message, "Missing %s file name", topt->type); - else if (sep && strlen(sep) > 1) - sprintf(g->Message, "Invalid separator %s", sep); - else - ok= true; - - break; - case TAB_MYSQL: - ok= true; - - if (create_info->connect_string.str && - create_info->connect_string.length) { - PMYDEF mydef= new(g) MYSQLDEF(); - - dsn= strz(g, create_info->connect_string); - mydef->SetName(create_info->alias); - - if (!mydef->ParseURL(g, dsn, false)) { - if (mydef->GetHostname()) - host= mydef->GetHostname(); - - if (mydef->GetUsername()) - user= mydef->GetUsername(); - - if (mydef->GetPassword()) - pwd= mydef->GetPassword(); - - if (mydef->GetTabschema()) - db = mydef->GetTabschema(); - - if (mydef->GetTabname()) - tab= mydef->GetTabname(); - - if (mydef->GetPortnumber()) - port= mydef->GetPortnumber(); - - } else - ok= false; - - } else if (!user) - user= "root"; - - if (ok && CheckSelf(g, table_s, host, db, tab, src, port)) - ok= false; - - break; -#if defined(__WIN__) - case TAB_WMI: - ok= true; - break; -#endif // __WIN__ -#if defined(PIVOT_SUPPORT) - case TAB_PIVOT: - supfnc= FNC_NO; -#endif // PIVOT_SUPPORT - case TAB_PRX: - case TAB_TBL: - case TAB_XCL: - case TAB_OCCUR: - if (!src && !stricmp(tab, create_info->alias) && - (!db || !stricmp(db, table_s->db.str))) - sprintf(g->Message, "A %s table cannot refer to itself", topt->type); - else - ok= true; - - break; - case TAB_OEM: - if (topt->module && topt->subtype) - ok= true; - else - strcpy(g->Message, "Missing OEM module or subtype"); - - break; -#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT) - case TAB_XML: -#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT - case TAB_JSON: - if (!fn && !zfn && !mul) - sprintf(g->Message, "Missing %s file name", topt->type); - else - ok= true; - - break; - case TAB_VIR: - ok= true; - break; - default: - sprintf(g->Message, "Cannot get column info for table type %s", topt->type); - break; - } // endif ttp - - // Check for supported catalog function - if (ok && !(supfnc & fnc)) { - sprintf(g->Message, "Unsupported catalog function %s for table type %s", - fncn, topt->type); - ok= false; - } // endif supfnc - - if (src && fnc != FNC_NO) { - strcpy(g->Message, "Cannot make catalog table from srcdef"); - ok= false; - } // endif src - - if (ok) { - char *cnm, *rem, *dft, *xtra, *key, *fmt; - int i, len, prec, dec, typ, flg; - - // if (cat) - // cat->SetDataPath(g, table_s->db.str); - // else - // return HA_ERR_INTERNAL_ERROR; // Should never happen - - dpath = SetPath(g, table_s->db.str); - - if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC && ttp != TAB_JDBC) { - qrp = SrcColumns(g, host, db, user, pwd, src, port); - - if (qrp && ttp == TAB_OCCUR) - if (OcrSrcCols(g, qrp, col, ocl, rnk)) { + if (!tbl) { + strcpy(g->Message, "Missing table list"); rc = HA_ERR_INTERNAL_ERROR; goto err; - } // endif OcrSrcCols + } // endif tbl - } else switch (ttp) { - case TAB_DBF: - qrp = DBFColumns(g, dpath, fn, fnc == FNC_COL); - break; + tab = PlugDup(g, tbl); + + if ((p = strchr(tab, ','))) + *p = 0; + + if ((p = strchr(tab, '.'))) { + *p = 0; + db = tab; + tab = p + 1; + } // endif p + + } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL))) + tab = table_s->table_name.str; // Default value + + } // endif tab + + switch (ttp) { #if defined(ODBC_SUPPORT) case TAB_ODBC: - switch (fnc) { - case FNC_NO: - case FNC_COL: - if (src) { - qrp = ODBCSrcCols(g, dsn, (char*)src, sop); - src = NULL; // for next tests - } else - qrp = ODBCColumns(g, dsn, shm, tab, NULL, - mxr, fnc == FNC_COL, sop); + dsn = strz(g, create_info->connect_string); - break; - case FNC_TABLE: - qrp = ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop); - break; - case FNC_DSN: - qrp = ODBCDataSources(g, mxr, true); - break; - case FNC_DRIVER: - qrp = ODBCDrivers(g, mxr, true); - break; - default: - sprintf(g->Message, "invalid catfunc %s", fncn); - break; - } // endswitch info + if (fnc & (FNC_DSN | FNC_DRIVER)) { + ok = true; +#if defined(PROMPT_OK) + } else if (!stricmp(thd->main_security_ctx.host, "localhost") + && cop == 1) { + if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) { + thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn)); + ok = true; + } // endif dsn +#endif // PROMPT_OK + } else if (!dsn) { + sprintf(g->Message, "Missing %s connection string", topt->type); + } else { + // Store ODBC additional parameters + sop = (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM)); + sop->User = (char*)user; + sop->Pwd = (char*)pwd; + sop->Cto = cto; + sop->Qto = qto; + sop->UseCnc = cnc; + ok = true; + } // endif's + + supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER); break; #endif // ODBC_SUPPORT #if defined(JDBC_SUPPORT) case TAB_JDBC: - switch (fnc) { - case FNC_NO: - case FNC_COL: - if (src) { - qrp = JDBCSrcCols(g, (char*)src, sjp); - src = NULL; // for next tests - } else - qrp = JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp); + if (fnc & FNC_DRIVER) { + ok = true; + } else if (!(url = strz(g, create_info->connect_string))) { + strcpy(g->Message, "Missing URL"); + } else { + // Store JDBC additional parameters + int rc; + PJDBCDEF jdef = new(g) JDBCDEF(); - break; - case FNC_TABLE: - qrp = JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp); - break; -#if 0 - case FNC_DSN: - qrp = JDBCDataSources(g, mxr, true); - break; -#endif // 0 - case FNC_DRIVER: - qrp = JDBCDrivers(g, mxr, true); - break; - default: - sprintf(g->Message, "invalid catfunc %s", fncn); - break; - } // endswitch info + jdef->SetName(create_info->alias); + sjp = (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); + sjp->Driver = driver; + // sjp->Properties = prop; + sjp->Fsize = 0; + sjp->Scrollable = false; + if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) { + sjp->Url = url; + sjp->User = (char*)user; + sjp->Pwd = (char*)pwd; + ok = true; + } else if (rc == RC_NF) { + if (jdef->GetTabname()) + tab = (char*)jdef->GetTabname(); + + ok = jdef->SetParms(sjp); + } // endif rc + + } // endif's + + supfnc |= (FNC_DRIVER | FNC_TABLE); break; #endif // JDBC_SUPPORT - case TAB_MYSQL: - qrp = MyColumns(g, thd, host, db, user, pwd, tab, - NULL, port, fnc == FNC_COL); - break; + case TAB_DBF: + dbf = true; + // Passthru case TAB_CSV: - qrp = CSVColumns(g, dpath, topt, fnc == FNC_COL); + if (!fn && fnc != FNC_NO) + sprintf(g->Message, "Missing %s file name", topt->type); + else if (sep && strlen(sep) > 1) + sprintf(g->Message, "Invalid separator %s", sep); + else + ok = true; + + break; + case TAB_MYSQL: + ok = true; + + if (create_info->connect_string.str && + create_info->connect_string.length) { + PMYDEF mydef = new(g) MYSQLDEF(); + + dsn = strz(g, create_info->connect_string); + mydef->SetName(create_info->alias); + + if (!mydef->ParseURL(g, dsn, false)) { + if (mydef->GetHostname()) + host = mydef->GetHostname(); + + if (mydef->GetUsername()) + user = mydef->GetUsername(); + + if (mydef->GetPassword()) + pwd = mydef->GetPassword(); + + if (mydef->GetTabschema()) + db = mydef->GetTabschema(); + + if (mydef->GetTabname()) + tab = (char*)mydef->GetTabname(); + + if (mydef->GetPortnumber()) + port = mydef->GetPortnumber(); + + } else + ok = false; + + } else if (!user) + user = "root"; + + if (ok && CheckSelf(g, table_s, host, db, tab, src, port)) + ok = false; + break; #if defined(__WIN__) case TAB_WMI: - qrp = WMIColumns(g, nsp, cls, fnc == FNC_COL); + ok = true; break; #endif // __WIN__ +#if defined(PIVOT_SUPPORT) + case TAB_PIVOT: + supfnc = FNC_NO; +#endif // PIVOT_SUPPORT case TAB_PRX: case TAB_TBL: case TAB_XCL: case TAB_OCCUR: - bif = fnc == FNC_COL; - qrp = TabColumns(g, thd, db, tab, bif); - - if (!qrp && bif && fnc != FNC_COL) // tab is a view - qrp = MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false); - - if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL) - if (OcrColumns(g, qrp, col, ocl, rnk)) { - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif OcrColumns + if (!src && !stricmp(tab, create_info->alias) && + (!db || !stricmp(db, table_s->db.str))) + sprintf(g->Message, "A %s table cannot refer to itself", topt->type); + else + ok = true; break; -#if defined(PIVOT_SUPPORT) - case TAB_PIVOT: - qrp = PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port); - break; -#endif // PIVOT_SUPPORT - case TAB_VIR: - qrp = VirColumns(g, fnc == FNC_COL); - break; - case TAB_JSON: - qrp = JSONColumns(g, (char*)db, topt, fnc == FNC_COL); + case TAB_OEM: + if (topt->module && topt->subtype) + ok = true; + else + strcpy(g->Message, "Missing OEM module or subtype"); + break; #if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT) case TAB_XML: - qrp = XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL); - break; #endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT - case TAB_OEM: - qrp = OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL); + case TAB_JSON: + dsn = strz(g, create_info->connect_string); + + if (!fn && !zfn && !mul && !dsn) + sprintf(g->Message, "Missing %s file name", topt->type); + else + ok = true; + + break; + case TAB_VIR: + ok = true; break; default: - strcpy(g->Message, "System error during assisted discovery"); + sprintf(g->Message, "Cannot get column info for table type %s", topt->type); break; - } // endswitch ttp + } // endif ttp - if (!qrp) { - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif !qrp + // Check for supported catalog function + if (ok && !(supfnc & fnc)) { + sprintf(g->Message, "Unsupported catalog function %s for table type %s", + fncn, topt->type); + ok = false; + } // endif supfnc - if (fnc != FNC_NO || src || ttp == TAB_PIVOT) { - // Catalog like table - for (crp = qrp->Colresp; !rc && crp; crp = crp->Next) { - cnm = (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name); - typ = crp->Type; - len = crp->Length; - dec = crp->Prec; - flg = crp->Flag; - v = (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var; - tm = (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; + if (src && fnc != FNC_NO) { + strcpy(g->Message, "Cannot make catalog table from srcdef"); + ok = false; + } // endif src - if (!len && typ == TYPE_STRING) - len = 256; // STRBLK's have 0 length - - // Now add the field - if (add_field(&sql, cnm, typ, len, dec, NULL, tm, - NULL, NULL, NULL, NULL, flg, dbf, v)) - rc = HA_ERR_OUT_OF_MEM; - } // endfor crp - - } else { - char *schem = NULL; - char *tn = NULL; - - // Not a catalog table - if (!qrp->Nblin) { - if (tab) - sprintf(g->Message, "Cannot get columns from %s", tab); - else - strcpy(g->Message, "Fail to retrieve columns"); + if (ok) { + const char *cnm, *rem; + char *dft, *xtra, *key, *fmt; + int i, len, prec, dec, typ, flg; + if (!(dpath = SetPath(g, table_s->db.str))) { rc = HA_ERR_INTERNAL_ERROR; goto err; - } // endif !nblin + } // endif dpath - for (i = 0; !rc && i < qrp->Nblin; i++) { - typ = len = prec = dec = 0; - tm = NOT_NULL_FLAG; - cnm = (char*)"noname"; - dft = xtra = key = fmt = tn = NULL; - v = ' '; - rem = NULL; + if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC && ttp != TAB_JDBC) { + qrp = SrcColumns(g, host, db, user, pwd, src, port); - for (crp = qrp->Colresp; crp; crp = crp->Next) - switch (crp->Fld) { - case FLD_NAME: - if (ttp == TAB_PRX || - (ttp == TAB_CSV && topt->data_charset && - (!stricmp(topt->data_charset, "UTF8") || - !stricmp(topt->data_charset, "UTF-8")))) - cnm = crp->Kdata->GetCharValue(i); - else - cnm = encode(g, crp->Kdata->GetCharValue(i)); - - break; - case FLD_TYPE: - typ = crp->Kdata->GetIntValue(i); - v = (crp->Nulls) ? crp->Nulls[i] : 0; - break; - case FLD_TYPENAME: - tn = crp->Kdata->GetCharValue(i); - break; - case FLD_PREC: - // PREC must be always before LENGTH - len = prec = crp->Kdata->GetIntValue(i); - break; - case FLD_LENGTH: - len = crp->Kdata->GetIntValue(i); - break; - case FLD_SCALE: - dec = (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1; - break; - case FLD_NULL: - if (crp->Kdata->GetIntValue(i)) - tm = 0; // Nullable - - break; - case FLD_FORMAT: - fmt = (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL; - break; - case FLD_REM: - rem = crp->Kdata->GetCharValue(i); - break; - // case FLD_CHARSET: - // No good because remote table is already translated - // if (*(csn= crp->Kdata->GetCharValue(i))) - // cs= get_charset_by_name(csn, 0); - - // break; - case FLD_DEFAULT: - dft = crp->Kdata->GetCharValue(i); - break; - case FLD_EXTRA: - xtra = crp->Kdata->GetCharValue(i); - - // Auto_increment is not supported yet - if (!stricmp(xtra, "AUTO_INCREMENT")) - xtra = NULL; - - break; - case FLD_KEY: - if (ttp == TAB_VIR) - key = crp->Kdata->GetCharValue(i); - - break; - case FLD_SCHEM: -#if defined(ODBC_SUPPORT) || defined(JDBC_SUPPORT) - if ((ttp == TAB_ODBC || ttp == TAB_JDBC) && crp->Kdata) { - if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) { - sprintf(g->Message, - "Several %s tables found, specify DBNAME", tab); - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } else if (!schem) - schem = crp->Kdata->GetCharValue(i); - - } // endif ttp -#endif // ODBC_SUPPORT || JDBC_SUPPORT - default: - break; // Ignore - } // endswitch Fld + if (qrp && ttp == TAB_OCCUR) + if (OcrSrcCols(g, qrp, col, ocl, rnk)) { + rc = HA_ERR_INTERNAL_ERROR; + goto err; + } // endif OcrSrcCols + } else switch (ttp) { + case TAB_DBF: + qrp = DBFColumns(g, dpath, fn, fnc == FNC_COL); + break; #if defined(ODBC_SUPPORT) - if (ttp == TAB_ODBC) { - int plgtyp; - bool w = false; // Wide character type - - // typ must be PLG type, not SQL type - if (!(plgtyp = TranslateSQLType(typ, dec, prec, v, w))) { - if (GetTypeConv() == TPC_SKIP) { - // Skip this column - sprintf(g->Message, "Column %s skipped (unsupported type %d)", - cnm, typ); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - continue; - } else { - sprintf(g->Message, "Unsupported SQL type %d", typ); - rc = HA_ERR_INTERNAL_ERROR; - goto err; - } // endif type_conv - - } else - typ = plgtyp; - - switch (typ) { - case TYPE_STRING: - if (w) { - sprintf(g->Message, "Column %s is wide characters", cnm); - push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message); - } // endif w + case TAB_ODBC: + switch (fnc) { + case FNC_NO: + case FNC_COL: + if (src) { + qrp = ODBCSrcCols(g, dsn, (char*)src, sop); + src = NULL; // for next tests + } else + qrp = ODBCColumns(g, dsn, shm, tab, NULL, + mxr, fnc == FNC_COL, sop); break; - case TYPE_DOUBLE: - // Some data sources do not count dec in length (prec) - prec += (dec + 2); // To be safe + case FNC_TABLE: + qrp = ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop); break; - case TYPE_DECIM: - prec = len; + case FNC_DSN: + qrp = ODBCDataSources(g, mxr, true); + break; + case FNC_DRIVER: + qrp = ODBCDrivers(g, mxr, true); break; default: - dec = 0; - } // endswitch typ + sprintf(g->Message, "invalid catfunc %s", fncn); + break; + } // endswitch info - } else + break; #endif // ODBC_SUPPORT #if defined(JDBC_SUPPORT) - if (ttp == TAB_JDBC) { + case TAB_JDBC: + switch (fnc) { + case FNC_NO: + case FNC_COL: + if (src) { + qrp = JDBCSrcCols(g, (char*)src, sjp); + src = NULL; // for next tests + } else + qrp = JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp); + + break; + case FNC_TABLE: + qrp = JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp); + break; +#if 0 + case FNC_DSN: + qrp = JDBCDataSources(g, mxr, true); + break; +#endif // 0 + case FNC_DRIVER: + qrp = JDBCDrivers(g, mxr, true); + break; + default: + sprintf(g->Message, "invalid catfunc %s", fncn); + break; + } // endswitch info + + break; +#endif // JDBC_SUPPORT + case TAB_MYSQL: + qrp = MyColumns(g, thd, host, db, user, pwd, tab, + NULL, port, fnc == FNC_COL); + break; + case TAB_CSV: + qrp = CSVColumns(g, dpath, topt, fnc == FNC_COL); + break; +#if defined(__WIN__) + case TAB_WMI: + qrp = WMIColumns(g, nsp, cls, fnc == FNC_COL); + break; +#endif // __WIN__ + case TAB_PRX: + case TAB_TBL: + case TAB_XCL: + case TAB_OCCUR: + bif = fnc == FNC_COL; + qrp = TabColumns(g, thd, db, tab, bif); + + if (!qrp && bif && fnc != FNC_COL) // tab is a view + qrp = MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false); + + if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL) + if (OcrColumns(g, qrp, col, ocl, rnk)) { + rc = HA_ERR_INTERNAL_ERROR; + goto err; + } // endif OcrColumns + + break; +#if defined(PIVOT_SUPPORT) + case TAB_PIVOT: + qrp = PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port); + break; +#endif // PIVOT_SUPPORT + case TAB_VIR: + qrp = VirColumns(g, fnc == FNC_COL); + break; + case TAB_JSON: + qrp = JSONColumns(g, (char*)db, dsn, topt, fnc == FNC_COL); + break; +#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT) + case TAB_XML: + qrp = XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL); + break; +#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT + case TAB_OEM: + qrp = OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL); + break; + default: + strcpy(g->Message, "System error during assisted discovery"); + break; + } // endswitch ttp + + if (!qrp) { + rc = HA_ERR_INTERNAL_ERROR; + goto err; + } // endif !qrp + + if (fnc != FNC_NO || src || ttp == TAB_PIVOT) { + // Catalog like table + for (crp = qrp->Colresp; !rc && crp; crp = crp->Next) { + cnm = (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name); + typ = crp->Type; + len = crp->Length; + dec = crp->Prec; + flg = crp->Flag; + v = (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var; + tm = (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; + + if (!len && typ == TYPE_STRING) + len = 256; // STRBLK's have 0 length + + // Now add the field + if (add_field(&sql, cnm, typ, len, dec, NULL, tm, + NULL, NULL, NULL, NULL, flg, dbf, v)) + rc = HA_ERR_OUT_OF_MEM; + } // endfor crp + + } else { + char *schem = NULL; + char *tn = NULL; + + // Not a catalog table + if (!qrp->Nblin) { + if (tab) + sprintf(g->Message, "Cannot get columns from %s", tab); + else + strcpy(g->Message, "Fail to retrieve columns"); + + rc = HA_ERR_INTERNAL_ERROR; + goto err; + } // endif !nblin + + for (i = 0; !rc && i < qrp->Nblin; i++) { + typ = len = prec = dec = 0; + tm = NOT_NULL_FLAG; + cnm = (char*)"noname"; + dft = xtra = key = fmt = tn = NULL; + v = ' '; + rem = NULL; + + for (crp = qrp->Colresp; crp; crp = crp->Next) + switch (crp->Fld) { + case FLD_NAME: + if (ttp == TAB_PRX || + (ttp == TAB_CSV && topt->data_charset && + (!stricmp(topt->data_charset, "UTF8") || + !stricmp(topt->data_charset, "UTF-8")))) + cnm = crp->Kdata->GetCharValue(i); + else + cnm = encode(g, crp->Kdata->GetCharValue(i)); + + break; + case FLD_TYPE: + typ = crp->Kdata->GetIntValue(i); + v = (crp->Nulls) ? crp->Nulls[i] : 0; + break; + case FLD_TYPENAME: + tn = crp->Kdata->GetCharValue(i); + break; + case FLD_PREC: + // PREC must be always before LENGTH + len = prec = crp->Kdata->GetIntValue(i); + break; + case FLD_LENGTH: + len = crp->Kdata->GetIntValue(i); + break; + case FLD_SCALE: + dec = (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1; + break; + case FLD_NULL: + if (crp->Kdata->GetIntValue(i)) + tm = 0; // Nullable + + break; + case FLD_FORMAT: + fmt = (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL; + break; + case FLD_REM: + rem = crp->Kdata->GetCharValue(i); + break; + // case FLD_CHARSET: + // No good because remote table is already translated + // if (*(csn= crp->Kdata->GetCharValue(i))) + // cs= get_charset_by_name(csn, 0); + + // break; + case FLD_DEFAULT: + dft = crp->Kdata->GetCharValue(i); + break; + case FLD_EXTRA: + xtra = crp->Kdata->GetCharValue(i); + + // Auto_increment is not supported yet + if (!stricmp(xtra, "AUTO_INCREMENT")) + xtra = NULL; + + break; + case FLD_KEY: + if (ttp == TAB_VIR) + key = crp->Kdata->GetCharValue(i); + + break; + case FLD_SCHEM: +#if defined(ODBC_SUPPORT) || defined(JDBC_SUPPORT) + if ((ttp == TAB_ODBC || ttp == TAB_JDBC) && crp->Kdata) { + if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) { + sprintf(g->Message, + "Several %s tables found, specify DBNAME", tab); + rc = HA_ERR_INTERNAL_ERROR; + goto err; + } else if (!schem) + schem = crp->Kdata->GetCharValue(i); + + } // endif ttp +#endif // ODBC_SUPPORT || JDBC_SUPPORT + default: + break; // Ignore + } // endswitch Fld + +#if defined(ODBC_SUPPORT) + if (ttp == TAB_ODBC) { int plgtyp; + bool w = false; // Wide character type // typ must be PLG type, not SQL type - if (!(plgtyp = TranslateJDBCType(typ, tn, dec, prec, v))) { + if (!(plgtyp = TranslateSQLType(typ, dec, prec, v, w))) { if (GetTypeConv() == TPC_SKIP) { // Skip this column sprintf(g->Message, "Column %s skipped (unsupported type %d)", @@ -5966,43 +5870,84 @@ static int connect_assisted_discovery(handlerton *, THD* thd, typ = plgtyp; switch (typ) { + case TYPE_STRING: + if (w) { + sprintf(g->Message, "Column %s is wide characters", cnm); + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message); + } // endif w + + break; case TYPE_DOUBLE: - case TYPE_DECIM: // Some data sources do not count dec in length (prec) prec += (dec + 2); // To be safe break; + case TYPE_DECIM: + prec = len; + break; default: dec = 0; } // endswitch typ } else #endif // ODBC_SUPPORT - // Make the arguments as required by add_fields - if (typ == TYPE_DOUBLE) - prec = len; +#if defined(JDBC_SUPPORT) + if (ttp == TAB_JDBC) { + int plgtyp; - if (typ == TYPE_DATE) - prec = 0; + // typ must be PLG type, not SQL type + if (!(plgtyp = TranslateJDBCType(typ, tn, dec, prec, v))) { + if (GetTypeConv() == TPC_SKIP) { + // Skip this column + sprintf(g->Message, "Column %s skipped (unsupported type %d)", + cnm, typ); + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); + continue; + } else { + sprintf(g->Message, "Unsupported SQL type %d", typ); + rc = HA_ERR_INTERNAL_ERROR; + goto err; + } // endif type_conv - // Now add the field - if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra, - fmt, 0, dbf, v)) - rc = HA_ERR_OUT_OF_MEM; - } // endfor i + } else + typ = plgtyp; - } // endif fnc + switch (typ) { + case TYPE_DOUBLE: + case TYPE_DECIM: + // Some data sources do not count dec in length (prec) + prec += (dec + 2); // To be safe + break; + default: + dec = 0; + } // endswitch typ - if (!rc) - rc = init_table_share(thd, table_s, create_info, &sql); + } else +#endif // ODBC_SUPPORT + // Make the arguments as required by add_fields + if (typ == TYPE_DOUBLE) + prec = len; - //g->jump_level--; - //PopUser(xp); - //return rc; - } else { - rc = HA_ERR_UNSUPPORTED; - } // endif ok + if (typ == TYPE_DATE) + prec = 0; + + // Now add the field + if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra, + fmt, 0, dbf, v)) + rc = HA_ERR_OUT_OF_MEM; + } // endfor i + + } // endif fnc + + if (!rc) + rc = init_table_share(thd, table_s, create_info, &sql); + + //g->jump_level--; + //PopUser(xp); + //return rc; + } else { + rc = HA_ERR_UNSUPPORTED; + } // endif ok -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -6013,16 +5958,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd, } // end catch err: -#else // !USE_TRY - err: - g->jump_level--; -#endif // !USE_TRY if (rc) my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); -#if !defined(USE_TRY) - jer: -#endif // !USE_TRY PopUser(xp); return rc; } // end of connect_assisted_discovery @@ -6189,8 +6127,8 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (!part_info) #endif // WITH_PARTITION_STORAGE_ENGINE {const char *src= options->srcdef; - char *host, *db, *tab= (char*)options->tabname; - int port; + PCSZ host, db, tab= options->tabname; + int port; host= GetListOption(g, "host", options->oplist, NULL); db= GetStringOption("database", NULL); @@ -6234,8 +6172,8 @@ int ha_connect::create(const char *name, TABLE *table_arg, } // endswitch ttp if (type == TAB_XML) { - bool dom; // True: MS-DOM, False libxml2 - char *xsup= GetListOption(g, "Xmlsup", options->oplist, "*"); + bool dom; // True: MS-DOM, False libxml2 + PCSZ xsup= GetListOption(g, "Xmlsup", options->oplist, "*"); // Note that if no support is specified, the default is MS-DOM // on Windows and libxml2 otherwise @@ -6495,15 +6433,15 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (options->zipped) { // Check whether the zip entry must be made from a file - char *fn = GetListOption(g, "Load", options->oplist, NULL); + PCSZ fn = GetListOption(g, "Load", options->oplist, NULL); if (fn) { - char zbuf[_MAX_PATH], buf[_MAX_PATH], dbpath[_MAX_PATH]; - char *entry = GetListOption(g, "Entry", options->oplist, NULL); - char *a = GetListOption(g, "Append", options->oplist, "NO"); - bool append = *a == '1' || *a == 'Y' || *a == 'y' || !stricmp(a, "ON"); - char *m = GetListOption(g, "Mulentries", options->oplist, "NO"); - bool mul = *m == '1' || *m == 'Y' || *m == 'y' || !stricmp(m, "ON"); + char zbuf[_MAX_PATH], buf[_MAX_PATH], dbpath[_MAX_PATH]; + PCSZ entry = GetListOption(g, "Entry", options->oplist, NULL); + PCSZ a = GetListOption(g, "Append", options->oplist, "NO"); + bool append = *a == '1' || *a == 'Y' || *a == 'y' || !stricmp(a, "ON"); + PCSZ m = GetListOption(g, "Mulentries", options->oplist, "NO"); + bool mul = *m == '1' || *m == 'Y' || *m == 'y' || !stricmp(m, "ON"); if (!entry && !mul) { my_message(ER_UNKNOWN_ERROR, "Missing entry name", MYF(0)); @@ -6575,8 +6513,6 @@ int ha_connect::create(const char *name, TABLE *table_arg, my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); rc = HA_ERR_INTERNAL_ERROR; } else if (cat) { -// cat->SetDataPath(g, table_arg->s->db.str); - #if defined(WITH_PARTITION_STORAGE_ENGINE) if (part_info) strncpy(partname, @@ -6632,8 +6568,9 @@ bool ha_connect::FileExists(const char *fn, bool bf) return true; if (table) { - char *s, tfn[_MAX_PATH], filename[_MAX_PATH], path[_MAX_PATH]; - bool b= false; + const char *s; + char tfn[_MAX_PATH], filename[_MAX_PATH], path[_MAX_PATH]; + bool b= false; int n; struct stat info; @@ -6690,9 +6627,9 @@ bool ha_connect::CheckString(const char *str1, const char *str2) /** check whether a string option have changed */ -bool ha_connect::SameString(TABLE *tab, char *opn) +bool ha_connect::SameString(TABLE *tab, PCSZ opn) { - char *str1, *str2; + PCSZ str1, str2; tshp= tab->s; // The altered table str1= GetStringOption(opn); @@ -6704,7 +6641,7 @@ bool ha_connect::SameString(TABLE *tab, char *opn) /** check whether a Boolean option have changed */ -bool ha_connect::SameBool(TABLE *tab, char *opn) +bool ha_connect::SameBool(TABLE *tab, PCSZ opn) { bool b1, b2; @@ -6718,7 +6655,7 @@ bool ha_connect::SameBool(TABLE *tab, char *opn) /** check whether an integer option have changed */ -bool ha_connect::SameInt(TABLE *tab, char *opn) +bool ha_connect::SameInt(TABLE *tab, PCSZ opn) { int i1, i2; @@ -6897,7 +6834,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table, // Conversion to outward table is only allowed for file based // tables whose file does not exist. tshp= altered_table->s; - char *fn= GetStringOption("filename"); + PCSZ fn= GetStringOption("filename"); tshp= NULL; if (FileExists(fn, false)) { @@ -7142,10 +7079,10 @@ maria_declare_plugin(connect) PLUGIN_LICENSE_GPL, connect_init_func, /* Plugin Init */ connect_done_func, /* Plugin Deinit */ - 0x0105, /* version number (1.05) */ + 0x0106, /* version number (1.05) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.05.0003", /* string version */ - MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ + "1.06.0001", /* string version */ + MariaDB_PLUGIN_MATURITY_BETA /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 155bec3c966..8d8307b4bd1 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /** @file ha_connect.h @@ -61,7 +61,7 @@ public: oldopn= newopn= NULL; oldpix= newpix= NULL;} - inline char *SetName(PGLOBAL g, char *name) {return PlugDup(g, name);} + inline char *SetName(PGLOBAL g, PCSZ name) {return PlugDup(g, name);} bool oldsep; // Sepindex before create/alter bool newsep; // Sepindex after create/alter @@ -168,18 +168,18 @@ public: static bool connect_init(void); static bool connect_end(void); TABTYPE GetRealType(PTOS pos= NULL); - char *GetRealString(const char *s); - char *GetStringOption(char *opname, char *sdef= NULL); + char *GetRealString(PCSZ s); + PCSZ GetStringOption(PCSZ opname, PCSZ sdef= NULL); PTOS GetTableOptionStruct(TABLE_SHARE *s= NULL); - bool GetBooleanOption(char *opname, bool bdef); - bool SetBooleanOption(char *opname, bool b); - int GetIntegerOption(char *opname); - bool GetIndexOption(KEY *kp, char *opname); - bool CheckString(const char *str1, const char *str2); - bool SameString(TABLE *tab, char *opn); - bool SetIntegerOption(char *opname, int n); - bool SameInt(TABLE *tab, char *opn); - bool SameBool(TABLE *tab, char *opn); + bool GetBooleanOption(PCSZ opname, bool bdef); + bool SetBooleanOption(PCSZ opname, bool b); + int GetIntegerOption(PCSZ opname); + bool GetIndexOption(KEY *kp, PCSZ opname); + bool CheckString(PCSZ str1, PCSZ str2); + bool SameString(TABLE *tab, PCSZ opn); + bool SetIntegerOption(PCSZ opname, int n); + bool SameInt(TABLE *tab, PCSZ opn); + bool SameBool(TABLE *tab, PCSZ opn); bool FileExists(const char *fn, bool bf); bool NoFieldOptionChange(TABLE *tab); PFOS GetFieldOptionStruct(Field *fp); @@ -187,8 +187,8 @@ public: PXOS GetIndexOptionStruct(KEY *kp); PIXDEF GetIndexInfo(TABLE_SHARE *s= NULL); bool CheckVirtualIndex(TABLE_SHARE *s); - const char *GetDBName(const char *name); - const char *GetTableName(void); + PCSZ GetDBName(PCSZ name); + PCSZ GetTableName(void); char *GetPartName(void); //int GetColNameLen(Field *fp); //char *GetColName(Field *fp); @@ -197,9 +197,9 @@ public: bool IsSameIndex(PIXDEF xp1, PIXDEF xp2); bool IsPartitioned(void); bool IsUnique(uint n); - char *GetDataPath(void) {return (char*)datapath;} + PCSZ GetDataPath(void) {return datapath;} - bool SetDataPath(PGLOBAL g, const char *path); + bool SetDataPath(PGLOBAL g, PCSZ path); PTDB GetTDB(PGLOBAL g); int OpenTable(PGLOBAL g, bool del= false); bool CheckColumnList(PGLOBAL g); @@ -513,7 +513,7 @@ protected: ulong hnum; // The number of this handler query_id_t valid_query_id; // The one when tdbp was allocated query_id_t creat_query_id; // The one when handler was allocated - char *datapath; // Is the Path of DB data directory + PCSZ datapath; // Is the Path of DB data directory PTDB tdbp; // To table class object PVAL sdvalin1; // Used to convert date values PVAL sdvalin2; // Used to convert date values diff --git a/storage/connect/inihandl.c b/storage/connect/inihandl.c index 46102557b20..0ce0eb9fa0d 100644 --- a/storage/connect/inihandl.c +++ b/storage/connect/inihandl.c @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include "my_global.h" diff --git a/storage/connect/ioapi.c b/storage/connect/ioapi.c index 7f5c191b2af..a49da91f7f0 100644 --- a/storage/connect/ioapi.c +++ b/storage/connect/ioapi.c @@ -27,6 +27,7 @@ #include "ioapi.h" +#include "my_attribute.h" voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) { @@ -92,7 +93,7 @@ static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPO static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); -static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +static voidpf ZCALLBACK fopen_file_func (voidpf opaque __attribute__((unused)), const char* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; @@ -110,7 +111,7 @@ static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, in return file; } -static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque __attribute__((unused)), const void* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; @@ -129,21 +130,21 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, } -static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +static uLong ZCALLBACK fread_file_func (voidpf opaque __attribute__((unused)), voidpf stream, void* buf, uLong size) { uLong ret; ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +static uLong ZCALLBACK fwrite_file_func (voidpf opaque __attribute__((unused)), voidpf stream, const void* buf, uLong size) { uLong ret; ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +static long ZCALLBACK ftell_file_func (voidpf opaque __attribute__((unused)), voidpf stream) { long ret; ret = ftell((FILE *)stream); @@ -151,14 +152,14 @@ static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) } -static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque __attribute__((unused)), voidpf stream) { ZPOS64_T ret; ret = FTELLO_FUNC((FILE *)stream); return ret; } -static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +static long ZCALLBACK fseek_file_func (voidpf opaque __attribute__((unused)), voidpf stream, uLong offset, int origin) { int fseek_origin=0; long ret; @@ -181,7 +182,7 @@ static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offs return ret; } -static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +static long ZCALLBACK fseek64_file_func (voidpf opaque __attribute__((unused)), voidpf stream, ZPOS64_T offset, int origin) { int fseek_origin=0; long ret; @@ -207,14 +208,14 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T } -static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +static int ZCALLBACK fclose_file_func (voidpf opaque __attribute__((unused)), voidpf stream) { int ret; ret = fclose((FILE *)stream); return ret; } -static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +static int ZCALLBACK ferror_file_func (voidpf opaque __attribute__((unused)), voidpf stream) { int ret; ret = ferror((FILE *)stream); diff --git a/storage/connect/ioapi.h b/storage/connect/ioapi.h index 8dcbdb06e35..4fa73002053 100644 --- a/storage/connect/ioapi.h +++ b/storage/connect/ioapi.h @@ -129,8 +129,9 @@ extern "C" { #endif #endif - - +#ifndef OF +#define OF(args) args +#endif typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); diff --git a/storage/connect/jdbccat.h b/storage/connect/jdbccat.h index 7108aa376ce..0b87df8bb51 100644 --- a/storage/connect/jdbccat.h +++ b/storage/connect/jdbccat.h @@ -4,10 +4,10 @@ typedef struct jdbc_parms { int CheckSize(int rows); - char *Driver; // JDBC driver - char *Url; // Driver URL - char *User; // User connect info - char *Pwd; // Password connect info + PCSZ Driver; // JDBC driver + PCSZ Url; // Driver URL + PCSZ User; // User connect info + PCSZ Pwd; // Password connect info //char *Properties; // Connection property list //int Cto; // Connect timeout //int Qto; // Query timeout @@ -19,12 +19,12 @@ typedef struct jdbc_parms { /* JDBC catalog function prototypes. */ /***********************************************************************/ #if defined(PROMPT_OK) -char *JDBCCheckConnection(PGLOBAL g, char *dsn, int cop); +char *JDBCCheckConnection(PGLOBAL g, PCSZ dsn, int cop); #endif // PROMPT_OK //PQRYRES JDBCDataSources(PGLOBAL g, int maxres, bool info); -PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, - char *colpat, int maxres, bool info, PJPARM sop); -PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sop); -PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, - char *tabtyp, int maxres, bool info, PJPARM sop); +PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, + PCSZ colpat, int maxres, bool info, PJPARM sop); +PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sop); +PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, + PCSZ tabtyp, int maxres, bool info, PJPARM sop); PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info); diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index e8a260c8be9..f162a7ae645 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -189,8 +189,8 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v) /***********************************************************************/ /* Allocate the structure used to refer to the result set. */ /***********************************************************************/ -static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db, - char *tab, PQRYRES qrp) +static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, PCSZ db, + PCSZ tab, PQRYRES qrp) { JCATPARM *cap; @@ -213,7 +213,7 @@ static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db, /* JDBCColumns: constructs the result blocks containing all columns */ /* of a JDBC table that will be retrieved by GetData commands. */ /***********************************************************************/ -PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat, +PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat, int maxres, bool info, PJPARM sjp) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, @@ -316,7 +316,7 @@ PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat, /* JDBCSrcCols: constructs the result blocks containing the */ /* description of all the columns of a Srcdef option. */ /**************************************************************************/ -PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp) +PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sjp) { char *sqry; PQRYRES qrp; @@ -330,7 +330,7 @@ PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp) sqry = (char*)PlugSubAlloc(g, NULL, strlen(src) + 2); sprintf(sqry, src, "1=1"); // dummy where clause } else - sqry = src; + sqry = (char*)src; qrp = jcp->GetMetaData(g, sqry); jcp->Close(); @@ -341,7 +341,7 @@ PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp) /* JDBCTables: constructs the result blocks containing all tables in */ /* an JDBC database that will be retrieved by GetData commands. */ /**************************************************************************/ -PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp, +PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, PCSZ tabtyp, int maxres, bool info, PJPARM sjp) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, @@ -1059,7 +1059,7 @@ int JDBConn::Open(PJPARM sop) /***********************************************************************/ /* Execute an SQL command. */ /***********************************************************************/ -int JDBConn::ExecSQLcommand(char *sql) +int JDBConn::ExecSQLcommand(PCSZ sql) { int rc; jint n; @@ -1142,7 +1142,7 @@ int JDBConn::Fetch(int pos) /***********************************************************************/ /* Restart from beginning of result set */ /***********************************************************************/ -int JDBConn::Rewind(char *sql) +int JDBConn::Rewind(PCSZ sql) { int rbuf = -1; @@ -1200,11 +1200,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) if (rank == 0) if (!name || (jn = env->NewStringUTF(name)) == nullptr) { sprintf(g->Message, "Fail to allocate jstring %s", SVP(name)); -#if defined(USE_TRY) throw TYPE_AM_JDBC; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); -#endif // !USE_TRY } // endif name // Returns 666 is case of error @@ -1212,11 +1208,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) if (Check((ctyp == 666) ? -1 : 1)) { sprintf(g->Message, "Getting ctyp: %s", Msg); -#if defined(USE_TRY) throw TYPE_AM_JDBC; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); -#endif // !USE_TRY } // endif Check if (val->GetNullable()) @@ -1235,7 +1227,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) case 12: // VARCHAR case -1: // LONGVARCHAR case 1: // CHAR - case 3: // DECIMAL + case 3: // DECIMAL if (jb && ctyp != 3) cn = (jstring)jb; else if (!gmID(g, chrfldid, "StringField", "(ILjava/lang/String;)Ljava/lang/String;")) @@ -1323,11 +1315,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) env->DeleteLocalRef(jn); sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", Msg, rank, (int)ctyp); -#if defined(USE_TRY) throw TYPE_AM_JDBC; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); -#endif // !USE_TRY } // endif Check if (rank == 0) @@ -1338,7 +1326,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) /***********************************************************************/ /* Prepare an SQL statement for insert. */ /***********************************************************************/ -bool JDBConn::PrepareSQL(char *sql) +bool JDBConn::PrepareSQL(PCSZ sql) { bool b = true; PGLOBAL& g = m_G; @@ -1361,7 +1349,7 @@ bool JDBConn::PrepareSQL(char *sql) /***********************************************************************/ /* Execute an SQL query that returns a result set. */ /***********************************************************************/ -int JDBConn::ExecuteQuery(char *sql) +int JDBConn::ExecuteQuery(PCSZ sql) { int rc = RC_FX; jint ncol; @@ -1389,7 +1377,7 @@ int JDBConn::ExecuteQuery(char *sql) /***********************************************************************/ /* Execute an SQL query and get the affected rows. */ /***********************************************************************/ -int JDBConn::ExecuteUpdate(char *sql) +int JDBConn::ExecuteUpdate(PCSZ sql) { int rc = RC_FX; jint n; @@ -1417,7 +1405,7 @@ int JDBConn::ExecuteUpdate(char *sql) /***********************************************************************/ /* Get the number of lines of the result set. */ /***********************************************************************/ -int JDBConn::GetResultSize(char *sql, JDBCCOL *colp) +int JDBConn::GetResultSize(PCSZ sql, JDBCCOL *colp) { int rc, n = 0; @@ -1655,7 +1643,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) /* GetMetaData: constructs the result blocks containing the */ /* description of all the columns of an SQL command. */ /**************************************************************************/ - PQRYRES JDBConn::GetMetaData(PGLOBAL g, char *src) + PQRYRES JDBConn::GetMetaData(PGLOBAL g, PCSZ src) { static int buftyp[] = {TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT}; @@ -1857,7 +1845,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) PGLOBAL& g = m_G; // void *buffer; int i, ncol; - PSZ fnc = "Unknown"; + PCSZ fnc = "Unknown"; uint n; short len, tp; int crow = 0; diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index 9d428142839..73271c8f5be 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -46,9 +46,9 @@ enum JCATINFO { typedef struct tagJCATPARM { JCATINFO Id; // Id to indicate function PQRYRES Qrp; // Result set pointer - char *DB; // Database (Schema) - char *Tab; // Table name or pattern - char *Pat; // Table type or column pattern + PCSZ DB; // Database (Schema) + PCSZ Tab; // Table name or pattern + PCSZ Pat; // Table type or column pattern } JCATPARM; typedef jint(JNICALL *CRTJVM) (JavaVM **, void **, void *); @@ -77,7 +77,7 @@ public: JDBConn(PGLOBAL g, TDBJDBC *tdbp); int Open(PJPARM sop); - int Rewind(char *sql); + int Rewind(PCSZ sql); void Close(void); PQRYRES AllocateResult(PGLOBAL g); @@ -96,19 +96,19 @@ public: //void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;} //void SetUserName(PSZ user) {m_User = user;} //void SetUserPwd(PSZ pwd) {m_Pwd = pwd;} - int GetResultSize(char *sql, JDBCCOL *colp); - int ExecuteQuery(char *sql); - int ExecuteUpdate(char *sql); + int GetResultSize(PCSZ sql, JDBCCOL *colp); + int ExecuteQuery(PCSZ sql); + int ExecuteUpdate(PCSZ sql); int Fetch(int pos = 0); - bool PrepareSQL(char *sql); + bool PrepareSQL(PCSZ sql); int ExecuteSQL(void); bool SetParam(JDBCCOL *colp); - int ExecSQLcommand(char *sql); + int ExecSQLcommand(PCSZ sql); void SetColumnValue(int rank, PSZ name, PVAL val); int GetCatInfo(JCATPARM *cap); //bool GetDataSources(PQRYRES qrp); bool GetDrivers(PQRYRES qrp); - PQRYRES GetMetaData(PGLOBAL g, char *src); + PQRYRES GetMetaData(PGLOBAL g, PCSZ src); public: // Set static variables @@ -174,16 +174,10 @@ protected: jmethodID timfldid; // The TimeField method ID jmethodID tspfldid; // The TimestampField method ID jmethodID bigfldid; // The BigintField method ID - //DWORD m_LoginTimeout; -//DWORD m_QueryTimeout; -//DWORD m_UpdateOptions; - char *Msg; + PCSZ Msg; char *m_Wrap; char m_IDQuoteChar[2]; -//PSZ m_Driver; -//PSZ m_Url; -//PSZ m_User; - PSZ m_Pwd; + PCSZ m_Pwd; int m_Ncol; int m_Aff; int m_Rows; diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index 2aca1377d69..bcea0ec85aa 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -81,123 +81,70 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma) if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n'))) pty[0] = false; - -#if defined(USE_TRY) - try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return NULL; - } // endif jump_level - -#if defined(SE_CATCH) - // Let's try to recover from any kind of interrupt - _se_translator_function f = _set_se_translator(trans_func); - try { -#endif // SE_CATCH --------------------- try section -------------------- - if (setjmp(g->jumper[++g->jump_level])) { - goto fin; - } // endif rc + for (i = 0; i < len; i++) + switch (s[i]) { + case '[': + if (jsp) + goto tryit; + else if (!(jsp = ParseArray(g, ++i, src, pty))) + throw 1; -#if defined(SE_CATCH) // ------------- end of try section ----------------- -} catch (SE_Exception e) { - sprintf(g->Message, "ParseJson: exception doing setjmp: %s (rc=%hd)", - GetExceptionDesc(g, e.nSE), e.nSE); - _set_se_translator(f); - goto err; -} catch (...) { - strcpy(g->Message, "Exception doing setjmp"); - _set_se_translator(f); - goto err; -} // end of try-catches + break; + case '{': + if (jsp) + goto tryit; + else if (!(jsp = ParseObject(g, ++i, src, pty))) + throw 2; -_set_se_translator(f); -#endif // SE_CATCH -#endif // !USE_TRY + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + case ',': + if (jsp && (pretty == 1 || pretty == 3)) { + if (comma) + *comma = true; - for (i = 0; i < len; i++) - switch (s[i]) { - case '[': - if (jsp) - goto tryit; - else if (!(jsp = ParseArray(g, ++i, src, pty))) -#if defined(USE_TRY) - throw 1; -#else // !USE_TRY - goto fin; -#endif // !USE_TRY + pty[0] = pty[2] = false; + break; + } // endif pretty - break; - case '{': - if (jsp) - goto tryit; - else if (!(jsp = ParseObject(g, ++i, src, pty))) -#if defined(USE_TRY) - throw 2; -#else // !USE_TRY - goto fin; -#endif // !USE_TRY + sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty); + throw 3; + case '(': + b = true; + break; + case ')': + if (b) { + b = false; + break; + } // endif b - break; - case ' ': - case '\t': - case '\n': - case '\r': - break; - case ',': - if (jsp && (pretty == 1 || pretty == 3)) { - if (comma) - *comma = true; + default: + if (jsp) + goto tryit; + else if (!(jsp = ParseValue(g, i, src, pty))) + throw 4; - pty[0] = pty[2] = false; - break; - } // endif pretty + break; + }; // endswitch s[i] - sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty); -#if defined(USE_TRY) - throw 3; -#else // !USE_TRY - jsp = NULL; - goto fin; -#endif // !USE_TRY - case '(': - b = true; - break; - case ')': - if (b) { - b = false; - break; - } // endif b + if (!jsp) + sprintf(g->Message, "Invalid Json string '%.*s'", 50, s); + else if (ptyp && pretty == 3) { + *ptyp = 3; // Not recognized pretty - default: - if (jsp) - goto tryit; - else if (!(jsp = ParseValue(g, i, src, pty))) -#if defined(USE_TRY) - throw 4; -#else // !USE_TRY - goto fin; -#endif // !USE_TRY + for (i = 0; i < 3; i++) + if (pty[i]) { + *ptyp = i; + break; + } // endif pty - break; - }; // endswitch s[i] + } // endif ptyp - if (!jsp) - sprintf(g->Message, "Invalid Json string '%.*s'", 50, s); - else if (ptyp && pretty == 3) { - *ptyp = 3; // Not recognized pretty - - for (i = 0; i < 3; i++) - if (pty[i]) { - *ptyp = i; - break; - } // endif pty - - } // endif ptyp - -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -208,20 +155,12 @@ _set_se_translator(f); } // end catch return jsp; -#else // !USE_TRY -fin: - g->jump_level--; - return jsp; -#endif // !USE_TRY tryit: if (pty[0] && (!pretty || pretty > 2)) { if ((jsp = ParseArray(g, (i = 0), src, pty)) && ptyp && pretty == 3) *ptyp = (pty[0]) ? 0 : 3; -#if !defined(USE_TRY) - g->jump_level--; -#endif // !USE_TRY return jsp; } else strcpy(g->Message, "More than one item in file"); @@ -620,101 +559,75 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src) PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty) { PSZ str = NULL; - bool b = false, err = true; - JOUT *jp; + bool b = false, err = true; + JOUT *jp; FILE *fs = NULL; g->Message[0] = 0; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return NULL; - } // endif jump_level - - if (setjmp(g->jumper[++g->jump_level])) { - str = NULL; - goto fin; - } // endif jmp -#endif // !USE_TRY - - if (!jsp) { - strcpy(g->Message, "Null json tree"); -#if defined(USE_TRY) - throw 1; -#else // !USE_TRY - goto fin; -#endif // !USE_TRY - } else if (!fn) { - // Serialize to a string - jp = new(g) JOUTSTR(g); - b = pretty == 1; - } else { - if (!(fs = fopen(fn, "wb"))) { - sprintf(g->Message, MSG(OPEN_MODE_ERROR), - "w", (int)errno, fn); - strcat(strcat(g->Message, ": "), strerror(errno)); -#if defined(USE_TRY) - throw 2; -#else // !USE_TRY - goto fin; -#endif // !USE_TRY - } else if (pretty >= 2) { - // Serialize to a pretty file - jp = new(g)JOUTPRT(g, fs); + if (!jsp) { + strcpy(g->Message, "Null json tree"); + throw 1; + } else if (!fn) { + // Serialize to a string + jp = new(g) JOUTSTR(g); + b = pretty == 1; } else { - // Serialize to a flat file - b = true; - jp = new(g)JOUTFILE(g, fs, pretty); + if (!(fs = fopen(fn, "wb"))) { + sprintf(g->Message, MSG(OPEN_MODE_ERROR), + "w", (int)errno, fn); + strcat(strcat(g->Message, ": "), strerror(errno)); + throw 2; + } else if (pretty >= 2) { + // Serialize to a pretty file + jp = new(g)JOUTPRT(g, fs); + } else { + // Serialize to a flat file + b = true; + jp = new(g)JOUTFILE(g, fs, pretty); + } // endif's + + } // endif's + + switch (jsp->GetType()) { + case TYPE_JAR: + err = SerializeArray(jp, (PJAR)jsp, b); + break; + case TYPE_JOB: + err = ((b && jp->Prty()) && jp->WriteChr('\t')); + err |= SerializeObject(jp, (PJOB)jsp); + break; + case TYPE_JVAL: + err = SerializeValue(jp, (PJVAL)jsp); + break; + default: + strcpy(g->Message, "Invalid json tree"); + } // endswitch Type + + if (fs) { + fputs(EL, fs); + fclose(fs); + str = (err) ? NULL : strcpy(g->Message, "Ok"); + } else if (!err) { + str = ((JOUTSTR*)jp)->Strp; + jp->WriteChr('\0'); + PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N); + } else { + if (!g->Message[0]) + strcpy(g->Message, "Error in Serialize"); + } // endif's - } // endif's + } catch (int n) { + if (trace) + htrc("Exception %d: %s\n", n, g->Message); + str = NULL; + } catch (const char *msg) { + strcpy(g->Message, msg); + str = NULL; + } // end catch - switch (jsp->GetType()) { - case TYPE_JAR: - err = SerializeArray(jp, (PJAR)jsp, b); - break; - case TYPE_JOB: - err = ((b && jp->Prty()) && jp->WriteChr('\t')); - err |= SerializeObject(jp, (PJOB)jsp); - break; - case TYPE_JVAL: - err = SerializeValue(jp, (PJVAL)jsp); - break; - default: - strcpy(g->Message, "Invalid json tree"); - } // endswitch Type - - if (fs) { - fputs(EL, fs); - fclose(fs); - str = (err) ? NULL : strcpy(g->Message, "Ok"); - } else if (!err) { - str = ((JOUTSTR*)jp)->Strp; - jp->WriteChr('\0'); - PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N); - } else { - if (!g->Message[0]) - strcpy(g->Message, "Error in Serialize"); - - } // endif's - -#if defined(USE_TRY) -} catch (int n) { - if (trace) - htrc("Exception %d: %s\n", n, g->Message); - str = NULL; -} catch (const char *msg) { - strcpy(g->Message, msg); - str = NULL; -} // end catch -#else // !USE_TRY -fin: - g->jump_level--; -#endif // !USE_TRY return str; } // end of Serialize @@ -1023,7 +936,7 @@ return false; /***********************************************************************/ /* Add a new pair to an Object. */ /***********************************************************************/ -PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key) +PJPR JOBJECT::AddPair(PGLOBAL g, PCSZ key) { PJPR jpp = new(g) JPAIR(key); @@ -1109,7 +1022,7 @@ bool JOBJECT::Merge(PGLOBAL g, PJSON jsp) /***********************************************************************/ /* Set or add a value corresponding to the given key. */ /***********************************************************************/ -void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key) +void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PCSZ key) { PJPR jp; @@ -1129,7 +1042,7 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key) /***********************************************************************/ /* Delete a value corresponding to the given key. */ /***********************************************************************/ -void JOBJECT::DeleteKey(PSZ key) +void JOBJECT::DeleteKey(PCSZ key) { PJPR jp, *pjp = &First; @@ -1308,10 +1221,10 @@ JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON() /***********************************************************************/ /* Constructor for a given string. */ /***********************************************************************/ -JVALUE::JVALUE(PGLOBAL g, PSZ strp) : JSON() +JVALUE::JVALUE(PGLOBAL g, PCSZ strp) : JSON() { Jsp = NULL; - Value = AllocateValue(g, strp, TYPE_STRING); + Value = AllocateValue(g, (void*)strp, TYPE_STRING); Next = NULL; Del = false; } // end of JVALUE constructor @@ -1466,6 +1379,6 @@ void JVALUE::SetString(PGLOBAL g, PSZ s, short c) /***********************************************************************/ bool JVALUE::IsNull(void) { - return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true; + return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true; } // end of IsNull diff --git a/storage/connect/json.h b/storage/connect/json.h index 4ea169e1b18..49675ce8559 100644 --- a/storage/connect/json.h +++ b/storage/connect/json.h @@ -125,14 +125,14 @@ class JPAIR : public BLOCK { friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*); friend bool SerializeObject(JOUT *, PJOB); public: - JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;} + JPAIR(PCSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;} - inline PSZ GetKey(void) {return Key;} + inline PCSZ GetKey(void) {return Key;} inline PJVAL GetVal(void) {return Val;} inline PJPR GetNext(void) {return Next;} protected: - PSZ Key; // This pair key name + PCSZ Key; // This pair key name PJVAL Val; // To the value of the pair PJPR Next; // To the next pair }; // end of class JPAIR @@ -150,7 +150,7 @@ class JSON : public BLOCK { virtual JTYP GetValType(void) {X return TYPE_JSON;} virtual void InitArray(PGLOBAL g) {X} //virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL) {X return NULL;} - virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;} + virtual PJPR AddPair(PGLOBAL g, PCSZ key) {X return NULL;} virtual PJAR GetKeyList(PGLOBAL g) {X return NULL;} virtual PJVAL GetValue(const char *key) {X return NULL;} virtual PJOB GetObject(void) {return NULL;} @@ -166,13 +166,13 @@ class JSON : public BLOCK { virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;} virtual bool Merge(PGLOBAL g, PJSON jsp) { X return true; } virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) { X return true; } - virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X} + virtual void SetValue(PGLOBAL g, PJVAL jvp, PCSZ key) {X} virtual void SetValue(PVAL valp) {X} virtual void SetValue(PJSON jsp) {X} virtual void SetString(PGLOBAL g, PSZ s, short c) {X} virtual void SetInteger(PGLOBAL g, int n) {X} virtual void SetFloat(PGLOBAL g, double f) {X} - virtual void DeleteKey(char *k) {X} + virtual void DeleteKey(PCSZ k) {X} virtual bool DeleteValue(int i) {X return true;} virtual bool IsNull(void) {X return true;} @@ -195,14 +195,14 @@ class JOBJECT : public JSON { virtual void Clear(void) {First = Last = NULL; Size = 0;} virtual JTYP GetType(void) {return TYPE_JOB;} virtual PJPR GetFirst(void) {return First;} - virtual PJPR AddPair(PGLOBAL g, PSZ key); + virtual PJPR AddPair(PGLOBAL g, PCSZ key); virtual PJOB GetObject(void) {return this;} virtual PJVAL GetValue(const char* key); virtual PJAR GetKeyList(PGLOBAL g); virtual PSZ GetText(PGLOBAL g, PSZ text); virtual bool Merge(PGLOBAL g, PJSON jsp); - virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key); - virtual void DeleteKey(char *k); + virtual void SetValue(PGLOBAL g, PJVAL jvp, PCSZ key); + virtual void DeleteKey(PCSZ k); virtual bool IsNull(void); protected: @@ -253,7 +253,7 @@ class JVALUE : public JSON { JVALUE(PJSON jsp) : JSON() {Jsp = jsp; Value = NULL; Next = NULL; Del = false;} JVALUE(PGLOBAL g, PVAL valp); - JVALUE(PGLOBAL g, PSZ strp); + JVALUE(PGLOBAL g, PCSZ strp); using JSON::GetValue; using JSON::SetValue; diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 9ea391edae9..4e00703d9ef 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1455,7 +1455,7 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n, free(g->Sarea); if (!(g->Sarea = PlugAllocMem(g, ml))) { - char errmsg[256]; + char errmsg[MAX_STR]; sprintf(errmsg, MSG(WORK_AREA), g->Message); strcpy(g->Message, errmsg); @@ -1496,7 +1496,7 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i) /*********************************************************************************/ /* Make a valid key from the passed argument. */ /*********************************************************************************/ -static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) +static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) { if (args->arg_count > (unsigned)i) { int j = 0, n = args->attribute_lengths[i]; @@ -2253,7 +2253,8 @@ my_bool json_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) { - char *key, *str = NULL; + PCSZ key; + char *str = NULL; PGLOBAL g = (PGLOBAL)initid->ptr; if (g->Xchk) { @@ -2358,7 +2359,7 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endif Xchk if (!CheckMemory(g, initid, args, 1, false, true, true)) { - char *key; + PCSZ key; PJOB jobp; PJSON jsp, top; PJVAL jvp = MakeValue(g, args, 0, &top); @@ -2921,70 +2922,53 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result, if (g->N) { str = (char*)g->Activityp; - goto fin; + goto err; } else if (initid->const_item) g->N = 1; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - PUSH_WARNING(MSG(TOO_MANY_JUMPS)); - *is_null = 1; - return NULL; - } // endif jump_level - - if (setjmp(g->jumper[++g->jump_level])) { - PUSH_WARNING(g->Message); - str = NULL; - goto err; - } // endif rc -#endif // !USE_TRY - - if (!g->Xchk) { - if (CheckMemory(g, initid, args, 1, true)) { - PUSH_WARNING("CheckMemory error"); - goto err; - } else - jvp = MakeValue(g, args, 0); - - if ((p = jvp->GetString())) { - if (!(jsp = ParseJson(g, p, strlen(p)))) { - PUSH_WARNING(g->Message); + if (!g->Xchk) { + if (CheckMemory(g, initid, args, 1, true)) { + PUSH_WARNING("CheckMemory error"); goto err; - } // endif jsp + } else + jvp = MakeValue(g, args, 0); + + if ((p = jvp->GetString())) { + if (!(jsp = ParseJson(g, p, strlen(p)))) { + PUSH_WARNING(g->Message); + goto err; + } // endif jsp + + } else + jsp = jvp->GetJson(); + + if (g->Mrr) { // First argument is a constant + g->Xchk = jsp; + JsonMemSave(g); + } // endif Mrr } else - jsp = jvp->GetJson(); + jsp = (PJSON)g->Xchk; - if (g->Mrr) { // First argument is a constant - g->Xchk = jsp; - JsonMemSave(g); - } // endif Mrr + path = MakePSZ(g, args, 1); + jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length); - } else - jsp = (PJSON)g->Xchk; + if (jsx->SetJpath(g, path)) { + PUSH_WARNING(g->Message); + goto err; + } // endif SetJpath - path = MakePSZ(g, args, 1); - jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length); + jsx->ReadValue(g); - if (jsx->SetJpath(g, path)) { - PUSH_WARNING(g->Message); - goto err; - } // endif SetJpath + if (!jsx->GetValue()->IsNull()) + str = jsx->GetValue()->GetCharValue(); - jsx->ReadValue(g); + if (initid->const_item) + // Keep result of constant function + g->Activityp = (PACTIVITY)str; - if (!jsx->GetValue()->IsNull()) - str = jsx->GetValue()->GetCharValue(); - - if (initid->const_item) - // Keep result of constant function - g->Activityp = (PACTIVITY)str; - -#if defined(USE_TRY) - } catch (int n) { + } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); PUSH_WARNING(g->Message); @@ -2996,12 +2980,6 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result, } // end catch err: -#else // !USE_TRY - err: - g->jump_level--; -#endif // !USE_TRY - - fin: if (!str) { *is_null = 1; *res_length = 0; @@ -3292,64 +3270,45 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result, } else if (initid->const_item) g->N = 1; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - PUSH_WARNING(MSG(TOO_MANY_JUMPS)); - *error = 1; - *is_null = 1; - return NULL; - } // endif jump_level - - if (setjmp(g->jumper[++g->jump_level])) { - PUSH_WARNING(g->Message); - *error = 1; - path = NULL; - goto err; - } // endif rc -#endif // !USE_TRY - - if (!g->Xchk) { - if (CheckMemory(g, initid, args, 1, !g->Xchk)) { - PUSH_WARNING("CheckMemory error"); - *error = 1; - goto err; - } else - jvp = MakeValue(g, args, 0); - - if ((p = jvp->GetString())) { - if (!(jsp = ParseJson(g, p, strlen(p)))) { - PUSH_WARNING(g->Message); + if (!g->Xchk) { + if (CheckMemory(g, initid, args, 1, !g->Xchk)) { + PUSH_WARNING("CheckMemory error"); + *error = 1; goto err; - } // endif jsp + } else + jvp = MakeValue(g, args, 0); + + if ((p = jvp->GetString())) { + if (!(jsp = ParseJson(g, p, strlen(p)))) { + PUSH_WARNING(g->Message); + goto err; + } // endif jsp + + } else + jsp = jvp->GetJson(); + + if (g->Mrr) { // First argument is a constant + g->Xchk = jsp; + JsonMemSave(g); + } // endif Mrr } else - jsp = jvp->GetJson(); + jsp = (PJSON)g->Xchk; - if (g->Mrr) { // First argument is a constant - g->Xchk = jsp; - JsonMemSave(g); - } // endif Mrr + // The item to locate + jvp2 = MakeValue(g, args, 1); - } else - jsp = (PJSON)g->Xchk; + k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1; - // The item to locate - jvp2 = MakeValue(g, args, 1); + jsx = new(g) JSNX(g, jsp, TYPE_STRING); + path = jsx->Locate(g, jsp, jvp2, k); - k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1; + if (initid->const_item) + // Keep result of constant function + g->Activityp = (PACTIVITY)path; - jsx = new(g) JSNX(g, jsp, TYPE_STRING); - path = jsx->Locate(g, jsp, jvp2, k); - - if (initid->const_item) - // Keep result of constant function - g->Activityp = (PACTIVITY)path; - -#if defined(USE_TRY) - } catch (int n) { + } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); PUSH_WARNING(g->Message); @@ -3363,11 +3322,6 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result, } // end catch err: -#else // !USE_TRY - err: - g->jump_level--; -#endif // !USE_TRY - if (!path) { *res_length = 0; *is_null = 1; @@ -3439,65 +3393,46 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result, } else if (initid->const_item) g->N = 1; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - PUSH_WARNING(MSG(TOO_MANY_JUMPS)); - *error = 1; - *is_null = 1; - return NULL; - } // endif jump_level - - if (setjmp(g->jumper[++g->jump_level])) { - PUSH_WARNING(g->Message); - *error = 1; - path = NULL; - goto err; - } // endif rc -#endif // !USE_TRY - - if (!g->Xchk) { - if (CheckMemory(g, initid, args, 1, true)) { - PUSH_WARNING("CheckMemory error"); - *error = 1; - goto err; - } else - jvp = MakeValue(g, args, 0); - - if ((p = jvp->GetString())) { - if (!(jsp = ParseJson(g, p, strlen(p)))) { - PUSH_WARNING(g->Message); + if (!g->Xchk) { + if (CheckMemory(g, initid, args, 1, true)) { + PUSH_WARNING("CheckMemory error"); + *error = 1; goto err; - } // endif jsp + } else + jvp = MakeValue(g, args, 0); + + if ((p = jvp->GetString())) { + if (!(jsp = ParseJson(g, p, strlen(p)))) { + PUSH_WARNING(g->Message); + goto err; + } // endif jsp + + } else + jsp = jvp->GetJson(); + + if (g->Mrr) { // First argument is a constant + g->Xchk = jsp; + JsonMemSave(g); + } // endif Mrr } else - jsp = jvp->GetJson(); + jsp = (PJSON)g->Xchk; - if (g->Mrr) { // First argument is a constant - g->Xchk = jsp; - JsonMemSave(g); - } // endif Mrr + // The item to locate + jvp2 = MakeValue(g, args, 1); - } else - jsp = (PJSON)g->Xchk; + if (args->arg_count > 2) + mx = (int)*(long long*)args->args[2]; - // The item to locate - jvp2 = MakeValue(g, args, 1); + jsx = new(g) JSNX(g, jsp, TYPE_STRING); + path = jsx->LocateAll(g, jsp, jvp2, mx); - if (args->arg_count > 2) - mx = (int)*(long long*)args->args[2]; + if (initid->const_item) + // Keep result of constant function + g->Activityp = (PACTIVITY)path; - jsx = new(g) JSNX(g, jsp, TYPE_STRING); - path = jsx->LocateAll(g, jsp, jvp2, mx); - - if (initid->const_item) - // Keep result of constant function - g->Activityp = (PACTIVITY)path; - -#if defined(USE_TRY) - } catch (int n) { + } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); PUSH_WARNING(g->Message); @@ -3511,11 +3446,6 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result, } // end catch err: -#else // !USE_TRY - err: - g->jump_level--; -#endif // !USE_TRY - if (!path) { *res_length = 0; *is_null = 1; @@ -3722,87 +3652,61 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, goto fin; } // endelse -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - PUSH_WARNING(MSG(TOO_MANY_JUMPS)); - *error = 1; - goto fin; - } // endif jump_level + if (!g->Xchk) { + if (CheckMemory(g, initid, args, 1, true, false, true)) { + PUSH_WARNING("CheckMemory error"); + throw 1; + } else + jvp = MakeValue(g, args, 0); - if (setjmp(g->jumper[++g->jump_level])) { - PUSH_WARNING(g->Message); - str = NULL; - goto err; - } // endif rc -#endif // !USE_TRY + if ((p = jvp->GetString())) { + if (!(jsp = ParseJson(g, p, strlen(p)))) { + throw 2; + } // endif jsp + + } else + jsp = jvp->GetJson(); + + if (g->Mrr) { // First argument is a constant + g->Xchk = jsp; + JsonMemSave(g); + } // endif Mrr - if (!g->Xchk) { - if (CheckMemory(g, initid, args, 1, true, false, true)) { - PUSH_WARNING("CheckMemory error"); -#if defined(USE_TRY) - throw 1; -#else // !USE_TRY - goto err; -#endif // !USE_TRY } else - jvp = MakeValue(g, args, 0); + jsp = (PJSON)g->Xchk; - if ((p = jvp->GetString())) { - if (!(jsp = ParseJson(g, p, strlen(p)))) { -#if defined(USE_TRY) - throw 2; -#else // !USE_TRY + jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true); + + for (uint i = 1; i + 1 < args->arg_count; i += 2) { + jvp = MakeValue(gb, args, i); + path = MakePSZ(g, args, i + 1); + + if (jsx->SetJpath(g, path, false)) { PUSH_WARNING(g->Message); - goto err; -#endif // !USE_TRY - } // endif jsp + continue; + } // endif SetJpath - } else - jsp = jvp->GetJson(); + if (w) { + jsx->ReadValue(g); + b = jsx->GetValue()->IsNull(); + b = (w == 1) ? b : !b; + } // endif w - if (g->Mrr) { // First argument is a constant - g->Xchk = jsp; - JsonMemSave(g); - } // endif Mrr + if (b && jsx->WriteValue(gb, jvp)) + PUSH_WARNING(g->Message); - } else - jsp = (PJSON)g->Xchk; + } // endfor i - jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true); + // In case of error or file, return unchanged argument + if (!(str = MakeResult(g, args, jsp, INT_MAX32))) + str = MakePSZ(g, args, 0); - for (uint i = 1; i+1 < args->arg_count; i += 2) { - jvp = MakeValue(gb, args, i); - path = MakePSZ(g, args, i+1); + if (g->N) + // Keep result of constant function + g->Activityp = (PACTIVITY)str; - if (jsx->SetJpath(g, path, false)) { - PUSH_WARNING(g->Message); - continue; - } // endif SetJpath - - if (w) { - jsx->ReadValue(g); - b = jsx->GetValue()->IsNull(); - b = (w == 1) ? b : !b; - } // endif w - - if (b && jsx->WriteValue(gb, jvp)) - PUSH_WARNING(g->Message); - - } // endfor i - - // In case of error or file, return unchanged argument - if (!(str = MakeResult(g, args, jsp, INT_MAX32))) - str = MakePSZ(g, args, 0); - - if (g->N) - // Keep result of constant function - g->Activityp = (PACTIVITY)str; - -#if defined(USE_TRY) - } catch (int n) { + } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); PUSH_WARNING(g->Message); @@ -3812,10 +3716,6 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, PUSH_WARNING(g->Message); str = NULL; } // end catch -#else // !USE_TRY -err: - g->jump_level--; -#endif // !USE_TRY fin: if (!str) { @@ -4642,7 +4542,7 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endif bsp if (!CheckMemory(g, initid, args, 2, false, true, true)) { - char *key; + PCSZ key; PJOB jobp; PJVAL jvp = MakeValue(g, args, 0, &top); PJSON jsp = jvp->GetJson(); @@ -4722,7 +4622,7 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endif bsp if (!CheckMemory(g, initid, args, 1, false, true, true)) { - char *key; + PCSZ key; PJOB jobp; PJVAL jvp = MakeValue(g, args, 0, &top); PJSON jsp = jvp->GetJson(); diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h index d2890421c62..5f4b98a0652 100644 --- a/storage/connect/jsonudf.h +++ b/storage/connect/jsonudf.h @@ -232,7 +232,7 @@ extern "C" { /*********************************************************************************/ typedef struct _jpn { enum JTYP Type; - PSZ Key; + PCSZ Key; int N; } JPN, *PJPN; diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp index 2470d37c353..700d247da38 100644 --- a/storage/connect/libdoc.cpp +++ b/storage/connect/libdoc.cpp @@ -68,9 +68,9 @@ class LIBXMLDOC : public XMLDOCUMENT { virtual void SetNofree(bool b) {Nofreelist = b;} // Methods - virtual bool Initialize(PGLOBAL g, char *entry, bool zipped); + virtual bool Initialize(PGLOBAL g, PCSZ entry, bool zipped); virtual bool ParseFile(PGLOBAL g, char *fn); - virtual bool NewDoc(PGLOBAL g, char *ver); + virtual bool NewDoc(PGLOBAL g, PCSZ ver); virtual void AddComment(PGLOBAL g, char *com); virtual PXNODE GetRoot(PGLOBAL g); virtual PXNODE NewRoot(PGLOBAL g, char *name); @@ -119,9 +119,9 @@ class XML2NODE : public XMLNODE { virtual PXLIST SelectNodes(PGLOBAL g, char *xp, PXLIST lp); virtual PXNODE SelectSingleNode(PGLOBAL g, char *xp, PXNODE np); virtual PXATTR GetAttribute(PGLOBAL g, char *name, PXATTR ap); - virtual PXNODE AddChildNode(PGLOBAL g, char *name, PXNODE np); + virtual PXNODE AddChildNode(PGLOBAL g, PCSZ name, PXNODE np); virtual PXATTR AddProperty(PGLOBAL g, char *name, PXATTR ap); - virtual void AddText(PGLOBAL g, char *txtp); + virtual void AddText(PGLOBAL g, PCSZ txtp); virtual void DeleteChild(PGLOBAL g, PXNODE dnp); protected: @@ -373,7 +373,7 @@ LIBXMLDOC::LIBXMLDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp) /******************************************************************/ /* Initialize XML parser and check library compatibility. */ /******************************************************************/ -bool LIBXMLDOC::Initialize(PGLOBAL g, char *entry, bool zipped) +bool LIBXMLDOC::Initialize(PGLOBAL g, PCSZ entry, bool zipped) { if (zipped && InitZip(g, entry)) return true; @@ -434,7 +434,7 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn) /******************************************************************/ /* Construct and add the XML processing instruction node. */ /******************************************************************/ -bool LIBXMLDOC::NewDoc(PGLOBAL g, char *ver) +bool LIBXMLDOC::NewDoc(PGLOBAL g, PCSZ ver) { if (trace) htrc("NewDoc\n"); @@ -863,14 +863,13 @@ RCODE XML2NODE::GetContent(PGLOBAL g, char *buf, int len) xmlFree(Content); if ((Content = xmlNodeGetContent(Nodep))) { - char *extra = " \t\r\n"; char *p1 = (char*)Content, *p2 = buf; bool b = false; // Copy content eliminating extra characters for (; *p1; p1++) if ((p2 - buf) < len) { - if (strchr(extra, *p1)) { + if (strchr(" \t\r\n", *p1)) { if (b) { // This to have one blank between sub-nodes *p2++ = ' '; @@ -1020,19 +1019,19 @@ PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap) /******************************************************************/ /* Add a new child node to this node and return it. */ /******************************************************************/ -PXNODE XML2NODE::AddChildNode(PGLOBAL g, char *name, PXNODE np) +PXNODE XML2NODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np) { - char *p, *pn, *pf = NULL; + char *p, *pn, *pf = NULL, *nmp = PlugDup(g, name); if (trace) htrc("AddChildNode: %s\n", name); // Is a prefix specified - if ((pn = strchr(name, ':'))) { - pf = name; + if ((pn = strchr(nmp, ':'))) { + pf = nmp; *pn++ = '\0'; // Separate name from prefix } else - pn = name; + pn = nmp; // If name has the format m[n] only m is taken as node name if ((p = strchr(pn, '['))) @@ -1096,7 +1095,7 @@ PXATTR XML2NODE::AddProperty(PGLOBAL g, char *name, PXATTR ap) /******************************************************************/ /* Add a new text node to this node. */ /******************************************************************/ -void XML2NODE::AddText(PGLOBAL g, char *txtp) +void XML2NODE::AddText(PGLOBAL g, PCSZ txtp) { if (trace) htrc("AddText: %s\n", txtp); diff --git a/storage/connect/macutil.cpp b/storage/connect/macutil.cpp index f5d3bb11fe9..b9600bdac2e 100644 --- a/storage/connect/macutil.cpp +++ b/storage/connect/macutil.cpp @@ -192,7 +192,7 @@ bool MACINFO::GetOneInfo(PGLOBAL g, int flag, void *v, int lv) case 23: break; default: - p = ""; + p = PlugDup(g, ""); } // endswitch flag } else switch (flag) { diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 30ac7613dd6..750cf3c0639 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /*************** Mycat CC Program Source Code File (.CC) ***************/ /* PROGRAM NAME: MYCAT */ @@ -161,7 +161,7 @@ TABTYPE GetTypeID(const char *type) #ifdef ZIP_SUPPORT : (!stricmp(type, "ZIP")) ? TAB_ZIP #endif - : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; + : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; } // end of GetTypeID /***********************************************************************/ @@ -477,39 +477,6 @@ void MYCAT::Reset(void) { } // end of Reset -#if 0 -/***********************************************************************/ -/* This function sets the current database path. */ -/***********************************************************************/ -void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path) - { - if (path) { - size_t len= strlen(path) + (*path != '.' ? 4 : 1); - char *buf= (char*)PlugSubAlloc(g, NULL, len); - - if (PlugIsAbsolutePath(path)) - { - strcpy(buf, path); - *datapath= buf; - return; - } - - if (*path != '.') { -#if defined(__WIN__) - char *s= "\\"; -#else // !__WIN__ - char *s= "/"; -#endif // !__WIN__ - strcat(strcat(strcat(strcpy(buf, "."), s), path), s); - } else - strcpy(buf, path); - - *datapath= buf; - } // endif path - - } // end of SetDataPath -#endif // 0 - /***********************************************************************/ /* GetTableDesc: retrieve a table descriptor. */ /* Look for a table descriptor matching the name and type. */ diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h index 663b68fd4b9..b6bdd5e5e11 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /**************** MYCAT H Declares Source Code File (.H) ***************/ /* Name: MYCAT.H Version 2.3 */ @@ -98,10 +98,7 @@ class MYCAT : public CATALOG { // Methods void Reset(void); -//void SetDataPath(PGLOBAL g, const char *path) -// {SetPath(g, &DataPath, path);} bool StoreIndex(PGLOBAL, PTABDEF) {return false;} // Temporary -// PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name, PRELDEF GetTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR type, PRELDEF *prp = NULL); PTDB GetTable(PGLOBAL g, PTABLE tablep, @@ -109,9 +106,7 @@ class MYCAT : public CATALOG { void ClearDB(PGLOBAL g); protected: -// PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am); PRELDEF MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am); - //void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path); // Members ha_connect *Hc; // The Connect handler diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index f7cd245df59..e68489faad5 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -137,7 +137,8 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db, FLD_CHARSET}; //unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0}; unsigned int length[] = {0, 4, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0}; - char *fld, *colname, *chset, *fmt, v, buf[128], uns[16], zero[16]; + PCSZ fmt; + char *fld, *colname, *chset, v, buf[128], uns[16], zero[16]; int i, n, nf, ncol = sizeof(buftyp) / sizeof(int); int len, type, prec, rc, k = 0; bool b; @@ -874,7 +875,8 @@ MYSQL_FIELD *MYSQLC::GetNextField(void) /***********************************************************************/ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) { - char *fmt, v; + PCSZ fmt; + char *name, v; int n; bool uns; PCOLRES *pcrp, crp; @@ -912,8 +914,9 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) memset(crp, 0, sizeof(COLRES)); crp->Ncol = ++qrp->Nbcol; - crp->Name = (char*)PlugSubAlloc(g, NULL, fld->name_length + 1); - strcpy(crp->Name, fld->name); + name = (char*)PlugSubAlloc(g, NULL, fld->name_length + 1); + strcpy(name, fld->name); + crp->Name = name; if ((crp->Type = MYSQLtoPLG(fld->type, &v)) == TYPE_ERROR) { sprintf(g->Message, "Type %d not supported for column %s", diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp index 5fcc914f632..c2053f1c832 100644 --- a/storage/connect/myutil.cpp +++ b/storage/connect/myutil.cpp @@ -269,9 +269,9 @@ int MYSQLtoPLG(int mytype, char *var) /************************************************************************/ /* Returns the format corresponding to a MySQL date type number. */ /************************************************************************/ -char *MyDateFmt(int mytype) +PCSZ MyDateFmt(int mytype) { - char *fmt; + PCSZ fmt; switch (mytype) { case MYSQL_TYPE_TIMESTAMP: @@ -297,9 +297,9 @@ char *MyDateFmt(int mytype) /************************************************************************/ /* Returns the format corresponding to a MySQL date type name. */ /************************************************************************/ -char *MyDateFmt(char *typname) +PCSZ MyDateFmt(char *typname) { - char *fmt; + PCSZ fmt; if (!stricmp(typname, "datetime") || !stricmp(typname, "timestamp")) fmt = "YYYY-MM-DD hh:mm:ss"; diff --git a/storage/connect/myutil.h b/storage/connect/myutil.h index 9c22cfef118..6991172b39e 100644 --- a/storage/connect/myutil.h +++ b/storage/connect/myutil.h @@ -6,9 +6,9 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf, char var = 0); const char *PLGtoMYSQLtype(int type, bool dbf, char var = 0); -int MYSQLtoPLG(char *typname, char *var = NULL); -int MYSQLtoPLG(int mytype, char *var = NULL); -char *MyDateFmt(int mytype); -char *MyDateFmt(char *typname); +int MYSQLtoPLG(char *typname, char *var = NULL); +int MYSQLtoPLG(int mytype, char *var = NULL); +PCSZ MyDateFmt(int mytype); +PCSZ MyDateFmt(char *typname); #endif // __MYUTIL__H diff --git a/storage/connect/odbccat.h b/storage/connect/odbccat.h index 3b729bcb4bb..05b82e49727 100644 --- a/storage/connect/odbccat.h +++ b/storage/connect/odbccat.h @@ -3,11 +3,11 @@ #define DEFAULT_QUERY_TIMEOUT -1 // means do not set typedef struct odbc_parms { - char *User; // User connect info - char *Pwd; // Password connect info - int Cto; // Connect timeout - int Qto; // Query timeout - bool UseCnc; // Use SQLConnect (!SQLDriverConnect) + PCSZ User; // User connect info + PCSZ Pwd; // Password connect info + int Cto; // Connect timeout + int Qto; // Query timeout + bool UseCnc; // Use SQLConnect (!SQLDriverConnect) } ODBCPARM, *POPARM; /***********************************************************************/ @@ -17,9 +17,9 @@ typedef struct odbc_parms { char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop); #endif // PROMPT_OK PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info); -PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, - char *colpat, int maxres, bool info, POPARM sop); +PQRYRES ODBCColumns(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ table, + PCSZ colpat, int maxres, bool info, POPARM sop); PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop); -PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, - char *tabtyp, int maxres, bool info, POPARM sop); +PQRYRES ODBCTables(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ tabpat, + PCSZ tabtyp, int maxres, bool info, POPARM sop); PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info); diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index cf55846765f..3dbc2d577d5 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -239,62 +239,43 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop) /***********************************************************************/ /* Allocate the structure used to refer to the result set. */ /***********************************************************************/ -static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *db, - char *tab, PQRYRES qrp) - { - size_t i, m, n; - CATPARM *cap; +static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, PCSZ db, + PCSZ tab, PQRYRES qrp) +{ + size_t i, m, n; + CATPARM *cap; #if defined(_DEBUG) - assert(qrp); + assert(qrp); #endif -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return NULL; - } // endif jump_level + m = (size_t)qrp->Maxres; + n = (size_t)qrp->Nbcol; + cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM)); + memset(cap, 0, sizeof(CATPARM)); + cap->Id = fid; + cap->Qrp = qrp; + cap->DB = db; + cap->Tab = tab; + cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *)); - if (setjmp(g->jumper[++g->jump_level]) != 0) { + for (i = 0; i < n; i++) + cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN)); + + cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD)); + + } catch (int n) { + htrc("Exeption %d: %s\n", n, g->Message); + cap = NULL; + } catch (const char *msg) { + htrc(g->Message, msg); printf("%s\n", g->Message); cap = NULL; - goto fin; - } // endif rc -#endif // !USE_TRY + } // end catch - m = (size_t)qrp->Maxres; - n = (size_t)qrp->Nbcol; - cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM)); - memset(cap, 0, sizeof(CATPARM)); - cap->Id = fid; - cap->Qrp = qrp; - cap->DB = (PUCHAR)db; - cap->Tab = (PUCHAR)tab; - cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *)); - - for (i = 0; i < n; i++) - cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN)); - - cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD)); - -#if defined(USE_TRY) -} catch (int n) { - htrc("Exeption %d: %s\n", n, g->Message); - cap = NULL; -} catch (const char *msg) { - htrc(g->Message, msg); - printf("%s\n", g->Message); - cap = NULL; -} // end catch -#else // !USE_TRY - fin: - g->jump_level--; -#endif // !USE_TRY return cap; - } // end of AllocCatInfo +} // end of AllocCatInfo #if 0 /***********************************************************************/ @@ -324,8 +305,8 @@ static void ResetNullValues(CATPARM *cap) /* ODBCColumns: constructs the result blocks containing all columns */ /* of an ODBC table that will be retrieved by GetData commands. */ /***********************************************************************/ -PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, - char *colpat, int maxres, bool info, POPARM sop) +PQRYRES ODBCColumns(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ table, + PCSZ colpat, int maxres, bool info, POPARM sop) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, @@ -398,7 +379,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, if (!(cap = AllocCatInfo(g, CAT_COL, db, table, qrp))) return NULL; - cap->Pat = (PUCHAR)colpat; + cap->Pat = colpat; /************************************************************************/ /* Now get the results into blocks. */ @@ -633,8 +614,8 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info) /* ODBCTables: constructs the result blocks containing all tables in */ /* an ODBC database that will be retrieved by GetData commands. */ /**************************************************************************/ -PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, - char *tabtyp, int maxres, bool info, POPARM sop) +PQRYRES ODBCTables(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ tabpat, PCSZ tabtyp, + int maxres, bool info, POPARM sop) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING}; @@ -696,7 +677,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp))) return NULL; - cap->Pat = (PUCHAR)tabtyp; + cap->Pat = tabtyp; if (trace) htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol); @@ -894,7 +875,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, /***********************************************************************/ /* Implementation of DBX class. */ /***********************************************************************/ -DBX::DBX(RETCODE rc, PSZ msg) +DBX::DBX(RETCODE rc, PCSZ msg) { m_RC = rc; m_Msg = msg; @@ -1035,7 +1016,7 @@ bool ODBConn::Check(RETCODE rc) /***********************************************************************/ /* DB exception throw routines. */ /***********************************************************************/ -void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt) +void ODBConn::ThrowDBX(RETCODE rc, PCSZ msg, HSTMT hstmt) { DBX* xp = new(m_G) DBX(rc, msg); @@ -1045,7 +1026,7 @@ void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt) } // end of ThrowDBX -void ODBConn::ThrowDBX(PSZ msg) +void ODBConn::ThrowDBX(PCSZ msg) { DBX* xp = new(m_G) DBX(0, "Error"); @@ -1125,7 +1106,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt) /***********************************************************************/ /* Open: connect to a data source. */ /***********************************************************************/ -int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options) +int ODBConn::Open(PCSZ ConnectString, POPARM sop, DWORD options) { PGLOBAL& g = m_G; //ASSERT_VALID(this); @@ -1207,7 +1188,7 @@ void ODBConn::AllocConnect(DWORD Options) #if defined(_DEBUG) if (Options & traceSQL) { - SQLSetConnectOption(m_hdbc, SQL_OPT_TRACEFILE, (DWORD)"xodbc.out"); + SQLSetConnectOption(m_hdbc, SQL_OPT_TRACEFILE, (SQLULEN)"xodbc.out"); SQLSetConnectOption(m_hdbc, SQL_OPT_TRACE, 1); } // endif #endif // _DEBUG @@ -1230,7 +1211,7 @@ void ODBConn::AllocConnect(DWORD Options) // Turn on cursor lib support if (Options & useCursorLib) - rc = SQLSetConnectOption(m_hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_ODBC); + rc = SQLSetConnectOption(m_hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_DRIVER); return; } // end of AllocConnect @@ -1936,7 +1917,7 @@ bool ODBConn::ExecSQLcommand(char *sql) /* GetMetaData: constructs the result blocks containing the */ /* description of all the columns of an SQL command. */ /**************************************************************************/ -PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src) +PQRYRES ODBConn::GetMetaData(PGLOBAL g, PCSZ dsn, PCSZ src) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_INT, TYPE_SHORT, TYPE_SHORT}; @@ -2259,7 +2240,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) void *buffer; int i, irc; bool b; - PSZ fnc = "Unknown"; + PCSZ fnc = "Unknown"; UWORD n; SWORD ncol, len, tp; SQLULEN crow = 0; @@ -2298,22 +2279,20 @@ int ODBConn::GetCatInfo(CATPARM *cap) // Now do call the proper ODBC API switch (cap->Id) { case CAT_TAB: -// rc = SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID, -// (SQLPOINTER)false, 0); fnc = "SQLTables"; rc = SQLTables(hstmt, name.ptr(2), name.length(2), name.ptr(1), name.length(1), name.ptr(0), name.length(0), - cap->Pat, cap->Pat ? SQL_NTS : 0); + (SQLCHAR *)cap->Pat, + cap->Pat ? SQL_NTS : 0); break; case CAT_COL: -// rc = SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID, -// (SQLPOINTER)true, 0); fnc = "SQLColumns"; rc = SQLColumns(hstmt, name.ptr(2), name.length(2), name.ptr(1), name.length(1), name.ptr(0), name.length(0), - cap->Pat, cap->Pat ? SQL_NTS : 0); + (SQLCHAR *)cap->Pat, + cap->Pat ? SQL_NTS : 0); break; case CAT_KEY: fnc = "SQLPrimaryKeys"; diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h index 063985218ec..5abb8354160 100644 --- a/storage/connect/odbconn.h +++ b/storage/connect/odbconn.h @@ -54,9 +54,9 @@ enum CATINFO {CAT_TAB = 1, /* SQLTables */ typedef struct tagCATPARM { CATINFO Id; // Id to indicate function PQRYRES Qrp; // Result set pointer - PUCHAR DB; // Database (Schema) - PUCHAR Tab; // Table name or pattern - PUCHAR Pat; // Table type or column pattern + PCSZ DB; // Database (Schema) + PCSZ Tab; // Table name or pattern + PCSZ Pat; // Table type or column pattern SQLLEN* *Vlen; // To array of indicator values UWORD *Status; // To status block // For SQLStatistics @@ -80,23 +80,23 @@ class DBX : public BLOCK { friend class ODBConn; // Construction (by ThrowDBX only) -- destruction protected: - DBX(RETCODE rc, PSZ msg = NULL); + DBX(RETCODE rc, PCSZ msg = NULL); public: //virtual ~DBX() {} //void operator delete(void*, PGLOBAL, void*) {}; // Implementation (use ThrowDBX to create) RETCODE GetRC(void) {return m_RC;} - PSZ GetMsg(void) {return m_Msg;} - const char *GetErrorMessage(int i); + PCSZ GetMsg(void) {return m_Msg;} + PCSZ GetErrorMessage(int i); protected: bool BuildErrorMessage(ODBConn* pdb, HSTMT hstmt = SQL_NULL_HSTMT); // Attributes RETCODE m_RC; - PSZ m_Msg; - PSZ m_ErrMsg[MAX_NUM_OF_MSG]; + PCSZ m_Msg; + PCSZ m_ErrMsg[MAX_NUM_OF_MSG]; }; // end of DBX class definition /***********************************************************************/ @@ -119,7 +119,7 @@ class ODBConn : public BLOCK { noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog forceOdbcDialog = 0x0010}; // Always display ODBC connect dialog - int Open(PSZ ConnectString, POPARM sop, DWORD Options = 0); + int Open(PCSZ ConnectString, POPARM sop, DWORD Options = 0); int Rewind(char *sql, ODBCCOL *tocols); void Close(void); PQRYRES AllocateResult(PGLOBAL g); @@ -131,7 +131,7 @@ class ODBConn : public BLOCK { bool IsOpen(void) {return m_hdbc != SQL_NULL_HDBC;} PSZ GetStringInfo(ushort infotype); int GetMaxValue(ushort infotype); - PSZ GetConnect(void) {return m_Connect;} + PCSZ GetConnect(void) {return m_Connect;} public: // Operations @@ -149,7 +149,7 @@ class ODBConn : public BLOCK { int GetCatInfo(CATPARM *cap); bool GetDataSources(PQRYRES qrp); bool GetDrivers(PQRYRES qrp); - PQRYRES GetMetaData(PGLOBAL g, char *dsn, char *src); + PQRYRES GetMetaData(PGLOBAL g, PCSZ dsn, PCSZ src); public: // Set special options @@ -162,8 +162,8 @@ class ODBConn : public BLOCK { // ODBC operations protected: bool Check(RETCODE rc); - void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT); - void ThrowDBX(PSZ msg); + void ThrowDBX(RETCODE rc, PCSZ msg, HSTMT hstmt = SQL_NULL_HSTMT); + void ThrowDBX(PCSZ msg); void AllocConnect(DWORD dwOptions); void Connect(void); bool DriverConnect(DWORD Options); @@ -187,9 +187,9 @@ class ODBConn : public BLOCK { DWORD m_UpdateOptions; DWORD m_RowsetSize; char m_IDQuoteChar[2]; - PSZ m_Connect; - PSZ m_User; - PSZ m_Pwd; + PCSZ m_Connect; + PCSZ m_User; + PCSZ m_Pwd; int m_Catver; int m_Rows; int m_Fetch; diff --git a/storage/connect/os.h b/storage/connect/os.h index 2dc603fdcda..8056a272990 100644 --- a/storage/connect/os.h +++ b/storage/connect/os.h @@ -17,13 +17,16 @@ typedef off_t off64_t; #if defined(__WIN__) typedef __int64 BIGINT; +typedef _Null_terminated_ const char *PCSZ; #else // !__WIN__ typedef longlong BIGINT; #define FILE_BEGIN SEEK_SET #define FILE_CURRENT SEEK_CUR #define FILE_END SEEK_END +typedef const char *PCSZ; #endif // !__WIN__ + #if !defined(__WIN__) typedef const void *LPCVOID; typedef const char *LPCTSTR; diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 800b1098d50..2198c44c200 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -80,7 +80,8 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */ TAB_DMY = 25, /* DMY Dummy tables NIY */ TAB_JDBC = 26, /* Table accessed via JDBC */ TAB_ZIP = 27, /* ZIP file info table */ - TAB_NIY = 28}; /* Table not implemented yet */ +// TAB_MONGO = 28, /* Table retrieved from MongoDB */ + TAB_NIY = 30}; /* Table not implemented yet */ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */ TYPE_AM_ROWID = 1, /* ROWID type (special column) */ @@ -143,7 +144,8 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */ TYPE_AM_MYX = 193, /* MYSQL EXEC access method type */ TYPE_AM_CAT = 195, /* Catalog access method type no */ TYPE_AM_ZIP = 198, /* ZIP access method type no */ - TYPE_AM_OUT = 200}; /* Output relations (storage) */ + TYPE_AM_MGO = 199, /* MGO access method type no */ + TYPE_AM_OUT = 200}; /* Output relations (storage) */ enum RECFM {RECFM_NAF = -2, /* Not a file */ RECFM_OEM = -1, /* OEM file access method */ @@ -553,7 +555,7 @@ typedef struct _qryres { typedef struct _colres { PCOLRES Next; /* To next result column */ PCOL Colp; /* To matching column block */ - PSZ Name; /* Column header */ + PCSZ Name; /* Column header */ PVBLK Kdata; /* Column block of values */ char *Nulls; /* Column null value array */ int Type; /* Internal type */ @@ -583,7 +585,7 @@ void PlugLineDB(PGLOBAL, PSZ, short, void *, uint); char *SetPath(PGLOBAL g, const char *path); char *ExtractFromPath(PGLOBAL, char *, char *, OPVAL); void AddPointer(PTABS, void *); -PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int); +PDTP MakeDateFormat(PGLOBAL, PCSZ, bool, bool, int); int ExtractDate(char *, PDTP, int, int val[6]); /**************************************************************************/ @@ -615,11 +617,10 @@ DllExport void *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t); DllExport void NewPointer(PTABS, void *, void *); //lExport char *GetIni(int n= 0); // Not used anymore DllExport void SetTrc(void); -DllExport char *GetListOption(PGLOBAL, const char *, const char *, - const char *def=NULL); -DllExport char *GetStringTableOption(PGLOBAL, PTOS, char *, char *); -DllExport bool GetBooleanTableOption(PGLOBAL, PTOS, char *, bool); -DllExport int GetIntegerTableOption(PGLOBAL, PTOS, char *, int); +DllExport PCSZ GetListOption(PGLOBAL, PCSZ, PCSZ, PCSZ def=NULL); +DllExport PCSZ GetStringTableOption(PGLOBAL, PTOS, PCSZ, PCSZ); +DllExport bool GetBooleanTableOption(PGLOBAL, PTOS, PCSZ, bool); +DllExport int GetIntegerTableOption(PGLOBAL, PTOS, PCSZ, int); #define MSGID_NONE 0 #define MSGID_CANNOT_OPEN 1 diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index eef9fba44f5..4035e79e892 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -238,90 +238,74 @@ void ptrc(char const *fmt, ...) PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, int *buftyp, XFLD *fldtyp, unsigned int *length, bool blank, bool nonull) - { +{ char cname[NAM_LEN+1]; int i; PCOLRES *pcrp, crp; PQRYRES qrp; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return NULL; - } // endif jump_level + /**********************************************************************/ + /* Allocate the structure used to contain the result set. */ + /**********************************************************************/ + qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES)); + pcrp = &qrp->Colresp; + qrp->Continued = false; + qrp->Truncated = false; + qrp->Info = false; + qrp->Suball = true; + qrp->Maxres = maxres; + qrp->Maxsize = 0; + qrp->Nblin = 0; + qrp->Nbcol = 0; // will be ncol + qrp->Cursor = 0; + qrp->BadLines = 0; - if (setjmp(g->jumper[++g->jump_level]) != 0) { - printf("%s\n", g->Message); - qrp = NULL; - goto fin; - } // endif rc -#endif // !USE_TRY + for (i = 0; i < ncol; i++) { + *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); + crp = *pcrp; + pcrp = &crp->Next; + memset(crp, 0, sizeof(COLRES)); + crp->Colp = NULL; + crp->Ncol = ++qrp->Nbcol; + crp->Type = buftyp[i]; + crp->Length = length[i]; + crp->Clen = GetTypeSize(crp->Type, length[i]); + crp->Prec = 0; - /************************************************************************/ - /* Allocate the structure used to contain the result set. */ - /************************************************************************/ - qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES)); - pcrp = &qrp->Colresp; - qrp->Continued = false; - qrp->Truncated = false; - qrp->Info = false; - qrp->Suball = true; - qrp->Maxres = maxres; - qrp->Maxsize = 0; - qrp->Nblin = 0; - qrp->Nbcol = 0; // will be ncol - qrp->Cursor = 0; - qrp->BadLines = 0; - - for (i = 0; i < ncol; i++) { - *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); - crp = *pcrp; - pcrp = &crp->Next; - memset(crp, 0, sizeof(COLRES)); - crp->Colp = NULL; - crp->Ncol = ++qrp->Nbcol; - crp->Type = buftyp[i]; - crp->Length = length[i]; - crp->Clen = GetTypeSize(crp->Type, length[i]); - crp->Prec = 0; - - if (ids > 0) { + if (ids > 0) { #if defined(XMSG) - // Get header from message file - strncpy(cname, PlugReadMessage(g, ids + crp->Ncol, NULL), NAM_LEN); - cname[NAM_LEN] = 0; // for truncated long names + // Get header from message file + strncpy(cname, PlugReadMessage(g, ids + crp->Ncol, NULL), NAM_LEN); + cname[NAM_LEN] = 0; // for truncated long names #else // !XMSG - GetRcString(ids + crp->Ncol, cname, sizeof(cname)); + GetRcString(ids + crp->Ncol, cname, sizeof(cname)); #endif // !XMSG - crp->Name = (PSZ)PlugDup(g, cname); - } else - crp->Name = NULL; // Will be set by caller + crp->Name = (PSZ)PlugDup(g, cname); + } else + crp->Name = NULL; // Will be set by caller - if (fldtyp) - crp->Fld = fldtyp[i]; - else - crp->Fld = FLD_NO; + if (fldtyp) + crp->Fld = fldtyp[i]; + else + crp->Fld = FLD_NO; - // Allocate the Value Block that will contain data - if (crp->Length || nonull) - crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres, - crp->Length, 0, true, blank, false); - else - crp->Kdata = NULL; + // Allocate the Value Block that will contain data + if (crp->Length || nonull) + crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres, + crp->Length, 0, true, blank, false); + else + crp->Kdata = NULL; - if (trace) - htrc("Column(%d) %s type=%d len=%d value=%p\n", - crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata); + if (trace) + htrc("Column(%d) %s type=%d len=%d value=%p\n", + crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata); - } // endfor i + } // endfor i - *pcrp = NULL; + *pcrp = NULL; -#if defined(USE_TRY) - } catch (int n) { + } catch (int n) { htrc("Exception %d: %s\n", n, g->Message); qrp = NULL; } catch (const char *msg) { @@ -329,12 +313,9 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, htrc("%s\n", g->Message); qrp = NULL; } // end catch -#else // !USE_TRY - fin: - g->jump_level--; -#endif // !USE_TRY + return qrp; - } // end of PlgAllocResult +} // end of PlgAllocResult /***********************************************************************/ /* Allocate and initialize the new DB User Block. */ @@ -380,11 +361,7 @@ PCATLG PlgGetCatalog(PGLOBAL g, bool jump) if (!cat && jump) { // Raise exception so caller doesn't have to check return value strcpy(g->Message, MSG(NO_ACTIVE_DB)); -#if defined(USE_TRY) throw 1; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 1); -#endif // !USE_TRY } // endif cat return cat; @@ -410,27 +387,27 @@ char *SetPath(PGLOBAL g, const char *path) char *buf= NULL; if (path) { - size_t len= strlen(path) + (*path != '.' ? 4 : 1); + size_t len = strlen(path) + (*path != '.' ? 4 : 1); if (!(buf = (char*)PlgDBSubAlloc(g, NULL, len))) return NULL; if (PlugIsAbsolutePath(path)) { - strcpy(buf, path); - return buf; - } // endif path + strcpy(buf, path); + return buf; + } // endif path if (*path != '.') { #if defined(__WIN__) - char *s= "\\"; + const char *s = "\\"; #else // !__WIN__ - char *s= "/"; + const char *s = "/"; #endif // !__WIN__ strcat(strcat(strcat(strcpy(buf, "."), s), path), s); } else strcpy(buf, path); - } // endif path + } // endif path return buf; } // end of SetPath @@ -468,7 +445,7 @@ char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op) static bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat) { if (pat && strlen(pat)) { - // This leaves 512 bytes (MAX_STR / 2) for each components + // This leaves 2048 bytes (MAX_STR / 2) for each components LPSTR name = g->Message + MAX_STR / 2; strlwr(strcpy(name, string)); @@ -496,11 +473,7 @@ bool PlugEvalLike(PGLOBAL g, LPCSTR strg, LPCSTR pat, bool ci) tp = g->Message; else if (!(tp = new char[strlen(pat) + strlen(strg) + 2])) { strcpy(g->Message, MSG(NEW_RETURN_NULL)); -#if defined(USE_TRY) throw OP_LIKE; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], OP_LIKE); -#endif // !USE_TRY } /* endif tp */ sp = tp + strlen(pat) + 1; @@ -511,11 +484,7 @@ bool PlugEvalLike(PGLOBAL g, LPCSTR strg, LPCSTR pat, bool ci) tp = g->Message; /* Use this as temporary work space. */ else if (!(tp = new char[strlen(pat) + 1])) { strcpy(g->Message, MSG(NEW_RETURN_NULL)); -#if defined(USE_TRY) throw OP_LIKE; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], OP_LIKE); -#endif // !USE_TRY } /* endif tp */ strcpy(tp, pat); /* Make a copy to be worked into */ @@ -704,7 +673,7 @@ void PlugConvertConstant(PGLOBAL g, void* & value, short& type) /* format and a Strftime output format. Flag if not 0 indicates that */ /* non quoted blanks are not included in the output format. */ /***********************************************************************/ -PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag) +PDTP MakeDateFormat(PGLOBAL g, PCSZ dfmt, bool in, bool out, int flag) { int rc; PDTP pdp = (PDTP)PlugSubAlloc(g, NULL, sizeof(DATPAR)); @@ -713,7 +682,7 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag) htrc("MakeDateFormat: dfmt=%s\n", dfmt); memset(pdp, 0, sizeof(DATPAR)); - pdp->Format = pdp->Curp = dfmt; + pdp->Format = pdp->Curp = PlugDup(g, dfmt); pdp->Outsize = 2 * strlen(dfmt) + 1; if (in) @@ -755,10 +724,11 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag) /***********************************************************************/ int ExtractDate(char *dts, PDTP pdp, int defy, int val[6]) { - char *fmt, c, d, e, W[8][12]; - int i, k, m, numval; - int n, y = 30; - bool b = true; // true for null dates + PCSZ fmt; + char c, d, e, W[8][12]; + int i, k, m, numval; + int n, y = 30; + bool b = true; // true for null dates if (pdp) fmt = pdp->InFmt; @@ -1283,7 +1253,7 @@ void *PlgDBalloc(PGLOBAL g, void *area, MBLOCK& mp) // in the area, do allocate from virtual storage. #if defined(__WIN__) if (mp.Size >= BIGMEM) - mp.Memp = VirtualAlloc(NULL, mp.Size, MEM_COMMIT, PAGE_READWRITE); + mp.Memp = VirtualAlloc(NULL, mp.Size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); else #endif mp.Memp = malloc(mp.Size); @@ -1548,11 +1518,7 @@ DllExport void NewPointer(PTABS t, void *oldv, void *newv) PGLOBAL g = t->G; sprintf(g->Message, "NewPointer: %s", MSG(MEM_ALLOC_ERROR)); -#if defined(USE_TRY) throw 3; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 3); -#endif // !USE_TRY } else { tp->Next = t->P1; tp->Num = 0; @@ -1589,22 +1555,14 @@ int FileComp(PGLOBAL g, char *file1, char *file2) sprintf(g->Message, MSG(OPEN_MODE_ERROR), "rb", (int)errno, fn[i]); strcat(strcat(g->Message, ": "), strerror(errno)); -#if defined(USE_TRY) throw 666; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 666); -#endif // !USE_TRY // } else // len[i] = 0; // File does not exist yet } else { if ((len[i] = _filelength(h[i])) < 0) { sprintf(g->Message, MSG(FILELEN_ERROR), "_filelength", fn[i]); -#if defined(USE_TRY) throw 666; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 666); -#endif // !USE_TRY } // endif len } // endif h diff --git a/storage/connect/plgxml.cpp b/storage/connect/plgxml.cpp index eb31e24235b..f3d3a010266 100644 --- a/storage/connect/plgxml.cpp +++ b/storage/connect/plgxml.cpp @@ -45,7 +45,7 @@ XMLDOCUMENT::XMLDOCUMENT(char *nsl, char *nsdf, char *enc) /******************************************************************/ /* Initialize zipped file processing. */ /******************************************************************/ -bool XMLDOCUMENT::InitZip(PGLOBAL g, char *entry) +bool XMLDOCUMENT::InitZip(PGLOBAL g, PCSZ entry) { #if defined(ZIP_SUPPORT) bool mul = (entry) ? strchr(entry, '*') || strchr(entry, '?') : false; @@ -173,7 +173,7 @@ void XMLNODE::Delete(PXNODE dnp) /******************************************************************/ /* Store a string in Buf, enventually reallocating it. */ /******************************************************************/ -char *XMLNODE::BufAlloc(PGLOBAL g, char *p, int n) +char *XMLNODE::BufAlloc(PGLOBAL g, const char *p, int n) { if (Len < n) { Len = n; diff --git a/storage/connect/plgxml.h b/storage/connect/plgxml.h index 6870764c503..82629e4c7db 100644 --- a/storage/connect/plgxml.h +++ b/storage/connect/plgxml.h @@ -76,9 +76,9 @@ class XMLDOCUMENT : public BLOCK { virtual void SetNofree(bool b) = 0; // Methods - virtual bool Initialize(PGLOBAL, char *, bool) = 0; + virtual bool Initialize(PGLOBAL, PCSZ, bool) = 0; virtual bool ParseFile(PGLOBAL, char *) = 0; - virtual bool NewDoc(PGLOBAL, char *) = 0; + virtual bool NewDoc(PGLOBAL, PCSZ) = 0; virtual void AddComment(PGLOBAL, char *) = 0; virtual PXNODE GetRoot(PGLOBAL) = 0; virtual PXNODE NewRoot(PGLOBAL, char *) = 0; @@ -95,7 +95,7 @@ class XMLDOCUMENT : public BLOCK { // Utility bool MakeNSlist(PGLOBAL g); - bool InitZip(PGLOBAL g, char *entry); + bool InitZip(PGLOBAL g, PCSZ entry); char *GetMemDoc(PGLOBAL g, char *fn); void CloseZip(void); @@ -131,15 +131,15 @@ class XMLNODE : public BLOCK { virtual PXLIST SelectNodes(PGLOBAL, char *, PXLIST = NULL) = 0; virtual PXNODE SelectSingleNode(PGLOBAL, char *, PXNODE = NULL) = 0; virtual PXATTR GetAttribute(PGLOBAL, char *, PXATTR = NULL) = 0; - virtual PXNODE AddChildNode(PGLOBAL, char *, PXNODE = NULL) = 0; + virtual PXNODE AddChildNode(PGLOBAL, PCSZ, PXNODE = NULL) = 0; virtual PXATTR AddProperty(PGLOBAL, char *, PXATTR = NULL) = 0; - virtual void AddText(PGLOBAL, char *) = 0; + virtual void AddText(PGLOBAL, PCSZ) = 0; virtual void DeleteChild(PGLOBAL, PXNODE) = 0; protected: PXNODE NewChild(PXNODE ncp); void Delete(PXNODE dnp); - char *BufAlloc(PGLOBAL g, char *p, int n); + char *BufAlloc(PGLOBAL g, const char *p, int n); // Constructor XMLNODE(PXDOC dp); diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp index d34b43a63d2..f0822526b98 100644 --- a/storage/connect/plugutil.cpp +++ b/storage/connect/plugutil.cpp @@ -139,10 +139,17 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) htrc("PlugInit: Language='%s'\n", ((!Language) ? "Null" : (char*)Language)); - if (!(g = (PGLOBAL)malloc(sizeof(GLOBAL)))) { - fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); - return NULL; - } else { + try { + g = new GLOBAL; + } catch (...) { + fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); + return NULL; + } // end try/catch + + //if (!(g = (PGLOBAL)malloc(sizeof(GLOBAL)))) { + // fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); + // return NULL; + // } else { g->Sarea = NULL; g->Createas = 0; g->Alchecked = 0; @@ -157,14 +164,14 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) /* Allocate the main work segment. */ /*******************************************************************/ if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) { - char errmsg[256]; + char errmsg[MAX_STR]; sprintf(errmsg, MSG(WORK_AREA), g->Message); strcpy(g->Message, errmsg); g->Sarea_Size = 0; } else g->Sarea_Size = worksize; - } /* endif g */ + //} /* endif g */ g->jump_level = -1; /* New setting to allow recursive call of Plug */ return(g); @@ -183,7 +190,7 @@ int PlugExit(PGLOBAL g) if (g->Sarea) free(g->Sarea); - free(g); + delete g; return rc; } /* end of PlugExit */ @@ -510,7 +517,7 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size) memp, size, pph->To_Free, pph->FreeBlk); if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */ - char *pname = "Work"; + PCSZ pname = "Work"; sprintf(g->Message, "Not enough memory in %s area for request of %u (used=%d free=%d)", @@ -519,13 +526,7 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size) if (trace) htrc("PlugSubAlloc: %s\n", g->Message); -#if defined(USE_TRY) throw 1234; -#else // !USE_TRY - /* Nothing we can do if longjmp is not initialized. */ - assert(g->jump_level >= 0); - longjmp(g->jumper[g->jump_level], 1); -#endif // !USE_TRY } /* endif size OS32 code */ /*********************************************************************/ diff --git a/storage/connect/preparse.h b/storage/connect/preparse.h index 2892a958bdd..f16624548fb 100644 --- a/storage/connect/preparse.h +++ b/storage/connect/preparse.h @@ -7,14 +7,14 @@ /* Struct of variables used by the date format pre-parser. */ /***********************************************************************/ typedef struct _datpar { - char *Format; // Points to format to decode + const char *Format; // Points to format to decode char *Curp; // Points to current parsing position char *InFmt; // Start of input format char *OutFmt; // Start of output format int Index[8]; // Indexes of date values int Num; // Number of values to retrieve int Flag; // 1: Input, 2: Output, 4: no output blank - int Outsize; // Size of output buffers + int Outsize; // Size of output buffers } DATPAR, *PDTP; /***********************************************************************/ diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index c0f3074769a..26cc27b1b01 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -1,11 +1,11 @@ /************* RelDef CPP Program Source Code File (.CPP) **************/ /* PROGRAM NAME: RELDEF */ /* ------------- */ -/* Version 1.7 */ +/* Version 1.6 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2004-2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2004-2016 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -88,7 +88,7 @@ PTOS RELDEF::GetTopt(void) /***********************************************************************/ /* This function sets an integer table information. */ /***********************************************************************/ -bool RELDEF::SetIntCatInfo(PSZ what, int n) +bool RELDEF::SetIntCatInfo(PCSZ what, int n) { return Hc->SetIntegerOption(what, n); } // end of SetIntCatInfo @@ -96,7 +96,7 @@ bool RELDEF::SetIntCatInfo(PSZ what, int n) /***********************************************************************/ /* This function returns integer table information. */ /***********************************************************************/ -int RELDEF::GetIntCatInfo(PSZ what, int idef) +int RELDEF::GetIntCatInfo(PCSZ what, int idef) { int n= Hc->GetIntegerOption(what); @@ -106,7 +106,7 @@ int RELDEF::GetIntCatInfo(PSZ what, int idef) /***********************************************************************/ /* This function returns Boolean table information. */ /***********************************************************************/ -bool RELDEF::GetBoolCatInfo(PSZ what, bool bdef) +bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef) { bool b= Hc->GetBooleanOption(what, bdef); @@ -116,9 +116,10 @@ bool RELDEF::GetBoolCatInfo(PSZ what, bool bdef) /***********************************************************************/ /* This function returns size catalog information. */ /***********************************************************************/ -int RELDEF::GetSizeCatInfo(PSZ what, PSZ sdef) +int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) { - char * s, c; + char c; + PCSZ s; int i, n= 0; if (!(s= Hc->GetStringOption(what))) @@ -138,9 +139,9 @@ int RELDEF::GetSizeCatInfo(PSZ what, PSZ sdef) /***********************************************************************/ /* This function sets char table information in buf. */ /***********************************************************************/ -int RELDEF::GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size) +int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size) { - char *s= Hc->GetStringOption(what); + PCSZ s= Hc->GetStringOption(what); strncpy(buf, ((s) ? s : sdef), size); return size; @@ -158,9 +159,10 @@ bool RELDEF::Partitioned(void) /* This function returns string table information. */ /* Default parameter is "*" to get the handler default. */ /***********************************************************************/ -char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef) +char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) { - char *name, *sval= NULL, *s= Hc->GetStringOption(what, sdef); + char *sval = NULL; + PCSZ name, s= Hc->GetStringOption(what, sdef); if (s) { if (!Hc->IsPartitioned() || @@ -168,12 +170,12 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef) && stricmp(what, "connect"))) sval= PlugDup(g, s); else - sval= s; + sval= (char*)s; } else if (!stricmp(what, "filename")) { // Return default file name - char *ftype= Hc->GetStringOption("Type", "*"); - int i, n; + PCSZ ftype= Hc->GetStringOption("Type", "*"); + int i, n; if (IsFileType(GetTypeID(ftype))) { name= Hc->GetPartName(); @@ -251,9 +253,9 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, /***********************************************************************/ /* This function returns the database data path. */ /***********************************************************************/ -PSZ TABDEF::GetPath(void) +PCSZ TABDEF::GetPath(void) { - return (Database) ? (PSZ)Database : (Hc) ? Hc->GetDataPath() : NULL; + return (Database) ? Database : (Hc) ? Hc->GetDataPath() : NULL; } // end of GetPath /***********************************************************************/ @@ -279,7 +281,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g) #if defined(__WIN__) // Offsets of HTML and DIR tables start from 0, DBF at 1 - loff = (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; + loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; #else // !__WIN__ // Offsets of HTML tables start from 0, DIR and DBF at 1 loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; @@ -615,9 +617,10 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) if (!*Module) Module = Subtype; - Desc = (char*)PlugSubAlloc(g, NULL, strlen(Module) - + strlen(Subtype) + 3); - sprintf(Desc, "%s(%s)", Module, Subtype); + char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module) + + strlen(Subtype) + 3); + sprintf(desc, "%s(%s)", Module, Subtype); + Desc = desc; return false; } // end of DefineAM diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index 52a131dbf3d..8b19a413ade 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -42,13 +42,13 @@ class DllExport RELDEF : public BLOCK { // Relation definition block // Methods PTOS GetTopt(void); - bool GetBoolCatInfo(PSZ what, bool bdef); - bool SetIntCatInfo(PSZ what, int ival); + bool GetBoolCatInfo(PCSZ what, bool bdef); + bool SetIntCatInfo(PCSZ what, int ival); bool Partitioned(void); - int GetIntCatInfo(PSZ what, int idef); - int GetSizeCatInfo(PSZ what, PSZ sdef); - int GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size); - char *GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef); + int GetIntCatInfo(PCSZ what, int idef); + int GetSizeCatInfo(PCSZ what, PCSZ sdef); + int GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size); + char *GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef); virtual int Indexable(void) {return 0;} virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR schema, LPCSTR am) = 0; @@ -84,7 +84,7 @@ public: void SetNext(PTABDEF tdfp) {Next = tdfp;} int GetMultiple(void) {return Multiple;} int GetPseudo(void) {return Pseudo;} - PSZ GetPath(void); + PCSZ GetPath(void); //PSZ GetPath(void) // {return (Database) ? (PSZ)Database : Cat->GetDataPath();} bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);} @@ -105,8 +105,8 @@ public: protected: // Members - PSZ Schema; /* Table schema (for ODBC) */ - PSZ Desc; /* Table description */ + PCSZ Schema; /* Table schema (for ODBC) */ + PCSZ Desc; /* Table description */ uint Catfunc; /* Catalog function ID */ int Card; /* (max) number of rows in table */ int Elemt; /* Number of rows in blocks or rowset */ diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index d6651fb21a9..6f95eafe838 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -132,7 +132,8 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int) bool map = (am && (*am == 'M' || *am == 'm')); LPCSTR dfm = (am && (*am == 'F' || *am == 'f')) ? "F" : (am && (*am == 'B' || *am == 'b')) ? "B" - : (am && !stricmp(am, "DBF")) ? "D" : "V"; + : (am && (*am == 'X' || *am == 'x')) ? "X" + : (am && !stricmp(am, "DBF")) ? "D" : "V"; if ((Zipped = GetBoolCatInfo("Zipped", false))) { Entry = GetStringCatInfo(g, "Entry", NULL); @@ -148,7 +149,8 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int) GetCharCatInfo("Recfm", (PSZ)dfm, buf, sizeof(buf)); Recfm = (toupper(*buf) == 'F') ? RECFM_FIX : (toupper(*buf) == 'B') ? RECFM_BIN : - (toupper(*buf) == 'D') ? RECFM_DBF : RECFM_VAR; + (toupper(*buf) == 'X') ? RECFM_NAF : // MGO + (toupper(*buf) == 'D') ? RECFM_DBF : RECFM_VAR; Lrecl = GetIntCatInfo("Lrecl", 0); if (Recfm != RECFM_DBF) @@ -182,7 +184,7 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int) /***********************************************************************/ bool DOSDEF::GetOptFileName(PGLOBAL g, char *filename) { - char *ftype; + PCSZ ftype; switch (Recfm) { case RECFM_VAR: ftype = ".dop"; break; @@ -239,9 +241,9 @@ void DOSDEF::RemoveOptValues(PGLOBAL g) /***********************************************************************/ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf) { - char *ftype; - char filename[_MAX_PATH]; - bool sep, rc = false; + PCSZ ftype; + char filename[_MAX_PATH]; + bool sep, rc = false; if (!To_Indx) return false; // No index @@ -1511,11 +1513,7 @@ PBF TDBDOS::CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv) if (n == 8 && ctype != TYPE_LIST) { // Should never happen strcpy(g->Message, "Block opt: bad constant"); -#if defined(USE_TRY) throw 99; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 99); -#endif // !USE_TRY } // endif Conv if (type[0] == 1) { @@ -1796,7 +1794,7 @@ err: /* Make a dynamic index. */ /***********************************************************************/ bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted) - { +{ int k; volatile bool dynamic; bool brc; @@ -1867,17 +1865,7 @@ bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted) } else // Column contains same values as ROWID kxp = new(g) XXROW(this); -#if defined(USE_TRY) try { -#else // !USE_TRY - // Prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return true; - } // endif - - if (!setjmp(g->jumper[++g->jump_level])) { -#endif // !USE_TRY if (dynamic) { ResetBlockFilter(g); kxp->SetDynamic(dynamic); @@ -1902,7 +1890,6 @@ bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted) } // endif brc -#if defined(USE_TRY) } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -1911,14 +1898,9 @@ bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted) strcpy(g->Message, msg); brc = true; } // end catch -#else // !USE_TRY - } else - brc = true; - g->jump_level--; -#endif // !USE_TRY return brc; - } // end of InitialyzeIndex +} // end of InitialyzeIndex /***********************************************************************/ /* DOS GetProgMax: get the max value for progress information. */ @@ -2139,7 +2121,8 @@ bool TDBDOS::OpenDB(PGLOBAL g) return false; } // endif use - if (Mode == MODE_DELETE && !Next && Txfp->GetAmType() != TYPE_AM_DOS) { + if (Mode == MODE_DELETE && !Next && Txfp->GetAmType() != TYPE_AM_DOS + && Txfp->GetAmType() != TYPE_AM_MGO) { // Delete all lines. Not handled in MAP or block mode Txfp = new(g) DOSFAM((PDOSDEF)To_Def); Txfp->SetTdbp(this); @@ -2327,8 +2310,8 @@ void TDBDOS::CloseDB(PGLOBAL g) /***********************************************************************/ /* DOSCOL public constructor (also called by MAPCOL). */ /***********************************************************************/ -DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) - : COLBLK(cdp, tp, i) +DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am) + : COLBLK(cdp, tp, i) { char *p; int prec = Format.Prec; @@ -2358,7 +2341,7 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) Dval = NULL; Buf = NULL; - if (txfp->Blocked && Opt && (cdp->GetMin() || cdp->GetDval())) { + if (txfp && txfp->Blocked && Opt && (cdp->GetMin() || cdp->GetDval())) { int nblk = txfp->GetBlock(); Clustered = (cdp->GetXdb2()) ? 2 : 1; @@ -2537,11 +2520,7 @@ void DOSCOL::ReadColumn(PGLOBAL g) if (rc == RC_EF) sprintf(g->Message, MSG(INV_DEF_READ), rc); -#if defined(USE_TRY) throw 11; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 11); -#endif // !USE_TRY } // endif p = tdbp->To_Line + Deplac; @@ -2597,11 +2576,7 @@ void DOSCOL::ReadColumn(PGLOBAL g) break; default: sprintf(g->Message, MSG(BAD_RECFM), tdbp->Ftype); -#if defined(USE_TRY) throw 34; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 34); -#endif // !USE_TRY } // endswitch Ftype // Set null when applicable @@ -2710,11 +2685,7 @@ void DOSCOL::WriteColumn(PGLOBAL g) break; default: sprintf(g->Message, "Invalid field format for column %s", Name); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endswitch BufType p2 = Buf; @@ -2726,11 +2697,7 @@ void DOSCOL::WriteColumn(PGLOBAL g) if ((len = strlen(p2)) > field) { sprintf(g->Message, MSG(VALUE_TOO_LONG), p2, Name, field); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (Dsp) for (i = 0; i < len; i++) if (p2[i] == '.') diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h index c404328a675..d175cc2da4d 100644 --- a/storage/connect/tabdos.h +++ b/storage/connect/tabdos.h @@ -39,9 +39,9 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */ virtual PIXDEF GetIndx(void) {return To_Indx;} virtual void SetIndx(PIXDEF xdp) {To_Indx = xdp;} virtual bool IsHuge(void) {return Huge;} - PSZ GetFn(void) {return Fn;} - PSZ GetOfn(void) {return Ofn;} - PSZ GetEntry(void) {return Entry;} + PCSZ GetFn(void) {return Fn;} + PCSZ GetOfn(void) {return Ofn;} + PCSZ GetEntry(void) {return Entry;} bool GetMul(void) {return Mulentries;} bool GetAppend(void) {return Append;} void SetBlock(int block) { Block = block; } @@ -74,10 +74,10 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */ //virtual bool Erase(char *filename); // Members - PSZ Fn; /* Path/Name of corresponding file */ - PSZ Ofn; /* Base Path/Name of matching index files*/ - PSZ Entry; /* Zip entry name or pattern */ - PSZ Pwd; /* Zip password */ + PCSZ Fn; /* Path/Name of corresponding file */ + PCSZ Ofn; /* Base Path/Name of matching index files*/ + PCSZ Entry; /* Zip entry name or pattern */ + PCSZ Pwd; /* Zip password */ PIXDEF To_Indx; /* To index definitions blocks */ RECFM Recfm; /* 0:VAR, 1:FIX, 2:BIN, 3:VCT, 6:DBF */ bool Mapped; /* 0: disk file, 1: memory mapped file */ @@ -133,8 +133,8 @@ class DllExport TDBDOS : public TDBASE { // Implementation virtual AMT GetAmType(void) {return Txfp->GetAmType();} - virtual PSZ GetFile(PGLOBAL) {return Txfp->To_File;} - virtual void SetFile(PGLOBAL, PSZ fn) {Txfp->To_File = fn;} + virtual PCSZ GetFile(PGLOBAL) {return Txfp->To_File;} + virtual void SetFile(PGLOBAL, PCSZ fn) {Txfp->To_File = fn;} virtual void SetAbort(bool b) {Abort = b;} virtual RECFM GetFtype(void) {return Ftype;} virtual bool SkipHeader(PGLOBAL) {return false;} @@ -214,7 +214,7 @@ class DllExport DOSCOL : public COLBLK { friend class TDBFIX; public: // Constructors - DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am = "DOS"); + DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am = "DOS"); DOSCOL(DOSCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index ad9716b6a10..8f6e610dfc2 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -35,9 +35,9 @@ /***********************************************************************/ /* CONDFIL Constructor. */ /***********************************************************************/ -CONDFIL::CONDFIL(const Item *cond, uint idx, AMT type) +CONDFIL::CONDFIL(uint idx, AMT type) { - Cond = cond; +//Cond = cond; Idx = idx; Type = type; Op = OP_XX; @@ -61,7 +61,7 @@ int CONDFIL::Init(PGLOBAL g, PHC hc) bool h; if (options) - alt = GetListOption(g, "Alias", options->oplist, NULL); + alt = (char*)GetListOption(g, "Alias", options->oplist, NULL); while (alt) { if (!(p = strchr(alt, '='))) { @@ -267,7 +267,7 @@ TDBEXT::TDBEXT(PTDBEXT tdbp) : TDB(tdbp) /******************************************************************/ /* Convert an UTF-8 string to latin characters. */ /******************************************************************/ -int TDBEXT::Decode(char *txt, char *buf, size_t n) +int TDBEXT::Decode(PCSZ txt, char *buf, size_t n) { uint dummy_errors; uint32 len = copy_and_convert(buf, n, &my_charset_latin1, @@ -285,16 +285,17 @@ int TDBEXT::Decode(char *txt, char *buf, size_t n) /***********************************************************************/ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) { - char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3]; + PCSZ schmp = NULL; + char *catp = NULL, buf[NAM_LEN * 3]; int len; - bool oom = false, first = true; + bool first = true; PTABLE tablep = To_Table; PCOL colp; if (Srcdef) { if ((catp = strstr(Srcdef, "%s"))) { char *fil1, *fil2; - PSZ ph = ((EXTDEF*)To_Def)->Phpos; + PCSZ ph = ((EXTDEF*)To_Def)->Phpos; if (!ph) ph = (strstr(catp + 2, "%s")) ? "WH" : "W"; @@ -341,7 +342,7 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) for (colp = Columns; colp; colp = colp->GetNext()) if (!colp->IsSpecial()) { if (!first) - oom |= Query->Append(", "); + Query->Append(", "); else first = false; @@ -350,11 +351,11 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) if (Quote) { // Put column name between identifier quotes in case in contains blanks - oom |= Query->Append(Quote); - oom |= Query->Append(buf); - oom |= Query->Append(Quote); + Query->Append(Quote); + Query->Append(buf); + Query->Append(Quote); } else - oom |= Query->Append(buf); + Query->Append(buf); ((PEXTCOL)colp)->SetRank(++Ncol); } // endif colp @@ -362,13 +363,13 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) } else // !Columns can occur for queries such that sql count(*) from... // for which we will count the rows from sql * from... - oom |= Query->Append('*'); + Query->Append('*'); } else // SQL statement used to retrieve the size of the result - oom |= Query->Append("count(*)"); + Query->Append("count(*)"); - oom |= Query->Append(" FROM "); + Query->Append(" FROM "); if (Catalog && *Catalog) catp = Catalog; @@ -380,17 +381,17 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) schmp = Schema; if (catp) { - oom |= Query->Append(catp); + Query->Append(catp); if (schmp) { - oom |= Query->Append('.'); - oom |= Query->Append(schmp); + Query->Append('.'); + Query->Append(schmp); } // endif schmp - oom |= Query->Append('.'); + Query->Append('.'); } else if (schmp) { - oom |= Query->Append(schmp); - oom |= Query->Append('.'); + Query->Append(schmp); + Query->Append('.'); } // endif schmp // Table name can be encoded in UTF-8 @@ -398,18 +399,18 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) if (Quote) { // Put table name between identifier quotes in case in contains blanks - oom |= Query->Append(Quote); - oom |= Query->Append(buf); - oom |= Query->Append(Quote); + Query->Append(Quote); + Query->Append(buf); + Query->Append(Quote); } else - oom |= Query->Append(buf); + Query->Append(buf); len = Query->GetLength(); if (To_CondFil) { if (Mode == MODE_READ) { - oom |= Query->Append(" WHERE "); - oom |= Query->Append(To_CondFil->Body); + Query->Append(" WHERE "); + Query->Append(To_CondFil->Body); len = Query->GetLength() + 1; } else len += (strlen(To_CondFil->Body) + 256); @@ -417,10 +418,11 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) } else len += ((Mode == MODE_READX) ? 256 : 1); - if (oom || Query->Resize(len)) { + if (Query->IsTruncated()) { strcpy(g->Message, "MakeSQL: Out of memory"); return true; - } // endif oom + } else + Query->Resize(len); if (trace) htrc("Query=%s\n", Query->GetStr()); @@ -434,7 +436,8 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) /***********************************************************************/ bool TDBEXT::MakeCommand(PGLOBAL g) { - char *p, *stmt, name[132], *body = NULL, *schmp = NULL; + PCSZ schmp = NULL; + char *p, *stmt, name[132], *body = NULL; char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1); bool qtd = Quoted > 0; char q = qtd ? *Quote : ' '; @@ -562,7 +565,7 @@ int TDBEXT::GetProgMax(PGLOBAL g) /***********************************************************************/ /* EXTCOL public constructor. */ /***********************************************************************/ -EXTCOL::EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +EXTCOL::EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : COLBLK(cdp, tdbp, i) { if (cprec) { diff --git a/storage/connect/tabext.h b/storage/connect/tabext.h index 2ef20c89f2c..a7f5fb9d856 100644 --- a/storage/connect/tabext.h +++ b/storage/connect/tabext.h @@ -28,14 +28,14 @@ class ALIAS : public BLOCK { class CONDFIL : public BLOCK { public: // Constructor - CONDFIL(const Item *cond, uint idx, AMT type); + CONDFIL(uint idx, AMT type); // Functions int Init(PGLOBAL g, PHC hc); const char *Chk(const char *cln, bool *h); // Members - const Item *Cond; +//const Item *Cond; AMT Type; uint Idx; OPVAL Op; @@ -60,10 +60,10 @@ public: // Implementation virtual const char *GetType(void) { return "EXT"; } - inline PSZ GetTabname(void) { return Tabname; } - inline PSZ GetTabschema(void) { return Tabschema; } - inline PSZ GetUsername(void) { return Username; }; - inline PSZ GetPassword(void) { return Password; }; + inline PCSZ GetTabname(void) { return Tabname; } + inline PCSZ GetTabschema(void) { return Tabschema; } + inline PCSZ GetUsername(void) { return Username; }; + inline PCSZ GetPassword(void) { return Password; }; inline PSZ GetTabcat(void) { return Tabcat; } inline PSZ GetSrcdef(void) { return Srcdef; } inline char GetSep(void) { return (Sep) ? *Sep : 0; } @@ -76,10 +76,10 @@ public: protected: // Members - PSZ Tabname; /* External table name */ - PSZ Tabschema; /* External table schema */ - PSZ Username; /* User connect name */ - PSZ Password; /* Password connect info */ + PCSZ Tabname; /* External table name */ + PCSZ Tabschema; /* External table schema */ + PCSZ Username; /* User connect name */ + PCSZ Password; /* Password connect info */ PSZ Tabcat; /* External table catalog */ PSZ Tabtyp; /* Catalog table type */ PSZ Colpat; /* Catalog column pattern */ @@ -115,7 +115,7 @@ public: virtual bool IsRemote(void) { return true; } // Methods - virtual PSZ GetServer(void) { return "Remote"; } + virtual PCSZ GetServer(void) { return "Remote"; } virtual int GetRecpos(void); // Database routines @@ -127,19 +127,19 @@ protected: virtual bool MakeSQL(PGLOBAL g, bool cnt); //virtual bool MakeInsert(PGLOBAL g); virtual bool MakeCommand(PGLOBAL g); - int Decode(char *utf, char *buf, size_t n); + int Decode(PCSZ utf, char *buf, size_t n); // Members PQRYRES Qrp; // Points to storage result PSTRG Query; // Constructed SQL query - char *TableName; // Points to ODBC table name - char *Schema; // Points to ODBC table Schema - char *User; // User connect info - char *Pwd; // Password connect info + PCSZ TableName; // Points to ODBC table name + PCSZ Schema; // Points to ODBC table Schema + PCSZ User; // User connect info + PCSZ Pwd; // Password connect info char *Catalog; // Points to ODBC table Catalog char *Srcdef; // The source table SQL definition char *Count; // Points to count(*) SQL statement - //char *Where; // Points to local where clause + //char *Where; // Points to local where clause char *Quote; // The identifier quoting character char *MulConn; // Used for multiple ODBC tables char *DBQ; // The address part of Connect string @@ -170,7 +170,7 @@ class DllExport EXTCOL : public COLBLK { friend class TDBEXT; public: // Constructor - EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am); + EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am); EXTCOL(PEXTCOL colp, PTDB tdbp); // Constructor used in copy process // Implementation diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp index fb25ab3d5c8..a78d5861e53 100644 --- a/storage/connect/tabfix.cpp +++ b/storage/connect/tabfix.cpp @@ -373,7 +373,7 @@ int TDBFIX::WriteDB(PGLOBAL g) /***********************************************************************/ /* BINCOL public constructor. */ /***********************************************************************/ -BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) +BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am) : DOSCOL(g, cdp, tp, cp, i, am) { char c, *fmt = cdp->GetFmt(); @@ -411,11 +411,7 @@ BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) case 'D': M = sizeof(double); break; default: sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name); -#if defined(USE_TRY) throw 11; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 11); -#endif // !USE_TRY } // endswitch Fmt } else if (IsTypeChar(Buf_Type)) @@ -490,11 +486,7 @@ void BINCOL::ReadColumn(PGLOBAL g) if (rc == RC_EF) sprintf(g->Message, MSG(INV_DEF_READ), rc); -#if defined(USE_TRY) throw 11; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 11); -#endif // !USE_TRY } // endif p = tdbp->To_Line + Deplac; @@ -553,11 +545,7 @@ void BINCOL::ReadColumn(PGLOBAL g) break; default: sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name); -#if defined(USE_TRY) throw 11; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 11); -#endif // !USE_TRY } // endswitch Fmt // Set null when applicable @@ -607,11 +595,7 @@ void BINCOL::WriteColumn(PGLOBAL g) } else if (Value->GetBinValue(p, Long, Status)) { sprintf(g->Message, MSG(BIN_F_TOO_LONG), Name, Value->GetSize(), Long); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endif p break; @@ -620,11 +604,7 @@ void BINCOL::WriteColumn(PGLOBAL g) if (n > 32767LL || n < -32768LL) { sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (Status) Value->GetValueNonAligned(p, (short)n); @@ -634,11 +614,7 @@ void BINCOL::WriteColumn(PGLOBAL g) if (n > 255LL || n < -256LL) { sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (Status) *p = (char)n; @@ -648,11 +624,7 @@ void BINCOL::WriteColumn(PGLOBAL g) if (n > INT_MAX || n < INT_MIN) { sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (Status) Value->GetValueNonAligned(p, (int)n); @@ -676,11 +648,7 @@ void BINCOL::WriteColumn(PGLOBAL g) case 'C': // Characters if ((n = (signed)strlen(Value->GetCharString(Buf))) > Long) { sprintf(g->Message, MSG(BIN_F_TOO_LONG), Name, (int) n, Long); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endif n if (Status) { @@ -692,11 +660,7 @@ void BINCOL::WriteColumn(PGLOBAL g) break; default: sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endswitch Fmt if (Eds && Status) { diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h index 4b9f9689992..53c0af1c422 100644 --- a/storage/connect/tabfix.h +++ b/storage/connect/tabfix.h @@ -65,7 +65,7 @@ class DllExport BINCOL : public DOSCOL { friend class TDBFIX; public: // Constructors - BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am = "BIN"); + BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am = "BIN"); BINCOL(BINCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation @@ -108,7 +108,7 @@ class TDBDCL : public TDBCAT { {return DBFColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, false);} // Members - char *Fn; // The DBF file (path) name + PCSZ Fn; // The DBF file (path) name }; // end of class TDBOCL diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index ac85165d99f..516601a5eb4 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -81,7 +81,7 @@ USETEMP UseTemp(void); /* of types (TYPE_STRING < TYPE_DOUBLE < TYPE_INT) (1 < 2 < 7). */ /* If these values are changed, this will have to be revisited. */ /***********************************************************************/ -PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) +PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; @@ -153,7 +153,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) tdp->Lrecl = 4096; tdp->Multiple = GetIntegerTableOption(g, topt, "Multiple", 0); - p = GetStringTableOption(g, topt, "Separator", ","); + p = (char*)GetStringTableOption(g, topt, "Separator", ","); tdp->Sep = (strlen(p) == 2 && p[0] == '\\' && p[1] == 't') ? '\t' : *p; #if defined(__WIN__) @@ -167,7 +167,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) sep = tdp->Sep; tdp->Quoted = GetIntegerTableOption(g, topt, "Quoted", -1); - p = GetStringTableOption(g, topt, "Qchar", ""); + p = (char*)GetStringTableOption(g, topt, "Qchar", ""); tdp->Qot = *p; if (tdp->Qot && tdp->Quoted < 0) @@ -1435,11 +1435,7 @@ void CSVCOL::ReadColumn(PGLOBAL g) if (rc == RC_EF) sprintf(g->Message, MSG(INV_DEF_READ), rc); -#if defined(USE_TRY) throw 34; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 34); -#endif // !USE_TRY } // endif if (tdbp->Mode != MODE_UPDATE) { @@ -1457,11 +1453,7 @@ void CSVCOL::ReadColumn(PGLOBAL g) Long = colen; // Restore column length sprintf(g->Message, MSG(FLD_TOO_LNG_FOR), Fldnum + 1, Name, To_Tdb->RowNumber(g), tdbp->GetFile(g)); -#if defined(USE_TRY) throw 34; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 34); -#endif // !USE_TRY } // endif Long // Now do the reading @@ -1524,11 +1516,7 @@ void CSVCOL::WriteColumn(PGLOBAL g) if ((signed)strlen(p) > flen) { sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, flen, tdbp->RowNumber(g), tdbp->GetFile(g)); -#if defined(USE_TRY) throw 34; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 34); -#endif // !USE_TRY } else if (Dsp) for (int i = 0; p[i]; i++) if (p[i] == '.') @@ -1544,11 +1532,7 @@ void CSVCOL::WriteColumn(PGLOBAL g) if (Fldnum < 0) { // This can happen for wrong offset value in XDB files sprintf(g->Message, MSG(BAD_FIELD_RANK), Fldnum + 1, Name); -#if defined(USE_TRY) throw 34; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 34); -#endif // !USE_TRY } else strncpy(tdbp->Field[Fldnum], p, flen); diff --git a/storage/connect/tabfmt.h b/storage/connect/tabfmt.h index e5655435be7..396bba568ff 100644 --- a/storage/connect/tabfmt.h +++ b/storage/connect/tabfmt.h @@ -13,7 +13,7 @@ typedef class TDBFMT *PTDBFMT; /***********************************************************************/ /* Functions used externally. */ /***********************************************************************/ -PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info); +PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info); /***********************************************************************/ /* CSV table. */ @@ -21,7 +21,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info); class DllExport CSVDEF : public DOSDEF { /* Logical table description */ friend class TDBCSV; friend class TDBCCL; - friend PQRYRES CSVColumns(PGLOBAL, char *, PTOS, bool); + friend PQRYRES CSVColumns(PGLOBAL, PCSZ, PTOS, bool); public: // Constructor CSVDEF(void); @@ -53,7 +53,7 @@ public: class DllExport TDBCSV : public TDBDOS { friend class CSVCOL; friend class MAPFAM; - friend PQRYRES CSVColumns(PGLOBAL, char *, PTOS, bool); + friend PQRYRES CSVColumns(PGLOBAL, PCSZ, PTOS, bool); public: // Constructor TDBCSV(PCSVDEF tdp, PTXF txfp); diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 48427b9620c..7c82a2fc138 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -365,10 +365,11 @@ PCOL TDBJDBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) /***********************************************************************/ bool TDBJDBC::MakeInsert(PGLOBAL g) { - char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3]; + PCSZ schmp = NULL; + char *catp = NULL, buf[NAM_LEN * 3]; int len = 0; uint pos; - bool b = false, oom = false; + bool b = false; PTABLE tablep = To_Table; PCOL colp; @@ -405,32 +406,32 @@ bool TDBJDBC::MakeInsert(PGLOBAL g) Query = new(g)STRING(g, len, "INSERT INTO "); if (catp) { - oom |= Query->Append(catp); + Query->Append(catp); if (schmp) { - oom |= Query->Append('.'); - oom |= Query->Append(schmp); + Query->Append('.'); + Query->Append(schmp); } // endif schmp - oom |= Query->Append('.'); + Query->Append('.'); } else if (schmp) { - oom |= Query->Append(schmp); - oom |= Query->Append('.'); + Query->Append(schmp); + Query->Append('.'); } // endif schmp if (Quote) { // Put table name between identifier quotes in case in contains blanks - oom |= Query->Append(Quote); - oom |= Query->Append(buf); - oom |= Query->Append(Quote); + Query->Append(Quote); + Query->Append(buf); + Query->Append(Quote); } else - oom |= Query->Append(buf); + Query->Append(buf); - oom |= Query->Append('('); + Query->Append('('); for (colp = Columns; colp; colp = colp->GetNext()) { if (b) - oom |= Query->Append(", "); + Query->Append(", "); else b = true; @@ -439,15 +440,15 @@ bool TDBJDBC::MakeInsert(PGLOBAL g) if (Quote) { // Put column name between identifier quotes in case in contains blanks - oom |= Query->Append(Quote); - oom |= Query->Append(buf); - oom |= Query->Append(Quote); + Query->Append(Quote); + Query->Append(buf); + Query->Append(Quote); } else - oom |= Query->Append(buf); + Query->Append(buf); } // endfor colp - if ((oom |= Query->Append(") VALUES ("))) { + if ((Query->Append(") VALUES ("))) { strcpy(g->Message, "MakeInsert: Out of memory"); return true; } else // in case prepared statement fails @@ -455,9 +456,9 @@ bool TDBJDBC::MakeInsert(PGLOBAL g) // Make prepared statement for (int i = 0; i < Nparm; i++) - oom |= Query->Append("?,"); + Query->Append("?,"); - if (oom) { + if (Query->IsTruncated()) { strcpy(g->Message, "MakeInsert: Out of memory"); return true; } else @@ -750,7 +751,7 @@ bool TDBJDBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr) To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0); *To_CondFil->Body= 0; - if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond))) + if ((To_CondFil = hc->CheckCond(g, To_CondFil, Cond))) PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1); } // endif active_index @@ -864,7 +865,6 @@ int TDBJDBC::WriteDB(PGLOBAL g) // an insert query for each line to insert uint len = Query->GetLength(); char buf[64]; - bool oom = false; // Make the Insert command value list for (PCOL colp = Columns; colp; colp = colp->GetNext()) { @@ -872,28 +872,28 @@ int TDBJDBC::WriteDB(PGLOBAL g) char *s = colp->GetValue()->GetCharString(buf); if (colp->GetResultType() == TYPE_STRING) - oom |= Query->Append_quoted(s); + Query->Append_quoted(s); else if (colp->GetResultType() == TYPE_DATE) { DTVAL *dtv = (DTVAL*)colp->GetValue(); if (dtv->IsFormatted()) - oom |= Query->Append_quoted(s); + Query->Append_quoted(s); else - oom |= Query->Append(s); + Query->Append(s); } else - oom |= Query->Append(s); + Query->Append(s); } else - oom |= Query->Append("NULL"); + Query->Append("NULL"); - oom |= Query->Append(','); + Query->Append(','); } // endfor colp - if (unlikely(oom)) { + if (unlikely(Query->IsTruncated())) { strcpy(g->Message, "WriteDB: Out of memory"); return RC_FX; - } // endif oom + } // endif Query Query->RepLast(')'); @@ -967,7 +967,7 @@ void TDBJDBC::CloseDB(PGLOBAL g) /***********************************************************************/ /* JDBCCOL public constructor. */ /***********************************************************************/ -JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : EXTCOL(cdp, tdbp, cprec, i, am) { } // end of JDBCCOL constructor @@ -1212,8 +1212,8 @@ int TDBXJDC::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ /* JSRCCOL public constructor. */ /***********************************************************************/ -JSRCCOL::JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) - : JDBCCOL(cdp, tdbp, cprec, i, am) +JSRCCOL::JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) + : JDBCCOL(cdp, tdbp, cprec, i, am) { // Set additional JDBC access method information for column. Flag = cdp->GetOffset(); diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index 5a59b6c2df8..7c14783285f 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -67,7 +67,7 @@ public: virtual PTDB Clone(PTABS t); virtual bool SetRecpos(PGLOBAL g, int recpos); virtual void ResetSize(void); - virtual PSZ GetServer(void) { return "JDBC"; } + virtual PCSZ GetServer(void) { return "JDBC"; } virtual int Indexable(void) { return 2; } // Database routines @@ -103,7 +103,7 @@ class JDBCCOL : public EXTCOL { friend class TDBJDBC; public: // Constructors - JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "JDBC"); + JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC"); JDBCCOL(JDBCCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation @@ -165,7 +165,7 @@ class JSRCCOL : public JDBCCOL { friend class TDBXJDC; public: // Constructors - JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "JDBC"); + JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC"); // Implementation virtual int GetAmType(void) {return TYPE_AM_JDBC;} @@ -210,9 +210,9 @@ protected: virtual PQRYRES GetResult(PGLOBAL g); // Members - char *Schema; // Points to schema name or NULL - char *Tab; // Points to JDBC table name or pattern - char *Tabtype; // Points to JDBC table type + PCSZ Schema; // Points to schema name or NULL + PCSZ Tab; // Points to JDBC table name or pattern + PCSZ Tabtype; // Points to JDBC table type JDBCPARM Ops; // Additional parameters }; // end of class TDBJTB @@ -229,7 +229,7 @@ protected: virtual PQRYRES GetResult(PGLOBAL g); // Members - char *Colpat; // Points to catalog column pattern + PCSZ Colpat; // Points to catalog column pattern }; // end of class TDBJDBCL #endif // !NJDBC diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 22f9b592952..edfe710bc92 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -63,7 +63,7 @@ typedef struct _jncol { /* JSONColumns: construct the result blocks containing the description */ /* of all the columns of a table contained inside a JSON file. */ /***********************************************************************/ -PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) +PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; @@ -112,7 +112,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) #endif // ZIP_SUPPORT tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); - if (!tdp->Fn) { + if (!tdp->Fn && !dsn) { strcpy(g->Message, MSG(MISSING_FNAME)); return NULL; } // endif Fn @@ -120,7 +120,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) if (!(tdp->Database = SetPath(g, db))) return NULL; - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); @@ -153,7 +153,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) if (tdp->Zipped) { #if defined(ZIP_SUPPORT) - tjnp = new(g)TDBJSN(tdp, new(g)UNZFAM(tdp)); + tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp)); #else // !ZIP_SUPPORT sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); return NULL; @@ -264,8 +264,13 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) break; if (jcp) { - if (jcp->Type != jcol.Type) - jcp->Type = TYPE_STRING; + if (jcp->Type != jcol.Type) { + if (jcp->Type == TYPE_UNKNOWN) + jcp->Type = jcol.Type; + else if (jcol.Type != TYPE_UNKNOWN) + jcp->Type = TYPE_STRING; + + } // endif Type if (*fmt && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) { jcp->Fmt = PlugDup(g, fmt); @@ -338,7 +343,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) skipit: if (trace) - htrc("CSVColumns: n=%d len=%d\n", n, length[0]); + htrc("JSONColumns: n=%d len=%d\n", n, length[0]); /*********************************************************************/ /* Allocate the structures used to refer to the result set. */ @@ -419,7 +424,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff) Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 10); Base = GetIntCatInfo("Base", 0) ? 1 : 0; - return DOSDEF::DefineAM(g, "DOS", poff); + return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff); } // end of DefineAM /***********************************************************************/ @@ -465,7 +470,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "GZ"); return NULL; #endif // !GZ_SUPPORT - } else if (map) + } else if (map) txfp = new(g) MAPFAM(this); else txfp = new(g) DOSFAM(this); @@ -488,7 +493,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) } else { if (Zipped) { #if defined(ZIP_SUPPORT) - if (m == MODE_READ || m == MODE_UPDATE) { + if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { txfp = new(g) UNZFAM(this); } else if (m == MODE_INSERT) { strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0"); @@ -537,7 +542,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) } else { Jmode = MODE_OBJECT; Objname = NULL; - Xcol = NULL; + Xcol = NULL; Limit = 1; Pretty = 0; B = 0; @@ -697,6 +702,9 @@ bool TDBJSN::OpenDB(PGLOBAL g) return true; } // endswitch Jmode + if (Xcol && Txfp->GetAmType() != TYPE_AM_MGO) + To_Filter = NULL; // Imcompatible + } // endif Use return TDBDOS::OpenDB(g); @@ -867,24 +875,21 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) } // end of PrepareWriting - /***********************************************************************/ - /* WriteDB: Data Base write routine for DOS access method. */ - /***********************************************************************/ - int TDBJSN::WriteDB(PGLOBAL g) +/***********************************************************************/ +/* WriteDB: Data Base write routine for DOS access method. */ +/***********************************************************************/ +int TDBJSN::WriteDB(PGLOBAL g) { int rc = TDBDOS::WriteDB(g); #if USE_G - if (rc == RC_FX) - strcpy(g->Message, G->Message); - PlugSubSet(G, G->Sarea, G->Sarea_Size); #endif Row->Clear(); return rc; } // end of WriteDB - /* ---------------------------- JSONCOL ------------------------------ */ +/* ---------------------------- JSONCOL ------------------------------ */ /***********************************************************************/ /* JSONCOL public constructor. */ @@ -1148,12 +1153,62 @@ bool JSONCOL::ParseJpath(PGLOBAL g) return false; } // end of ParseJpath +/***********************************************************************/ +/* Get Jpath converted to Mongo path. */ +/***********************************************************************/ +char *JSONCOL::GetJpath(PGLOBAL g, bool proj) +{ + if (Jpath) { + char *p1, *p2, *mgopath; + int i = 0; + + if (strcmp(Jpath, "*")) + mgopath = PlugDup(g, Jpath); + else + return NULL; + + for (p1 = p2 = mgopath; *p1; p1++) + if (i) { // Inside [] + if (isdigit(*p1)) { + if (!proj) + *p2++ = *p1; + + i = 2; + } else if (*p1 == ']' && i == 2) { + if (proj && *(p1 + 1) == ':') + p1++; + + i = 0; + } else if (proj) + i = 2; + else + return NULL; + + } else switch (*p1) { + case ':': *p2++ = '.'; break; + case '[': i = 1; break; + case '*': + if (*(p2 - 1) == '.' && !*(p1 + 1)) { + p2--; // Suppress last :* + break; + } // endif p2 + + default: *p2++ = *p1; break; + } // endswitch p1; + + *p2 = 0; + return mgopath; + } else + return NULL; + +} // end of GetJpath + /***********************************************************************/ /* MakeJson: Serialize the json item and set value to it. */ /***********************************************************************/ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) - { - if (Value->IsTypeNum()) { +{ + if (Value->IsTypeNum()) { strcpy(g->Message, "Cannot make Json for a numeric column"); Value->Reset(); } else @@ -1174,7 +1229,7 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) case TYPE_BINT: case TYPE_DBL: case TYPE_DATE: - vp->SetValue_pval(val->GetValue()); + vp->SetValue_pval(val->GetValue()); break; case TYPE_BOOL: if (vp->IsTypeNum()) @@ -1193,11 +1248,14 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) // } // endif Type default: + vp->Reset(); vp->SetNull(true); } // endswitch Type - } else + } else { + vp->Reset(); vp->SetNull(true); + } // endif val } // end of SetJsonValue @@ -1210,8 +1268,8 @@ void JSONCOL::ReadColumn(PGLOBAL g) Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0)); // Set null when applicable - if (Nullable) - Value->SetNull(Value->IsNull()); + if (!Nullable) + Value->SetNull(false); } // end of ReadColumn @@ -1292,11 +1350,7 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) { strcpy(g->Message, "Logical error expanding array"); -#if defined(USE_TRY) throw 666; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 666); -#endif // !USE_TRY } // endif jvp if (n < Nod - 1 && jvp->GetJson()) { @@ -1482,11 +1536,7 @@ void JSONCOL::WriteColumn(PGLOBAL g) { if (Xpd && Tjp->Pretty < 2) { strcpy(g->Message, "Cannot write expanded column when Pretty is not 2"); -#if defined(USE_TRY) throw 666; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 666); -#endif // !USE_TRY } // endif Xpd /*********************************************************************/ @@ -1521,11 +1571,7 @@ void JSONCOL::WriteColumn(PGLOBAL g) if (!(jsp = ParseJson(G, s, (int)strlen(s)))) { strcpy(g->Message, s); -#if defined(USE_TRY) throw 666; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 666); -#endif // !USE_TRY } // endif jsp if (arp) { @@ -1876,8 +1922,11 @@ bool TDBJSON::OpenDB(PGLOBAL g) return true; } // endswitch Jmode - Use = USE_OPEN; - return false; + if (Xcol) + To_Filter = NULL; // Imcompatible + + Use = USE_OPEN; + return false; } // end of OpenDB /***********************************************************************/ @@ -1887,7 +1936,7 @@ int TDBJSON::ReadDB(PGLOBAL) { int rc; - N++; + N++; if (NextSame) { SameRow = NextSame; @@ -1999,6 +2048,7 @@ TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) { Topt = tdp->GetTopt(); Db = (char*)tdp->GetDB(); + Dsn = (char*)tdp->Uri; } // end of TDBJCL constructor /***********************************************************************/ @@ -2006,7 +2056,7 @@ TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) /***********************************************************************/ PQRYRES TDBJCL::GetResult(PGLOBAL g) { - return JSONColumns(g, Db, Topt, false); + return JSONColumns(g, Db, Dsn, Topt, false); } // end of GetResult /* --------------------------- End of json --------------------------- */ diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index 924ce387900..2c8f226b5ca 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -1,7 +1,7 @@ /*************** tabjson H Declares Source Code File (.H) **************/ -/* Name: tabjson.h Version 1.1 */ +/* Name: tabjson.h Version 1.3 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */ /* */ /* This file contains the JSON classes declares. */ /***********************************************************************/ @@ -32,12 +32,12 @@ typedef struct _jnode { /***********************************************************************/ /* JSON table. */ /***********************************************************************/ -class JSONDEF : public DOSDEF { /* Table description */ +class DllExport JSONDEF : public DOSDEF { /* Table description */ friend class TDBJSON; friend class TDBJSN; friend class TDBJCL; - friend PQRYRES JSONColumns(PGLOBAL, char*, PTOS, bool); - public: + friend PQRYRES JSONColumns(PGLOBAL, char*, char*, PTOS, bool); +public: // Constructor JSONDEF(void); @@ -51,13 +51,14 @@ class JSONDEF : public DOSDEF { /* Table description */ protected: // Members JMODE Jmode; /* MODE_OBJECT by default */ - char *Objname; /* Name of first level object */ - char *Xcol; /* Name of expandable column */ + PCSZ Objname; /* Name of first level object */ + PCSZ Xcol; /* Name of expandable column */ int Limit; /* Limit of multiple values */ int Pretty; /* Depends on file structure */ int Level; /* Used for catalog table */ - int Base; /* Tne array index base */ + int Base; /* The array index base */ bool Strict; /* Strict syntax checking */ + const char *Uri; /* MongoDB connection URI */ }; // end of JSONDEF /* -------------------------- TDBJSN class --------------------------- */ @@ -66,7 +67,7 @@ class JSONDEF : public DOSDEF { /* Table description */ /* This is the JSN Access Method class declaration. */ /* The table is a DOS file, each record being a JSON object. */ /***********************************************************************/ -class TDBJSN : public TDBDOS { +class DllExport TDBJSN : public TDBDOS { friend class JSONCOL; friend class JSONDEF; public: @@ -87,6 +88,8 @@ public: virtual PCOL InsertSpecialColumn(PCOL colp); virtual int RowNumber(PGLOBAL g, bool b = FALSE) {return (b) ? M : N;} + virtual bool CanBeFiltered(void) + {return Txfp->GetAmType() == TYPE_AM_MGO || !Xcol;} // Database routines virtual int Cardinality(PGLOBAL g); @@ -107,8 +110,8 @@ public: PJSON Val; // The value of the current row PJCOL Colp; // The multiple column JMODE Jmode; // MODE_OBJECT by default - char *Objname; // The table object name - char *Xcol; // Name of expandable column + PCSZ Objname; // The table object name + PCSZ Xcol; // Name of expandable column int Fpos; // The current row index int N; // The current Rownum int M; // Index of multiple value @@ -127,9 +130,10 @@ public: /***********************************************************************/ /* Class JSONCOL: JSON access method column descriptor. */ /***********************************************************************/ -class JSONCOL : public DOSCOL { +class DllExport JSONCOL : public DOSCOL { friend class TDBJSN; friend class TDBJSON; + friend class MGOFAM; public: // Constructors JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i); @@ -139,20 +143,21 @@ class JSONCOL : public DOSCOL { virtual int GetAmType(void) {return Tjp->GetAmType();} // Methods - virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); - bool ParseJpath(PGLOBAL g); - virtual void ReadColumn(PGLOBAL g); - virtual void WriteColumn(PGLOBAL g); + virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); + bool ParseJpath(PGLOBAL g); + char *GetJpath(PGLOBAL g, bool proj); + virtual void ReadColumn(PGLOBAL g); + virtual void WriteColumn(PGLOBAL g); protected: - bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b); - bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm); - PVAL GetColumnValue(PGLOBAL g, PJSON row, int i); - PVAL ExpandArray(PGLOBAL g, PJAR arp, int n); - PVAL CalculateArray(PGLOBAL g, PJAR arp, int n); - PVAL MakeJson(PGLOBAL g, PJSON jsp); - void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n); - PJSON GetRow(PGLOBAL g); + bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b); + bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm); + PVAL GetColumnValue(PGLOBAL g, PJSON row, int i); + PVAL ExpandArray(PGLOBAL g, PJAR arp, int n); + PVAL CalculateArray(PGLOBAL g, PJAR arp, int n); + PVAL MakeJson(PGLOBAL g, PJSON jsp); + void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n); + PJSON GetRow(PGLOBAL g); // Default constructor not to be used JSONCOL(void) {} @@ -174,7 +179,7 @@ class JSONCOL : public DOSCOL { /***********************************************************************/ /* This is the JSON Access Method class declaration. */ /***********************************************************************/ -class TDBJSON : public TDBJSN { +class DllExport TDBJSON : public TDBJSN { friend class JSONDEF; friend class JSONCOL; public: @@ -221,7 +226,7 @@ class TDBJSON : public TDBJSN { /***********************************************************************/ /* This is the class declaration for the JSON catalog table. */ /***********************************************************************/ -class TDBJCL : public TDBCAT { +class DllExport TDBJCL : public TDBCAT { public: // Constructor TDBJCL(PJDEF tdp); @@ -233,4 +238,5 @@ class TDBJCL : public TDBCAT { // Members PTOS Topt; char *Db; + char *Dsn; }; // end of class TDBJCL diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp index 916449be6c6..22fb09dbb86 100644 --- a/storage/connect/table.cpp +++ b/storage/connect/table.cpp @@ -47,6 +47,7 @@ TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum) To_Orig = NULL; To_Filter = NULL; To_CondFil = NULL; + Cond = NULL; Next = NULL; Name = (tdp) ? tdp->GetName() : NULL; To_Table = NULL; @@ -68,6 +69,7 @@ TDB::TDB(PTDB tdbp) : Tdb_No(++Tnum) To_Orig = tdbp; To_Filter = NULL; To_CondFil = NULL; + Cond = NULL; Next = NULL; Name = tdbp->Name; To_Table = tdbp->To_Table; @@ -97,7 +99,7 @@ CHARSET_INFO *TDB::data_charset(void) /***********************************************************************/ /* Return the datapath of the DB this table belongs to. */ /***********************************************************************/ -PSZ TDB::GetPath(void) +PCSZ TDB::GetPath(void) { return To_Def->GetPath(); } // end of GetPath diff --git a/storage/connect/tabmac.cpp b/storage/connect/tabmac.cpp index bbaba591540..a28b5d7108c 100644 --- a/storage/connect/tabmac.cpp +++ b/storage/connect/tabmac.cpp @@ -329,7 +329,7 @@ void MACCOL::ReadColumn(PGLOBAL g) n = 0; break; default: - p = ""; + p = PlugDup(g, ""); } // endswitch Flag } else switch (Flag) { diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp index b5f07db8413..5c41f9094ac 100644 --- a/storage/connect/tabmul.cpp +++ b/storage/connect/tabmul.cpp @@ -603,10 +603,10 @@ bool TDBMSD::InitFileNames(PGLOBAL g) bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR, int) { Desc = Fn = GetStringCatInfo(g, "Filename", NULL); - Incl = GetBoolCatInfo("Subdir", false); + Incl = GetBoolCatInfo("Subdir", false); Huge = GetBoolCatInfo("Huge", false); Nodir = GetBoolCatInfo("Nodir", true); - return false; + return false; } // end of DefineAM /***********************************************************************/ @@ -924,7 +924,7 @@ void TDBDIR::CloseDB(PGLOBAL) /***********************************************************************/ /* DIRCOL public constructor. */ /***********************************************************************/ -DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ) +DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ) : COLBLK(cdp, tdbp, i) { if (cprec) { @@ -1016,11 +1016,7 @@ void DIRCOL::ReadColumn(PGLOBAL g) #endif // !__WIN__ default: sprintf(g->Message, MSG(INV_DIRCOL_OFST), N); -#if defined(USE_TRY) throw GetAmType(); -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], GetAmType()); -#endif // !USE_TRY } // endswitch N } // end of ReadColumn @@ -1247,8 +1243,8 @@ int TDBSDR::ReadDB(PGLOBAL g) break; } // endif findnext - } while (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || - (*FileData.cFileName == '.' && + } while(!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || + (*FileData.cFileName == '.' && (!FileData.cFileName[1] || FileData.cFileName[1] == '.'))); if (Sub->H == INVALID_HANDLE_VALUE) { @@ -1303,9 +1299,9 @@ int TDBSDR::ReadDB(PGLOBAL g) if (lstat(Fpath, &Fileinfo) < 0) { sprintf(g->Message, "%s: %s", Fpath, strerror(errno)); rc = RC_FX; - } else if (S_ISDIR(Fileinfo.st_mode) && strcmp(Entry->d_name, ".") - && strcmp(Entry->d_name, "..")) { - // Look in the name sub-directory + } else if (S_ISDIR(Fileinfo.st_mode) && strcmp(Entry->d_name, ".") + && strcmp(Entry->d_name, "..")) { + // Look in the name sub-directory if (!Sub->Next) { PSUBDIR sup; @@ -1548,11 +1544,7 @@ void TDBDHR::CloseDB(PGLOBAL g) // Close the search handle. if (!FindClose(Hsearch)) { strcpy(g->Message, MSG(SRCH_CLOSE_ERR)); -#if defined(USE_TRY) throw GetAmType(); -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], GetAmType()); -#endif // !USE_TRY } // endif FindClose iFile = 0; @@ -1564,8 +1556,8 @@ void TDBDHR::CloseDB(PGLOBAL g) /***********************************************************************/ /* DHRCOL public constructor. */ /***********************************************************************/ -DHRCOL::DHRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) - : COLBLK(cdp, tdbp, i) +DHRCOL::DHRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) + : COLBLK(cdp, tdbp, i) { if (cprec) { Next = cprec->GetNext(); diff --git a/storage/connect/tabmul.h b/storage/connect/tabmul.h index f26d982d49b..8a95a772c41 100644 --- a/storage/connect/tabmul.h +++ b/storage/connect/tabmul.h @@ -39,7 +39,7 @@ class DllExport TDBMUL : public TDBASE { virtual void ResetDB(void); virtual PTDB Clone(PTABS t); virtual bool IsSame(PTDB tp) {return tp == (PTDB)Tdbp;} - virtual PSZ GetFile(PGLOBAL g) {return Tdbp->GetFile(g);} + virtual PCSZ GetFile(PGLOBAL g) {return Tdbp->GetFile(g);} virtual int GetRecpos(void) {return 0;} virtual PCOL ColDB(PGLOBAL g, PSZ name, int num); bool InitFileNames(PGLOBAL g); @@ -118,9 +118,9 @@ class DllExport DIRDEF : public TABDEF { /* Directory listing table */ // Members PSZ Fn; /* Path/Name of file search */ bool Incl; /* true to include sub-directories */ - bool Huge; /* true if files can be larger than 2GB */ + bool Huge; /* true if files can be larger than 2GB */ bool Nodir; /* true to exclude directories */ -}; // end of DIRDEF + }; // end of DIRDEF /***********************************************************************/ /* This is the DIR Access Method class declaration for tables that */ @@ -177,7 +177,7 @@ public: char Fname[_MAX_FNAME]; // File name char Ftype[_MAX_EXT]; // File extention bool Nodir; // Exclude directories from file list -}; // end of class TDBDIR + }; // end of class TDBDIR /***********************************************************************/ /* This is the DIR Access Method class declaration for tables that */ @@ -226,7 +226,7 @@ class TDBSDR : public TDBDIR { class DIRCOL : public COLBLK { public: // Constructors - DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "DIR"); + DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "DIR"); DIRCOL(DIRCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 3ce1ea1f7d8..bdddcf64ca8 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -68,8 +68,8 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES); #endif // _CONSOLE // Used to check whether a MYSQL table is created on itself -bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host, - const char *db, char *tab, const char *src, int port); +bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, PCSZ db, + PCSZ tab, PCSZ src, int port); /***********************************************************************/ /* External function. */ @@ -125,7 +125,7 @@ bool MYSQLDEF::GetServerInfo(PGLOBAL g, const char *server_name) } // endif server DBUG_PRINT("info", ("get_server_by_name returned server at %lx", - (long unsigned int) server)); + (size_t) server)); // TODO: We need to examine which of these can really be NULL Hostname = PlugDup(g, server->host); @@ -183,19 +183,22 @@ bool MYSQLDEF::GetServerInfo(PGLOBAL g, const char *server_name) /***********************************************************************/ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b) { + char *tabn, *pwd, *schema; + if ((!strstr(url, "://") && (!strchr(url, '@')))) { // No :// or @ in connection string. Must be a straight // connection name of either "server" or "server/table" // ok, so we do a little parsing, but not completely! - if ((Tabname= strchr(url, '/'))) { + if ((tabn= strchr(url, '/'))) { // If there is a single '/' in the connection string, // this means the user is specifying a table name - *Tabname++= '\0'; + *tabn++= '\0'; // there better not be any more '/'s ! - if (strchr(Tabname, '/')) + if (strchr(tabn, '/')) return true; + Tabname = tabn; } else // Otherwise, straight server name, Tabname = (b) ? GetStringCatInfo(g, "Tabname", Name) : NULL; @@ -223,7 +226,7 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b) Username += 3; - if (!(Hostname = strchr(Username, '@'))) { + if (!(Hostname = (char*)strchr(Username, '@'))) { strcpy(g->Message, "No host specified in URL"); return true; } else { @@ -231,11 +234,11 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b) Server = Hostname; } // endif Hostname - if ((Password = strchr(Username, ':'))) { - *Password++ = 0; // End username + if ((pwd = (char*)strchr(Username, ':'))) { + *pwd++ = 0; // End username - // Make sure there isn't an extra / or @ - if ((strchr(Password, '/') || strchr(Hostname, '@'))) { + // Make sure there isn't an extra / + if (strchr(pwd, '/')) { strcpy(g->Message, "Syntax error in URL"); return true; } // endif @@ -243,8 +246,10 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b) // Found that if the string is: // user:@hostname:port/db/table // Then password is a null string, so set to NULL - if ((Password[0] == 0)) - Password = NULL; + if ((pwd[0] == 0)) + Password = NULL; + else + Password = pwd; } // endif password @@ -254,21 +259,23 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b) return true; } // endif - if ((Tabschema = strchr(Hostname, '/'))) { - *Tabschema++ = 0; + if ((schema = strchr(Hostname, '/'))) { + *schema++ = 0; - if ((Tabname = strchr(Tabschema, '/'))) { - *Tabname++ = 0; + if ((tabn = strchr(schema, '/'))) { + *tabn++ = 0; // Make sure there's not an extra / - if ((strchr(Tabname, '/'))) { + if ((strchr(tabn, '/'))) { strcpy(g->Message, "Syntax error in URL"); return true; } // endif / + Tabname = tabn; } // endif TableName - } // endif database + Tabschema = schema; + } // endif database if ((sport = strchr(Hostname, ':'))) *sport++ = 0; @@ -349,7 +356,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int) Portnumber = GetIntCatInfo("Port", GetDefaultPort()); Server = Hostname; } else { - char *locdb = Tabschema; + PCSZ locdb = Tabschema; if (ParseURL(g, url)) return true; @@ -495,11 +502,11 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) /* filter should be removed from column list. */ /***********************************************************************/ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx) - { +{ //char *tk = "`"; char tk = '`'; int len = 0, rank = 0; - bool b = false, oom = false; + bool b = false; PCOL colp; //PDBUSER dup = PlgGetUser(g); @@ -526,13 +533,13 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx) for (colp = Columns; colp; colp = colp->GetNext()) if (!colp->IsSpecial()) { if (b) - oom |= Query->Append(", "); + Query->Append(", "); else b = true; - oom |= Query->Append(tk); - oom |= Query->Append(colp->GetName()); - oom |= Query->Append(tk); + Query->Append(tk); + Query->Append(colp->GetName()); + Query->Append(tk); ((PMYCOL)colp)->Rank = rank++; } // endif colp @@ -542,22 +549,22 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx) // Query '*' from... // (the use of a char constant minimize the result storage) if (Isview) - oom |= Query->Append('*'); + Query->Append('*'); else - oom |= Query->Append("'*'"); + Query->Append("'*'"); } // endif ncol - oom |= Query->Append(" FROM "); - oom |= Query->Append(tk); - oom |= Query->Append(TableName); - oom |= Query->Append(tk); + Query->Append(" FROM "); + Query->Append(tk); + Query->Append(TableName); + Query->Append(tk); len = Query->GetLength(); if (To_CondFil) { if (!mx) { - oom |= Query->Append(" WHERE "); - oom |= Query->Append(To_CondFil->Body); + Query->Append(" WHERE "); + Query->Append(To_CondFil->Body); len = Query->GetLength() + 1; } else len += (strlen(To_CondFil->Body) + 256); @@ -565,25 +572,25 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx) } else len += (mx ? 256 : 1); - if (oom || Query->Resize(len)) { + if (Query->IsTruncated() || Query->Resize(len)) { strcpy(g->Message, "MakeSelect: Out of memory"); return true; - } // endif oom + } // endif Query if (trace) htrc("Query=%s\n", Query->GetStr()); return false; - } // end of MakeSelect +} // end of MakeSelect /***********************************************************************/ /* MakeInsert: make the Insert statement used with MySQL connection. */ /***********************************************************************/ bool TDBMYSQL::MakeInsert(PGLOBAL g) { - char *tk = "`"; + const char *tk = "`"; uint len = 0; - bool b = false, oom; + bool oom, b = false; PCOL colp; if (Query) @@ -622,38 +629,38 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g) Query = new(g) STRING(g, len); if (Delayed) - oom = Query->Set("INSERT DELAYED INTO "); + Query->Set("INSERT DELAYED INTO "); else - oom = Query->Set("INSERT INTO "); + Query->Set("INSERT INTO "); - oom |= Query->Append(tk); - oom |= Query->Append(TableName); - oom |= Query->Append("` ("); + Query->Append(tk); + Query->Append(TableName); + Query->Append("` ("); for (colp = Columns; colp; colp = colp->GetNext()) { if (b) - oom |= Query->Append(", "); + Query->Append(", "); else b = true; - oom |= Query->Append(tk); - oom |= Query->Append(colp->GetName()); - oom |= Query->Append(tk); + Query->Append(tk); + Query->Append(colp->GetName()); + Query->Append(tk); } // endfor colp - oom |= Query->Append(") VALUES ("); + Query->Append(") VALUES ("); #if defined(MYSQL_PREPARED_STATEMENTS) if (Prep) { for (int i = 0; i < Nparm; i++) - oom |= Query->Append("?,"); + Query->Append("?,"); Query->RepLast(')'); Query->Trim(); } // endif Prep #endif // MYSQL_PREPARED_STATEMENTS - if (oom) + if ((oom = Query->IsTruncated())) strcpy(g->Message, "MakeInsert: Out of memory"); return oom; @@ -684,18 +691,18 @@ bool TDBMYSQL::MakeCommand(PGLOBAL g) strlwr(strcpy(name, Name)); // Not a keyword if ((p = strstr(qrystr, name))) { - bool oom = Query->Set(Qrystr, p - qrystr); + Query->Set(Qrystr, p - qrystr); if (qtd && *(p-1) == ' ') { - oom |= Query->Append('`'); - oom |= Query->Append(TableName); - oom |= Query->Append('`'); + Query->Append('`'); + Query->Append(TableName); + Query->Append('`'); } else - oom |= Query->Append(TableName); + Query->Append(TableName); - oom |= Query->Append(Qrystr + (p - qrystr) + strlen(name)); + Query->Append(Qrystr + (p - qrystr) + strlen(name)); - if (oom) { + if (Query->IsTruncated()) { strcpy(g->Message, "MakeCommand: Out of memory"); return true; } else @@ -1096,7 +1103,7 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr) To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0); *To_CondFil->Body= 0; - if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond))) + if ((To_CondFil = hc->CheckCond(g, To_CondFil, Cond))) PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1); } // endif active_index @@ -1161,24 +1168,23 @@ int TDBMYSQL::WriteDB(PGLOBAL g) int rc; uint len = Query->GetLength(); char buf[64]; - bool oom = false; // Make the Insert command value list for (PCOL colp = Columns; colp; colp = colp->GetNext()) { if (!colp->GetValue()->IsNull()) { if (colp->GetResultType() == TYPE_STRING || colp->GetResultType() == TYPE_DATE) - oom |= Query->Append_quoted(colp->GetValue()->GetCharString(buf)); + Query->Append_quoted(colp->GetValue()->GetCharString(buf)); else - oom |= Query->Append(colp->GetValue()->GetCharString(buf)); + Query->Append(colp->GetValue()->GetCharString(buf)); } else - oom |= Query->Append("NULL"); + Query->Append("NULL"); - oom |= Query->Append(','); + Query->Append(','); } // endfor colp - if (unlikely(oom)) { + if (unlikely(Query->IsTruncated())) { strcpy(g->Message, "WriteDB: Out of memory"); rc = RC_FX; } else { @@ -1186,7 +1192,7 @@ int TDBMYSQL::WriteDB(PGLOBAL g) Myc.m_Rows = -1; // To execute the query rc = Myc.ExecSQL(g, Query->GetStr()); Query->Truncate(len); // Restore query - } // endif oom + } // endif Query return (rc == RC_NF) ? RC_OK : rc; // RC_NF is Ok } // end of WriteDB @@ -1234,7 +1240,7 @@ void TDBMYSQL::CloseDB(PGLOBAL g) /***********************************************************************/ /* MYSQLCOL public constructor. */ /***********************************************************************/ -MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : COLBLK(cdp, tdbp, i) { if (cprec) { @@ -1260,7 +1266,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) /***********************************************************************/ /* MYSQLCOL public constructor. */ /***********************************************************************/ -MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am) +MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am) : COLBLK(NULL, tdbp, i) { const char *chset = get_charset_name(fld->charsetnr); @@ -1407,11 +1413,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g) if (rc == RC_EF) sprintf(g->Message, MSG(INV_DEF_READ), rc); -#if defined(USE_TRY) throw 11; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 11); -#endif // !USE_TRY } else tdbp->Fetched = true; @@ -1673,7 +1675,7 @@ int TDBMYEXC::WriteDB(PGLOBAL g) /***********************************************************************/ /* MYXCOL public constructor. */ /***********************************************************************/ -MYXCOL::MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +MYXCOL::MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : MYSQLCOL(cdp, tdbp, cprec, i, am) { // Set additional EXEC MYSQL access method information for column. @@ -1683,7 +1685,7 @@ MYXCOL::MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) /***********************************************************************/ /* MYSQLCOL public constructor. */ /***********************************************************************/ -MYXCOL::MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am) +MYXCOL::MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am) : MYSQLCOL(fld, tdbp, i, am) { if (trace) diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h index 050fa59259b..3c37ae5bf3b 100644 --- a/storage/connect/tabmysql.h +++ b/storage/connect/tabmysql.h @@ -86,7 +86,7 @@ class TDBMYSQL : public TDBEXT { virtual void ResetDB(void) {N = 0;} virtual int RowNumber(PGLOBAL g, bool b = false); virtual bool IsView(void) {return Isview;} - virtual PSZ GetServer(void) {return Server;} + virtual PCSZ GetServer(void) {return Server;} void SetDatabase(LPCSTR db) {Schema = (char*)db;} // Schema routines @@ -109,7 +109,7 @@ class TDBMYSQL : public TDBEXT { // Internal functions bool MakeSelect(PGLOBAL g, bool mx); bool MakeInsert(PGLOBAL g); - int BindColumns(PGLOBAL g); + int BindColumns(PGLOBAL g __attribute__((unused))); virtual bool MakeCommand(PGLOBAL g); //int MakeUpdate(PGLOBAL g); //int MakeDelete(PGLOBAL g); @@ -146,8 +146,8 @@ class MYSQLCOL : public COLBLK { friend class TDBMYSQL; public: // Constructors - MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL"); - MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am = "MYSQL"); + MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "MYSQL"); + MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am = "MYSQL"); MYSQLCOL(MYSQLCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation @@ -215,8 +215,8 @@ class MYXCOL : public MYSQLCOL { friend class TDBMYEXC; public: // Constructors - MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL"); - MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am = "MYSQL"); + MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "MYSQL"); + MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am = "MYSQL"); MYXCOL(MYXCOL *colp, PTDB tdbp); // Constructor used in copy process // Methods @@ -242,10 +242,10 @@ class TDBMCL : public TDBCAT { virtual PQRYRES GetResult(PGLOBAL g); // Members - PSZ Host; // Host machine to use - PSZ Db; // Database to be used by server - PSZ Tab; // External table name - PSZ User; // User logon name - PSZ Pwd; // Password logon info - int Port; // MySQL port number (0 = default) + PCSZ Host; // Host machine to use + PCSZ Db; // Database to be used by server + PCSZ Tab; // External table name + PCSZ User; // User logon name + PCSZ Pwd; // Password logon info + int Port; // MySQL port number (0 = default) }; // end of class TDBMCL diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index b8c8a4d8cb4..34711d584f1 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -1,11 +1,11 @@ /************* Tabodbc C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABODBC */ /* ------------- */ -/* Version 3.1 */ +/* Version 3.2 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2000-2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2000-2017 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -231,7 +231,7 @@ PCOL TDBODBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) /* This used for Multiple(1) tables. Also prepare a connect string */ /* with a place holder to be used by SetFile. */ /***********************************************************************/ -PSZ TDBODBC::GetFile(PGLOBAL g) +PCSZ TDBODBC::GetFile(PGLOBAL g) { if (Connect) { char *p1, *p2; @@ -297,9 +297,10 @@ void TDBODBC::SetFile(PGLOBAL g, PSZ fn) /***********************************************************************/ bool TDBODBC::MakeInsert(PGLOBAL g) { - char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3]; + PCSZ schmp = NULL; + char *catp = NULL, buf[NAM_LEN * 3]; int len = 0; - bool b = false, oom = false; + bool oom, b = false; PTABLE tablep = To_Table; PCOL colp; @@ -336,32 +337,32 @@ bool TDBODBC::MakeInsert(PGLOBAL g) Query = new(g) STRING(g, len, "INSERT INTO "); if (catp) { - oom |= Query->Append(catp); + Query->Append(catp); if (schmp) { - oom |= Query->Append('.'); - oom |= Query->Append(schmp); + Query->Append('.'); + Query->Append(schmp); } // endif schmp - oom |= Query->Append('.'); + Query->Append('.'); } else if (schmp) { - oom |= Query->Append(schmp); - oom |= Query->Append('.'); + Query->Append(schmp); + Query->Append('.'); } // endif schmp if (Quote) { // Put table name between identifier quotes in case in contains blanks - oom |= Query->Append(Quote); - oom |= Query->Append(buf); - oom |= Query->Append(Quote); + Query->Append(Quote); + Query->Append(buf); + Query->Append(Quote); } else - oom |= Query->Append(buf); + Query->Append(buf); - oom |= Query->Append('('); + Query->Append('('); for (colp = Columns; colp; colp = colp->GetNext()) { if (b) - oom |= Query->Append(", "); + Query->Append(", "); else b = true; @@ -370,20 +371,20 @@ bool TDBODBC::MakeInsert(PGLOBAL g) if (Quote) { // Put column name between identifier quotes in case in contains blanks - oom |= Query->Append(Quote); - oom |= Query->Append(buf); - oom |= Query->Append(Quote); + Query->Append(Quote); + Query->Append(buf); + Query->Append(Quote); } else - oom |= Query->Append(buf); + Query->Append(buf); } // endfor colp - oom |= Query->Append(") VALUES ("); + Query->Append(") VALUES ("); for (int i = 0; i < Nparm; i++) - oom |= Query->Append("?,"); + Query->Append("?,"); - if (oom) + if ((oom = Query->IsTruncated())) strcpy(g->Message, "MakeInsert: Out of memory"); else Query->RepLast(')'); @@ -733,7 +734,7 @@ bool TDBODBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr) To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0); *To_CondFil->Body= 0; - if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond))) + if ((To_CondFil = hc->CheckCond(g, To_CondFil, Cond))) PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1); } // endif active_index @@ -883,7 +884,7 @@ void TDBODBC::CloseDB(PGLOBAL g) /***********************************************************************/ /* ODBCCOL public constructor. */ /***********************************************************************/ -ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : EXTCOL(cdp, tdbp, cprec, i, am) { // Set additional ODBC access method information for column. @@ -1301,7 +1302,7 @@ int TDBXDBC::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ /* XSRCCOL public constructor. */ /***********************************************************************/ -XSRCCOL::XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +XSRCCOL::XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : ODBCCOL(cdp, tdbp, cprec, i, am) { // Set additional ODBC access method information for column. diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h index 7c65a8ea7e5..487a5073559 100644 --- a/storage/connect/tabodbc.h +++ b/storage/connect/tabodbc.h @@ -70,10 +70,10 @@ class TDBODBC : public TDBEXT { // Methods virtual PTDB Clone(PTABS t); virtual bool SetRecpos(PGLOBAL g, int recpos); - virtual PSZ GetFile(PGLOBAL g); + virtual PCSZ GetFile(PGLOBAL g); virtual void SetFile(PGLOBAL g, PSZ fn); virtual void ResetSize(void); - virtual PSZ GetServer(void) {return "ODBC";} + virtual PCSZ GetServer(void) {return "ODBC";} virtual int Indexable(void) {return 2;} // Database routines @@ -108,7 +108,7 @@ class ODBCCOL : public EXTCOL { friend class TDBODBC; public: // Constructors - ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ODBC"); + ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "ODBC"); ODBCCOL(ODBCCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation @@ -179,7 +179,7 @@ class XSRCCOL : public ODBCCOL { friend class TDBXDBC; public: // Constructors - XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ODBC"); + XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "ODBC"); XSRCCOL(XSRCCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation @@ -239,10 +239,10 @@ class TDBOTB : public TDBDRV { virtual PQRYRES GetResult(PGLOBAL g); // Members - char *Dsn; // Points to connection string - char *Schema; // Points to schema name or NULL - char *Tab; // Points to ODBC table name or pattern - char *Tabtyp; // Points to ODBC table type + PCSZ Dsn; // Points to connection string + PCSZ Schema; // Points to schema name or NULL + PCSZ Tab; // Points to ODBC table name or pattern + PCSZ Tabtyp; // Points to ODBC table type ODBCPARM Ops; // Additional parameters }; // end of class TDBOTB diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index f24929eb2bb..76a46e6899b 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -106,7 +106,7 @@ bool PIVAID::SkipColumn(PCOLRES crp, char *skc) /* Make the Pivot table column list. */ /***********************************************************************/ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) - { +{ char *p, *query, *colname, *skc, buf[64]; int ndif, nblin, w = 0; bool b = false; @@ -114,205 +114,190 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) PQRYRES qrp; PCOLRES *pcrp, crp, fncrp = NULL; -#if defined(USE_TRY) try { -#else // !USE_TRY - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return NULL; - } // endif jump_level + // Are there columns to skip? + if (Skcol) { + uint n = strlen(Skcol); - if (setjmp(g->jumper[++g->jump_level])) { - goto err; - } // endif rc -#endif // !USE_TRY + skc = (char*)PlugSubAlloc(g, NULL, n + 2); + strcpy(skc, Skcol); + skc[n + 1] = 0; - // Are there columns to skip? - if (Skcol) { - uint n = strlen(Skcol); + // Replace ; by nulls in skc + for (p = strchr(skc, ';'); p; p = strchr(p, ';')) + *p++ = 0; - skc = (char*)PlugSubAlloc(g, NULL, n + 2); - strcpy(skc, Skcol); - skc[n + 1] = 0; + } else + skc = NULL; - // Replace ; by nulls in skc - for (p = strchr(skc, ';'); p; p = strchr(p, ';')) - *p++ = 0; + if (!Tabsrc && Tabname) { + // Locate the query + query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 26); + sprintf(query, "SELECT * FROM `%s` LIMIT 1", Tabname); + } else if (!Tabsrc) { + strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); + goto err; + } else + query = (char*)Tabsrc; - } else - skc = NULL; + // Open a MySQL connection for this table + if (!Myc.Open(g, Host, Database, User, Pwd, Port)) { + b = true; - if (!Tabsrc && Tabname) { - // Locate the query - query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 26); - sprintf(query, "SELECT * FROM `%s` LIMIT 1", Tabname); - } else if (!Tabsrc) { - strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); - goto err; - } else - query = Tabsrc; + // Returned values must be in their original character set + if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX) + goto err; + else + Myc.FreeResult(); - // Open a MySQL connection for this table - if (!Myc.Open(g, Host, Database, User, Pwd, Port)) { - b = true; - - // Returned values must be in their original character set - if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX) - goto err; - else - Myc.FreeResult(); - - } else - goto err; - - // Send the source command to MySQL - if (Myc.ExecSQL(g, query, &w) == RC_FX) - goto err; - - // We must have a storage query to get pivot column values - if (!(Qryp = Myc.GetResult(g, true))) - goto err; - - if (!Fncol) { - for (crp = Qryp->Colresp; crp; crp = crp->Next) - if ((!Picol || stricmp(Picol, crp->Name)) && !SkipColumn(crp, skc)) - Fncol = crp->Name; - - if (!Fncol) { - strcpy(g->Message, MSG(NO_DEF_FNCCOL)); - goto err; - } // endif Fncol - - } // endif Fncol - - if (!Picol) { - // Find default Picol as the last one not equal to Fncol - for (crp = Qryp->Colresp; crp; crp = crp->Next) - if (stricmp(Fncol, crp->Name) && !SkipColumn(crp, skc)) - Picol = crp->Name; - - if (!Picol) { - strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); - goto err; - } // endif Picol - - } // endif picol - - // Prepare the column list - for (pcrp = &Qryp->Colresp; crp = *pcrp; ) - if (SkipColumn(crp, skc)) { - // Ignore this column - *pcrp = crp->Next; - } else if (!stricmp(Picol, crp->Name)) { - if (crp->Nulls) { - sprintf(g->Message, "Pivot column %s cannot be nullable", Picol); - goto err; - } // endif Nulls - - Rblkp = crp->Kdata; - *pcrp = crp->Next; - } else if (!stricmp(Fncol, crp->Name)) { - fncrp = crp; - *pcrp = crp->Next; - } else - pcrp = &crp->Next; - - if (!Rblkp) { - strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); - goto err; - } else if (!fncrp) { - strcpy(g->Message, MSG(NO_DEF_FNCCOL)); - goto err; - } // endif - - if (Tabsrc) { - Myc.Close(); - b = false; - - // Before calling sort, initialize all - nblin = Qryp->Nblin; - - Index.Size = nblin * sizeof(int); - Index.Sub = TRUE; // Should be small enough - - if (!PlgDBalloc(g, NULL, Index)) + } else goto err; - Offset.Size = (nblin + 1) * sizeof(int); - Offset.Sub = TRUE; // Should be small enough - - if (!PlgDBalloc(g, NULL, Offset)) + // Send the source command to MySQL + if (Myc.ExecSQL(g, query, &w) == RC_FX) goto err; - ndif = Qsort(g, nblin); - - if (ndif < 0) // error + // We must have a storage query to get pivot column values + if (!(Qryp = Myc.GetResult(g, true))) goto err; - } else { - // The query was limited, we must get pivot column values - // Returned values must be in their original character set -// if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX) -// goto err; + if (!Fncol) { + for (crp = Qryp->Colresp; crp; crp = crp->Next) + if ((!Picol || stricmp(Picol, crp->Name)) && !SkipColumn(crp, skc)) + Fncol = crp->Name; - query = (char*)PlugSubAlloc(g, NULL, 0); - sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname); - PlugSubAlloc(g, NULL, strlen(query) + 1); - Myc.FreeResult(); + if (!Fncol) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + goto err; + } // endif Fncol - // Send the source command to MySQL - if (Myc.ExecSQL(g, query, &w) == RC_FX) - goto err; + } // endif Fncol - // We must have a storage query to get pivot column values - if (!(qrp = Myc.GetResult(g, true))) - goto err; + if (!Picol) { + // Find default Picol as the last one not equal to Fncol + for (crp = Qryp->Colresp; crp; crp = crp->Next) + if (stricmp(Fncol, crp->Name) && !SkipColumn(crp, skc)) + Picol = crp->Name; - Myc.Close(); - b = false; + if (!Picol) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + goto err; + } // endif Picol - // Get the column list - crp = qrp->Colresp; - Rblkp = crp->Kdata; - ndif = qrp->Nblin; - } // endif Tabsrc + } // endif picol - // Allocate the Value used to retieve column names - if (!(valp = AllocateValue(g, Rblkp->GetType(), - Rblkp->GetVlen(), - Rblkp->GetPrec()))) - goto err; + // Prepare the column list + for (pcrp = &Qryp->Colresp; crp = *pcrp; ) + if (SkipColumn(crp, skc)) { + // Ignore this column + *pcrp = crp->Next; + } else if (!stricmp(Picol, crp->Name)) { + if (crp->Nulls) { + sprintf(g->Message, "Pivot column %s cannot be nullable", Picol); + goto err; + } // endif Nulls - // Now make the functional columns - for (int i = 0; i < ndif; i++) { - if (i) { - crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); - memcpy(crp, fncrp, sizeof(COLRES)); - } else - crp = fncrp; + Rblkp = crp->Kdata; + *pcrp = crp->Next; + } else if (!stricmp(Fncol, crp->Name)) { + fncrp = crp; + *pcrp = crp->Next; + } else + pcrp = &crp->Next; - // Get the value that will be the generated column name - if (Tabsrc) - valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); - else - valp->SetValue_pvblk(Rblkp, i); + if (!Rblkp) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + goto err; + } else if (!fncrp) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + goto err; + } // endif - colname = valp->GetCharString(buf); - crp->Name = PlugDup(g, colname); - crp->Flag = 1; + if (Tabsrc) { + Myc.Close(); + b = false; - // Add this column - *pcrp = crp; - crp->Next = NULL; - pcrp = &crp->Next; - } // endfor i + // Before calling sort, initialize all + nblin = Qryp->Nblin; - // We added ndif columns and removed 2 (picol and fncol) - Qryp->Nbcol += (ndif - 2); -#if defined(USE_TRY) - return Qryp; + Index.Size = nblin * sizeof(int); + Index.Sub = TRUE; // Should be small enough + if (!PlgDBalloc(g, NULL, Index)) + goto err; + + Offset.Size = (nblin + 1) * sizeof(int); + Offset.Sub = TRUE; // Should be small enough + + if (!PlgDBalloc(g, NULL, Offset)) + goto err; + + ndif = Qsort(g, nblin); + + if (ndif < 0) // error + goto err; + + } else { + // The query was limited, we must get pivot column values + // Returned values must be in their original character set + // if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX) + // goto err; + + query = (char*)PlugSubAlloc(g, NULL, 0); + sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname); + PlugSubAlloc(g, NULL, strlen(query) + 1); + Myc.FreeResult(); + + // Send the source command to MySQL + if (Myc.ExecSQL(g, query, &w) == RC_FX) + goto err; + + // We must have a storage query to get pivot column values + if (!(qrp = Myc.GetResult(g, true))) + goto err; + + Myc.Close(); + b = false; + + // Get the column list + crp = qrp->Colresp; + Rblkp = crp->Kdata; + ndif = qrp->Nblin; + } // endif Tabsrc + + // Allocate the Value used to retieve column names + if (!(valp = AllocateValue(g, Rblkp->GetType(), + Rblkp->GetVlen(), + Rblkp->GetPrec()))) + goto err; + + // Now make the functional columns + for (int i = 0; i < ndif; i++) { + if (i) { + crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); + memcpy(crp, fncrp, sizeof(COLRES)); + } else + crp = fncrp; + + // Get the value that will be the generated column name + if (Tabsrc) + valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); + else + valp->SetValue_pvblk(Rblkp, i); + + colname = valp->GetCharString(buf); + crp->Name = PlugDup(g, colname); + crp->Flag = 1; + + // Add this column + *pcrp = crp; + crp->Next = NULL; + pcrp = &crp->Next; + } // endfor i + + // We added ndif columns and removed 2 (picol and fncol) + Qryp->Nbcol += (ndif - 2); + return Qryp; } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); @@ -321,19 +306,11 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) } // end catch err: -#else // !USE_TRY - g->jump_level--; - return Qryp; - -err: - g->jump_level--; -#endif // !USE_TRY - if (b) Myc.Close(); return NULL; - } // end of MakePivotColumns +} // end of MakePivotColumns /***********************************************************************/ /* PIVAID: Compare routine for sorting pivot column values. */ diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h index 07d5c3e456b..6c2d53e9527 100644 --- a/storage/connect/tabpivot.h +++ b/storage/connect/tabpivot.h @@ -32,16 +32,16 @@ class PIVAID : public CSORT { protected: // Members MYSQLC Myc; // MySQL connection class - char *Host; // Host machine to use - char *User; // User logon info - char *Pwd; // Password logon info - char *Database; // Database to be used by server + PCSZ Host; // Host machine to use + PCSZ User; // User logon info + PCSZ Pwd; // Password logon info + PCSZ Database; // Database to be used by server PQRYRES Qryp; // Points to Query result block - char *Tabname; // Name of source table - char *Tabsrc; // SQL of source table - char *Picol; // Pivot column name - char *Fncol; // Function column name - char *Skcol; // Skipped columns + PCSZ Tabname; // Name of source table + PCSZ Tabsrc; // SQL of source table + PCSZ Picol; // Pivot column name + PCSZ Fncol; // Function column name + PCSZ Skcol; // Skipped columns PVBLK Rblkp; // The value block of the pivot column int Port; // MySQL port number }; // end of class PIVAID diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp index d2f5cdb2780..7f0d9881298 100644 --- a/storage/connect/tabsys.cpp +++ b/storage/connect/tabsys.cpp @@ -355,7 +355,7 @@ void TDBINI::CloseDB(PGLOBAL) /***********************************************************************/ /* INICOL public constructor. */ /***********************************************************************/ -INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ) +INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ) : COLBLK(cdp, tdbp, i) { if (cprec) { @@ -511,19 +511,11 @@ void INICOL::WriteColumn(PGLOBAL g) if (strlen(p) > (unsigned)Long) { sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (Flag == 1) { if (tdbp->Mode == MODE_UPDATE) { strcpy(g->Message, MSG(NO_SEC_UPDATE)); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (*p) { tdbp->Section = p; } else @@ -532,11 +524,7 @@ void INICOL::WriteColumn(PGLOBAL g) return; } else if (!tdbp->Section) { strcpy(g->Message, MSG(SEC_NAME_FIRST)); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endif's /*********************************************************************/ @@ -548,11 +536,7 @@ void INICOL::WriteColumn(PGLOBAL g) if (!rc) { sprintf(g->Message, "Error %d writing to %s", GetLastError(), tdbp->Ifile); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endif rc } // endif Status @@ -785,7 +769,7 @@ int TDBXIN::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ /* XINCOL public constructor. */ /***********************************************************************/ -XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : INICOL(cdp, tdbp, cprec, i, am) { } // end of XINCOL constructor @@ -853,19 +837,11 @@ void XINCOL::WriteColumn(PGLOBAL g) if (strlen(p) > (unsigned)Long) { sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (Flag == 1) { if (tdbp->Mode == MODE_UPDATE) { strcpy(g->Message, MSG(NO_SEC_UPDATE)); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (*p) { tdbp->Section = p; } else @@ -875,11 +851,7 @@ void XINCOL::WriteColumn(PGLOBAL g) } else if (Flag == 2) { if (tdbp->Mode == MODE_UPDATE) { strcpy(g->Message, MSG(NO_KEY_UPDATE)); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } else if (*p) { tdbp->Keycur = p; } else @@ -888,11 +860,7 @@ void XINCOL::WriteColumn(PGLOBAL g) return; } else if (!tdbp->Section || !tdbp->Keycur) { strcpy(g->Message, MSG(SEC_KEY_FIRST)); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endif's /*********************************************************************/ @@ -904,11 +872,7 @@ void XINCOL::WriteColumn(PGLOBAL g) if (!rc) { sprintf(g->Message, "Error %d writing to %s", GetLastError(), tdbp->Ifile); -#if defined(USE_TRY) throw 31; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 31); -#endif // !USE_TRY } // endif rc } // endif Status diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h index ff1b8335690..44b5a137a70 100644 --- a/storage/connect/tabsys.h +++ b/storage/connect/tabsys.h @@ -61,7 +61,7 @@ class TDBINI : public TDBASE { virtual int GetRecpos(void) {return N;} virtual int GetProgCur(void) {return N;} //virtual int GetAffectedRows(void) {return 0;} - virtual PSZ GetFile(PGLOBAL g) {return Ifile;} + virtual PCSZ GetFile(PGLOBAL g) {return Ifile;} virtual void SetFile(PGLOBAL g, PSZ fn) {Ifile = fn;} virtual void ResetDB(void) {Seclist = Section = NULL; N = 0;} virtual void ResetSize(void) {MaxSize = -1; Seclist = NULL;} @@ -93,7 +93,7 @@ class TDBINI : public TDBASE { class INICOL : public COLBLK { public: // Constructors - INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI"); + INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "INI"); INICOL(INICOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation @@ -165,7 +165,7 @@ class TDBXIN : public TDBINI { class XINCOL : public INICOL { public: // Constructors - XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI"); + XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "INI"); XINCOL(XINCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 762c61bd1a1..574cef28ea3 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -119,7 +119,8 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM, FLD_NO, FLD_CHARSET}; unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32}; - char *pn, *tn, *fld, *colname, *chset, *fmt, v; + PCSZ fmt; + char *pn, *tn, *fld, *colname, *chset, v; int i, n, ncol = sizeof(buftyp) / sizeof(int); int prec, len, type, scale; int zconv = GetConvSize(); @@ -227,7 +228,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, fmt = MyDateFmt(fp->type()); prec = len = strlen(fmt); } else { - fmt = (char*)fp->option_struct->dateformat; + fmt = (PCSZ)fp->option_struct->dateformat; prec = len = fp->field_length; } // endif mysql @@ -314,7 +315,7 @@ bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR, int) strcpy(g->Message, "Missing object table definition"); return true; } else - tab = "Noname"; + tab = PlugDup(g, "Noname"); } else // Analyze the table name, it may have the format: [dbname.]tabname @@ -626,7 +627,7 @@ void TDBPRX::RemoveNext(PTABLE tp) /***********************************************************************/ /* PRXCOL public constructor. */ /***********************************************************************/ -PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) +PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : COLBLK(cdp, tdbp, i) { if (cprec) { @@ -741,7 +742,14 @@ void PRXCOL::ReadColumn(PGLOBAL g) if (Nullable) Value->SetNull(Value->IsNull()); - } // endif Colp + } else { + Value->Reset(); + + // Set null when applicable + if (Nullable) + Value->SetNull(true); + + } // endif Colp } // end of ReadColumn diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h index 8e56aecff86..62678508ca1 100644 --- a/storage/connect/tabutil.h +++ b/storage/connect/tabutil.h @@ -71,7 +71,7 @@ class DllExport TDBPRX : public TDBASE { virtual int GetRecpos(void) {return Tdbp->GetRecpos();} virtual void ResetDB(void) {Tdbp->ResetDB();} virtual int RowNumber(PGLOBAL g, bool b = FALSE); - virtual PSZ GetServer(void) {return (Tdbp) ? Tdbp->GetServer() : (PSZ)"?";} + virtual PCSZ GetServer(void) {return (Tdbp) ? Tdbp->GetServer() : (PSZ)"?";} // Database routines virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); @@ -101,7 +101,7 @@ class DllExport PRXCOL : public COLBLK { friend class TDBOCCUR; public: // Constructors - PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "PRX"); + PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "PRX"); PRXCOL(PRXCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp index 902137ead2e..533986e44da 100644 --- a/storage/connect/tabvct.cpp +++ b/storage/connect/tabvct.cpp @@ -174,7 +174,7 @@ bool VCTDEF::Erase(char *filename) /***********************************************************************/ int VCTDEF::MakeFnPattern(char *fpat) { - char pat[8]; + char pat[16]; #if defined(__WIN__) char drive[_MAX_DRIVE]; #else @@ -490,11 +490,7 @@ void VCTCOL::ReadBlock(PGLOBAL g) #if defined(_DEBUG) if (!Blk) { strcpy(g->Message, MSG(TO_BLK_IS_NULL)); -#if defined(USE_TRY) throw 58; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 58); -#endif // !USE_TRY } // endif #endif @@ -502,11 +498,7 @@ void VCTCOL::ReadBlock(PGLOBAL g) /* Read column block according to used access method. */ /*********************************************************************/ if (txfp->ReadBlock(g, this)) -#if defined(USE_TRY) throw 6; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 6); -#endif // !USE_TRY ColBlk = txfp->CurBlk; ColPos = -1; // Any invalid position @@ -526,11 +518,7 @@ void VCTCOL::WriteBlock(PGLOBAL g) #if defined(_DEBUG) if (!Blk) { strcpy(g->Message, MSG(BLK_IS_NULL)); -#if defined(USE_TRY) throw 56; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 56); -#endif // !USE_TRY } // endif #endif @@ -538,11 +526,7 @@ void VCTCOL::WriteBlock(PGLOBAL g) /* Write column block according to used access method. */ /*******************************************************************/ if (txfp->WriteBlock(g, this)) -#if defined(USE_TRY) throw 6; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 6); -#endif // !USE_TRY Modif = 0; } // endif Modif diff --git a/storage/connect/tabvir.cpp b/storage/connect/tabvir.cpp index dc57c9f3538..84b3dd1787b 100644 --- a/storage/connect/tabvir.cpp +++ b/storage/connect/tabvir.cpp @@ -269,7 +269,7 @@ int TDBVIR::DeleteDB(PGLOBAL g, int) /***********************************************************************/ /* VIRCOL public constructor. */ /***********************************************************************/ -VIRCOL::VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ) +VIRCOL::VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ) : COLBLK(cdp, tdbp, i) { if (cprec) { @@ -289,11 +289,7 @@ void VIRCOL::ReadColumn(PGLOBAL g) { // This should never be called sprintf(g->Message, "ReadColumn: Column %s is not virtual", Name); -#if defined(USE_TRY) throw TYPE_COLBLK; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_COLBLK); -#endif // !USE_TRY } // end of ReadColumn /* ---------------------------TDBVICL class -------------------------- */ diff --git a/storage/connect/tabvir.h b/storage/connect/tabvir.h index a53aceaeceb..e7313bbae67 100644 --- a/storage/connect/tabvir.h +++ b/storage/connect/tabvir.h @@ -76,7 +76,7 @@ class VIRCOL : public COLBLK { friend class TDBVIR; public: // Constructors - VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "VIRTUAL"); + VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "VIRTUAL"); // Implementation virtual int GetAmType(void) {return TYPE_AM_VIR;} diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp index 4871a1d66dc..335ffce5d7f 100644 --- a/storage/connect/tabwmi.cpp +++ b/storage/connect/tabwmi.cpp @@ -27,7 +27,7 @@ /***********************************************************************/ /* Initialize WMI operations. */ /***********************************************************************/ -PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname) +PWMIUT InitWMI(PGLOBAL g, PCSZ nsp, PCSZ classname) { IWbemLocator *loc; char *p; @@ -132,7 +132,7 @@ PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname) /* WMIColumns: constructs the result blocks containing the description */ /* of all the columns of a WMI table of a specified class. */ /***********************************************************************/ -PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info) +PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; diff --git a/storage/connect/tabwmi.h b/storage/connect/tabwmi.h index 6abb85453a1..7a18453374e 100644 --- a/storage/connect/tabwmi.h +++ b/storage/connect/tabwmi.h @@ -27,7 +27,7 @@ typedef struct _WMIutil { /***********************************************************************/ /* Functions used externally. */ /***********************************************************************/ -PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info); +PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info); /* -------------------------- WMI classes ---------------------------- */ diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index 386d016d082..80d4395058e 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -118,10 +118,11 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT}; static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0}; - char *fn, *op, colname[65], fmt[129], buf[512]; + char colname[65], fmt[129], buf[512]; int i, j, lvl, n = 0; int ncol = sizeof(buftyp) / sizeof(int); bool ok = true; + PCSZ fn, op; PXCL xcol, xcp, fxcp = NULL, pxcp = NULL; PLVL *lvlp, vp; PXNODE node = NULL; @@ -161,7 +162,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) if (!(tdp->Database = SetPath(g, db))) return NULL; - tdp->Tabname = tab; + tdp->Tabname = tab; tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); @@ -362,7 +363,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) skipit: if (trace) - htrc("CSVColumns: n=%d len=%d\n", n, length[0]); + htrc("XMLColumns: n=%d len=%d\n", n, length[0]); /*********************************************************************/ /* Allocate the structures used to refer to the result set. */ @@ -451,7 +452,8 @@ XMLDEF::XMLDEF(void) /***********************************************************************/ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - char *defrow, *defcol, buf[10]; + PCSZ defrow, defcol; + char buf[10]; Fn = GetStringCatInfo(g, "Filename", NULL); Encoding = GetStringCatInfo(g, "Encoding", "UTF-8"); @@ -1317,11 +1319,7 @@ void TDBXML::CloseDB(PGLOBAL g) Docp->CloseDoc(g, To_Xb); // This causes a crash in Diagnostics_area::set_error_status -//#if defined(USE_TRY) // throw TYPE_AM_XML; -//#else // !USE_TRY -// longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -//#endif // !USE_TRY } // endif DumpDoc } // endif Changed @@ -1364,8 +1362,8 @@ void TDBXML::CloseDB(PGLOBAL g) /***********************************************************************/ /* XMLCOL public constructor. */ /***********************************************************************/ -XMLCOL::XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) - : COLBLK(cdp, tdbp, i) +XMLCOL::XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) + : COLBLK(cdp, tdbp, i) { if (cprec) { Next = cprec->GetNext(); @@ -1644,11 +1642,7 @@ void XMLCOL::ReadColumn(PGLOBAL g) if (ValNode->GetType() != XML_ELEMENT_NODE && ValNode->GetType() != XML_ATTRIBUTE_NODE) { sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } // endif type // Get the Xname value from the XML file @@ -1659,11 +1653,7 @@ void XMLCOL::ReadColumn(PGLOBAL g) PushWarning(g, Tdbp); break; default: -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } // endswitch Value->SetValue_psz(Valbuf); @@ -1714,11 +1704,7 @@ void XMLCOL::WriteColumn(PGLOBAL g) /* For columns having an Xpath, the Clist must be updated. */ /*********************************************************************/ if (Tdbp->CheckRow(g, Nod || Tdbp->Colname)) -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY /*********************************************************************/ /* Null values are represented by no node. */ @@ -1790,15 +1776,7 @@ void XMLCOL::WriteColumn(PGLOBAL g) if (ColNode == NULL) { strcpy(g->Message, MSG(COL_ALLOC_ERR)); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY -#if defined(USE_TRY) - throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY -#endif // !USE_TRY } // endif ColNode } // endif ColNode @@ -1827,11 +1805,7 @@ void XMLCOL::WriteColumn(PGLOBAL g) if (strlen(p) > (unsigned)Long) { sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } else strcpy(Valbuf, p); @@ -1881,11 +1855,7 @@ void XMULCOL::ReadColumn(PGLOBAL g) if (ValNode->GetType() != XML_ELEMENT_NODE && ValNode->GetType() != XML_ATTRIBUTE_NODE) { sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } // endif type // Get the Xname value from the XML file @@ -1971,11 +1941,7 @@ void XMULCOL::WriteColumn(PGLOBAL g) /* For columns having an Xpath, the Clist must be updated. */ /*********************************************************************/ if (Tdbp->CheckRow(g, Nod)) -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY /*********************************************************************/ /* Find the column and value nodes to update or insert. */ @@ -2024,11 +1990,7 @@ void XMULCOL::WriteColumn(PGLOBAL g) if (len > 1 && !Tdbp->Xpand) { sprintf(g->Message, MSG(BAD_VAL_UPDATE), Name); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } else ValNode = Nlx->GetItem(g, Tdbp->Nsub, Vxnp); @@ -2070,11 +2032,7 @@ void XMULCOL::WriteColumn(PGLOBAL g) if (ColNode == NULL) { strcpy(g->Message, MSG(COL_ALLOC_ERR)); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } // endif ColNode } // endif ColNode @@ -2103,11 +2061,7 @@ void XMULCOL::WriteColumn(PGLOBAL g) if (strlen(p) > (unsigned)Long) { sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } else strcpy(Valbuf, p); @@ -2139,11 +2093,7 @@ void XPOSCOL::ReadColumn(PGLOBAL g) if (Tdbp->Clist == NULL) { strcpy(g->Message, MSG(MIS_TAG_LIST)); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } // endif Clist if ((ValNode = Tdbp->Clist->GetItem(g, Rank, Vxnp))) { @@ -2155,11 +2105,7 @@ void XPOSCOL::ReadColumn(PGLOBAL g) PushWarning(g, Tdbp); break; default: -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } // endswitch Value->SetValue_psz(Valbuf); @@ -2210,22 +2156,14 @@ void XPOSCOL::WriteColumn(PGLOBAL g) /* For all columns the Clist must be updated. */ /*********************************************************************/ if (Tdbp->CheckRow(g, true)) -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY /*********************************************************************/ /* Find the column and value nodes to update or insert. */ /*********************************************************************/ if (Tdbp->Clist == NULL) { strcpy(g->Message, MSG(MIS_TAG_LIST)); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } // endif Clist n = Tdbp->Clist->GetLength(); @@ -2250,11 +2188,7 @@ void XPOSCOL::WriteColumn(PGLOBAL g) if (strlen(p) > (unsigned)Long) { sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long); -#if defined(USE_TRY) throw TYPE_AM_XML; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_AM_XML); -#endif // !USE_TRY } else strcpy(Valbuf, p); diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h index 65b353072cb..6b18eb645f0 100644 --- a/storage/connect/tabxml.h +++ b/storage/connect/tabxml.h @@ -31,7 +31,7 @@ class DllExport XMLDEF : public TABDEF { /* Logical table description */ protected: // Members - char *Fn; /* Path/Name of corresponding file */ + PCSZ Fn; /* Path/Name of corresponding file */ char *Encoding; /* New XML table file encoding */ char *Tabname; /* Name of Table node */ char *Rowname; /* Name of first level nodes */ @@ -42,7 +42,7 @@ class DllExport XMLDEF : public TABDEF { /* Logical table description */ char *DefNs; /* Dummy name of default namespace */ char *Attrib; /* Table node attributes */ char *Hdattr; /* Header node attributes */ - char *Entry; /* Zip entry name or pattern */ + PCSZ Entry; /* Zip entry name or pattern */ int Coltype; /* Default column type */ int Limit; /* Limit of multiple values */ int Header; /* n first rows are header rows */ @@ -74,7 +74,7 @@ class DllExport TDBXML : public TDBASE { virtual PTDB Clone(PTABS t); virtual int GetRecpos(void); virtual int GetProgCur(void) {return N;} - virtual PSZ GetFile(PGLOBAL g) {return Xfile;} + virtual PCSZ GetFile(PGLOBAL g) {return Xfile;} virtual void SetFile(PGLOBAL g, PSZ fn) {Xfile = fn;} virtual void ResetDB(void) {N = 0;} virtual void ResetSize(void) {MaxSize = -1;} @@ -127,7 +127,7 @@ class DllExport TDBXML : public TDBASE { bool Void; // True if the file does not exist bool Zipped; // True if Zipped XML file(s) bool Mulentries; // True if multiple entries in zip file - char *Xfile; // The XML file + PCSZ Xfile; // The XML file char *Enc; // New XML table file encoding char *Tabname; // Name of Table node char *Rowname; // Name of first level nodes @@ -138,7 +138,7 @@ class DllExport TDBXML : public TDBASE { char *DefNs; // Dummy name of default namespace char *Attrib; // Table node attribut(s) char *Hdattr; // Header node attribut(s) - char *Entry; // Zip entry name or pattern + PCSZ Entry; // Zip entry name or pattern int Coltype; // Default column type int Limit; // Limit of multiple values int Header; // n first rows are header rows @@ -155,7 +155,7 @@ class DllExport TDBXML : public TDBASE { class XMLCOL : public COLBLK { public: // Constructors - XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "XML"); + XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "XML"); XMLCOL(XMLCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation diff --git a/storage/connect/tabzip.cpp b/storage/connect/tabzip.cpp index b91059a3843..c026744dba8 100644 --- a/storage/connect/tabzip.cpp +++ b/storage/connect/tabzip.cpp @@ -195,8 +195,8 @@ void TDBZIP::CloseDB(PGLOBAL g) /***********************************************************************/ /* ZIPCOL public constructor. */ /***********************************************************************/ -ZIPCOL::ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) - : COLBLK(cdp, tdbp, i) +ZIPCOL::ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) + : COLBLK(cdp, tdbp, i) { if (cprec) { Next = cprec->GetNext(); diff --git a/storage/connect/tabzip.h b/storage/connect/tabzip.h index dcec3475371..32b15281f81 100644 --- a/storage/connect/tabzip.h +++ b/storage/connect/tabzip.h @@ -34,7 +34,7 @@ public: protected: // Members - PSZ target; // The inside file to query + PCSZ target; // The inside file to query }; // end of ZIPDEF /***********************************************************************/ @@ -68,7 +68,7 @@ protected: // Members unzFile zipfile; // The ZIP container file - PSZ zfn; // The ZIP file name + PCSZ zfn; // The ZIP file name //PSZ target; unz_file_info64 finfo; // The current file info char fn[FILENAME_MAX]; // The current file name @@ -82,7 +82,7 @@ class DllExport ZIPCOL : public COLBLK { friend class TDBZIP; public: // Constructors - ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ZIP"); + ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "ZIP"); // Implementation virtual int GetAmType(void) { return TYPE_AM_ZIP; } diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc index 34d192361a5..ca3557666a4 100644 --- a/storage/connect/user_connect.cc +++ b/storage/connect/user_connect.cc @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /** @file user_connect.cc diff --git a/storage/connect/user_connect.h b/storage/connect/user_connect.h index 7f37973f378..a883eb85934 100644 --- a/storage/connect/user_connect.h +++ b/storage/connect/user_connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /** @file user_connect.h diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp index 4331962e0ad..5b98f3eb425 100644 --- a/storage/connect/valblk.cpp +++ b/storage/connect/valblk.cpp @@ -1,5 +1,5 @@ /************ Valblk C++ Functions Source Code File (.CPP) *************/ -/* Name: VALBLK.CPP Version 2.2 */ +/* Name: VALBLK.CPP Version 2.3 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2005-2017 */ /* */ @@ -138,18 +138,14 @@ PSZ VALBLK::GetCharValue(int) assert(g); sprintf(g->Message, MSG(NO_CHAR_FROM), Type); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY return NULL; } // end of GetCharValue /***********************************************************************/ /* Set format so formatted dates can be converted on input. */ /***********************************************************************/ -bool VALBLK::SetFormat(PGLOBAL g, PSZ, int, int) +bool VALBLK::SetFormat(PGLOBAL g, PCSZ, int, int) { sprintf(g->Message, MSG(NO_DATE_FMT), Type); return true; @@ -210,11 +206,7 @@ void VALBLK::ChkIndx(int n) if (n < 0 || n >= Nval) { PGLOBAL& g = Global; strcpy(g->Message, MSG(BAD_VALBLK_INDX)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif n } // end of ChkIndx @@ -224,11 +216,7 @@ void VALBLK::ChkTyp(PVAL v) if (Check && (Type != v->GetType() || Unsigned != v->IsUnsigned())) { PGLOBAL& g = Global; strcpy(g->Message, MSG(VALTYPE_NOMATCH)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif Type } // end of ChkTyp @@ -238,11 +226,7 @@ void VALBLK::ChkTyp(PVBLK vb) if (Check && (Type != vb->GetType() || Unsigned != vb->IsUnsigned())) { PGLOBAL& g = Global; strcpy(g->Message, MSG(VALTYPE_NOMATCH)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif Type } // end of ChkTyp @@ -351,18 +335,14 @@ uchar TYPBLK::GetTypedValue(PVAL valp) /* Set one value in a block from a zero terminated string. */ /***********************************************************************/ template -void TYPBLK::SetValue(PSZ p, int n) +void TYPBLK::SetValue(PCSZ p, int n) { ChkIndx(n); if (Check) { PGLOBAL& g = Global; strcpy(g->Message, MSG(BAD_SET_STRING)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif Check bool minus; @@ -405,18 +385,14 @@ template <> ulonglong TYPBLK::MaxVal(void) {return ULONGLONG_MAX;} template <> -void TYPBLK::SetValue(PSZ p, int n) +void TYPBLK::SetValue(PCSZ p, int n) { ChkIndx(n); if (Check) { PGLOBAL& g = Global; strcpy(g->Message, MSG(BAD_SET_STRING)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif Check Typp[n] = atof(p); @@ -427,7 +403,7 @@ void TYPBLK::SetValue(PSZ p, int n) /* Set one value in a block from an array of characters. */ /***********************************************************************/ template -void TYPBLK::SetValue(char *sp, uint len, int n) +void TYPBLK::SetValue(PCSZ sp, uint len, int n) { PGLOBAL& g = Global; PSZ spz = (PSZ)PlugSubAlloc(g, NULL, 0); // Temporary @@ -802,7 +778,7 @@ void CHRBLK::SetValue(PVAL valp, int n) /***********************************************************************/ /* Set one value in a block from a zero terminated string. */ /***********************************************************************/ -void CHRBLK::SetValue(PSZ sp, int n) +void CHRBLK::SetValue(PCSZ sp, int n) { uint len = (sp) ? strlen(sp) : 0; SetValue(sp, len, n); @@ -811,7 +787,7 @@ void CHRBLK::SetValue(PSZ sp, int n) /***********************************************************************/ /* Set one value in a block from an array of characters. */ /***********************************************************************/ -void CHRBLK::SetValue(char *sp, uint len, int n) +void CHRBLK::SetValue(const char *sp, uint len, int n) { char *p = Chrp + n * Long; @@ -819,11 +795,7 @@ void CHRBLK::SetValue(char *sp, uint len, int n) if (Check && (signed)len > Long) { PGLOBAL& g = Global; strcpy(g->Message, MSG(SET_STR_TRUNC)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif Check #endif // _DEBUG @@ -851,11 +823,7 @@ void CHRBLK::SetValue(PVBLK pv, int n1, int n2) if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) { PGLOBAL& g = Global; strcpy(g->Message, MSG(BLKTYPLEN_MISM)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif Type if (!(b = pv->IsNull(n2))) @@ -906,11 +874,7 @@ void CHRBLK::SetValues(PVBLK pv, int k, int n) if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) { PGLOBAL& g = Global; strcpy(g->Message, MSG(BLKTYPLEN_MISM)); -#if defined(USE_TRY) throw Type; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY } // endif Type #endif // _DEBUG char *p = ((CHRBLK*)pv)->Chrp; @@ -1188,7 +1152,7 @@ void STRBLK::SetValue(PVAL valp, int n) /***********************************************************************/ /* Set one value in a block from a zero terminated string. */ /***********************************************************************/ -void STRBLK::SetValue(PSZ p, int n) +void STRBLK::SetValue(PCSZ p, int n) { if (p) { if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1])) @@ -1204,7 +1168,7 @@ void STRBLK::SetValue(PSZ p, int n) /***********************************************************************/ /* Set one value in a block from an array of characters. */ /***********************************************************************/ -void STRBLK::SetValue(char *sp, uint len, int n) +void STRBLK::SetValue(const char *sp, uint len, int n) { PSZ p; @@ -1352,7 +1316,7 @@ DATBLK::DATBLK(void *mp, int nval) : TYPBLK(mp, nval, TYPE_INT) /***********************************************************************/ /* Set format so formatted dates can be converted on input. */ /***********************************************************************/ -bool DATBLK::SetFormat(PGLOBAL g, PSZ fmt, int len, int year) +bool DATBLK::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year) { if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, false, fmt))) return true; @@ -1379,7 +1343,7 @@ char *DATBLK::GetCharString(char *p, int n) /***********************************************************************/ /* Set one value in a block from a char string. */ /***********************************************************************/ -void DATBLK::SetValue(PSZ p, int n) +void DATBLK::SetValue(PCSZ p, int n) { if (Dvalp) { // Decode the string according to format diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h index c3cad79b234..38a73424985 100644 --- a/storage/connect/valblk.h +++ b/storage/connect/valblk.h @@ -91,7 +91,7 @@ class VALBLK : public BLOCK { virtual char *GetCharString(char *p, int n) = 0; virtual void ReAlloc(void *mp, int n) {Blkp = mp; Nval = n;} virtual void Reset(int n) = 0; - virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0); + virtual bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0); virtual void SetPrec(int p) {} virtual bool IsCi(void) {return false;} @@ -105,8 +105,8 @@ class VALBLK : public BLOCK { virtual void SetValue(double, int) {assert(false);} virtual void SetValue(char, int) {assert(false);} virtual void SetValue(uchar, int) {assert(false);} - virtual void SetValue(PSZ, int) {assert(false);} - virtual void SetValue(char *, uint, int) {assert(false);} + virtual void SetValue(PCSZ, int) {assert(false);} + virtual void SetValue(const char *, uint, int) {assert(false);} virtual void SetValue(PVAL valp, int n) = 0; virtual void SetValue(PVBLK pv, int n1, int n2) = 0; virtual void SetMin(PVAL valp, int n) = 0; @@ -165,8 +165,8 @@ class TYPBLK : public VALBLK { // Methods using VALBLK::SetValue; - virtual void SetValue(PSZ sp, int n); - virtual void SetValue(char *sp, uint len, int n); + virtual void SetValue(PCSZ sp, int n); + virtual void SetValue(const char *sp, uint len, int n); virtual void SetValue(short sval, int n) {Typp[n] = (TYPE)sval; SetNull(n, false);} virtual void SetValue(ushort sval, int n) @@ -236,8 +236,8 @@ class CHRBLK : public VALBLK { // Methods using VALBLK::SetValue; - virtual void SetValue(PSZ sp, int n); - virtual void SetValue(char *sp, uint len, int n); + virtual void SetValue(PCSZ sp, int n); + virtual void SetValue(const char *sp, uint len, int n); virtual void SetValue(PVAL valp, int n); virtual void SetValue(PVBLK pv, int n1, int n2); virtual void SetMin(PVAL valp, int n); @@ -290,8 +290,8 @@ class STRBLK : public VALBLK { // Methods using VALBLK::SetValue; - virtual void SetValue(PSZ sp, int n); - virtual void SetValue(char *sp, uint len, int n); + virtual void SetValue(PCSZ sp, int n); + virtual void SetValue(const char *sp, uint len, int n); virtual void SetValue(PVAL valp, int n); virtual void SetValue(PVBLK pv, int n1, int n2); virtual void SetMin(PVAL valp, int n); @@ -322,12 +322,12 @@ class DATBLK : public TYPBLK { DATBLK(void *mp, int size); // Implementation - virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0); + virtual bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0); virtual char *GetCharString(char *p, int n); // Methods using TYPBLK::SetValue; - virtual void SetValue(PSZ sp, int n); + virtual void SetValue(PCSZ sp, int n); protected: // Members @@ -352,7 +352,7 @@ class PTRBLK : public STRBLK { // Methods using STRBLK::SetValue; using STRBLK::CompVal; - virtual void SetValue(PSZ p, int n) {Strp[n] = p;} + virtual void SetValue(PCSZ p, int n) {Strp[n] = (char*)p;} virtual int CompVal(int i1, int i2); protected: diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index fec38217b0b..1e215c4df69 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -1,5 +1,5 @@ /************* Value C++ Functions Source Code File (.CPP) *************/ -/* Name: VALUE.CPP Version 2.7 */ +/* Name: VALUE.CPP Version 2.8 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2001-2017 */ /* */ @@ -57,17 +57,10 @@ /* Check macro's. */ /***********************************************************************/ #if defined(_DEBUG) -#if defined(USE_TRY) #define CheckType(V) if (Type != V->GetType()) { \ PGLOBAL& g = Global; \ strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \ throw Type; -#else // !USE_TRY -#define CheckType(V) if (Type != V->GetType()) { \ - PGLOBAL& g = Global; \ - strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \ - longjmp(g->jumper[g->jump_level], Type); -#endif // !USE_TRY #else #define CheckType(V) #endif @@ -101,12 +94,12 @@ PSZ strlwr(PSZ s); /* OUT minus: Set to true if the number is negative */ /* Returned val: The resulting number */ /***********************************************************************/ -ulonglong CharToNumber(char *p, int n, ulonglong maxval, +ulonglong CharToNumber(const char *p, int n, ulonglong maxval, bool un, bool *minus, bool *rc) { - char *p2; - uchar c; - ulonglong val; + const char *p2; + uchar c; + ulonglong val; if (minus) *minus = false; if (rc) *rc = false; @@ -145,9 +138,9 @@ ulonglong CharToNumber(char *p, int n, ulonglong maxval, /***********************************************************************/ /* GetTypeName: returns the PlugDB internal type name. */ /***********************************************************************/ -PSZ GetTypeName(int type) +PCSZ GetTypeName(int type) { - PSZ name; + PCSZ name; switch (type) { case TYPE_STRING: name = "CHAR"; break; @@ -191,9 +184,9 @@ int GetTypeSize(int type, int len) /***********************************************************************/ /* GetFormatType: returns the FORMAT character(s) according to type. */ /***********************************************************************/ -char *GetFormatType(int type) +const char *GetFormatType(int type) { - char *c = "X"; + const char *c = "X"; switch (type) { case TYPE_STRING: c = "C"; break; @@ -377,7 +370,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec) /* Allocate a variable Value according to type, length and precision. */ /***********************************************************************/ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, - bool uns, PSZ fmt) + bool uns, PCSZ fmt) { PVAL valp; @@ -565,6 +558,38 @@ bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL) return true; } // end of Compute +/***********************************************************************/ +/* Make file output of an object value. */ +/***********************************************************************/ +void VALUE::Print(PGLOBAL g, FILE *f, uint n) +{ + char m[64], buf[64]; + + memset(m, ' ', n); /* Make margin string */ + m[n] = '\0'; + + if (Null) + fprintf(f, "%s\n", m); + else + fprintf(f, strcat(strcat(GetCharString(buf), "\n"), m)); + +} /* end of Print */ + +/***********************************************************************/ +/* Make string output of an object value. */ +/***********************************************************************/ +void VALUE::Print(PGLOBAL g, char *ps, uint z) +{ + char *p, buf[64]; + + if (Null) + p = strcpy(buf, ""); + else + p = GetCharString(buf); + + strncpy(ps, p, z); +} // end of Print + /* -------------------------- Class TYPVAL ---------------------------- */ /***********************************************************************/ @@ -689,7 +714,7 @@ uchar TYPVAL::GetTypedValue(PVAL valp) /* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/ /***********************************************************************/ template -bool TYPVAL::SetValue_char(char *p, int n) +bool TYPVAL::SetValue_char(const char *p, int n) { bool rc, minus; ulonglong maxval = MaxVal(); @@ -711,7 +736,7 @@ bool TYPVAL::SetValue_char(char *p, int n) } // end of SetValue template <> -bool TYPVAL::SetValue_char(char *p, int n) +bool TYPVAL::SetValue_char(const char *p, int n) { if (p && n > 0) { char buf[64]; @@ -739,7 +764,7 @@ bool TYPVAL::SetValue_char(char *p, int n) /* TYPVAL SetValue: fill a typed value from a string. */ /***********************************************************************/ template -void TYPVAL::SetValue_psz(PSZ s) +void TYPVAL::SetValue_psz(PCSZ s) { if (s) { SetValue_char(s, (int)strlen(s)); @@ -1026,19 +1051,11 @@ TYPE TYPVAL::SafeAdd(TYPE n1, TYPE n2) if ((n2 > 0) && (n < n1)) { // Overflow strcpy(g->Message, MSG(FIX_OVFLW_ADD)); -#if defined(USE_TRY) throw 138; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 138); -#endif // !USE_TRY } else if ((n2 < 0) && (n > n1)) { // Underflow strcpy(g->Message, MSG(FIX_UNFLW_ADD)); -#if defined(USE_TRY) throw 138; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 138); -#endif // !USE_TRY } // endif's n2 return n; @@ -1062,19 +1079,11 @@ TYPE TYPVAL::SafeMult(TYPE n1, TYPE n2) if (n > MinMaxVal(true)) { // Overflow strcpy(g->Message, MSG(FIX_OVFLW_TIMES)); -#if defined(USE_TRY) throw 138; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 138); -#endif // !USE_TRY } else if (n < MinMaxVal(false)) { // Underflow strcpy(g->Message, MSG(FIX_UNFLW_TIMES)); -#if defined(USE_TRY) throw 138; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 138); -#endif // !USE_TRY } // endif's n2 return (TYPE)n; @@ -1193,7 +1202,7 @@ bool TYPVAL::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op) /* This function assumes that the format matches the value type. */ /***********************************************************************/ template -bool TYPVAL::FormatValue(PVAL vp, char *fmt) +bool TYPVAL::FormatValue(PVAL vp, PCSZ fmt) { char *buf = (char*)vp->GetTo_Val(); // Should be big enough int n = sprintf(buf, fmt, Tval); @@ -1215,37 +1224,6 @@ bool TYPVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt) return false; } // end of SetConstFormat -/***********************************************************************/ -/* Make file output of a typed object. */ -/***********************************************************************/ -template -void TYPVAL::Print(PGLOBAL g, FILE *f, uint n) - { - char m[64], buf[12]; - - memset(m, ' ', n); /* Make margin string */ - m[n] = '\0'; - - if (Null) - fprintf(f, "%s\n", m); - else - fprintf(f, strcat(strcat(strcpy(buf, "%s"), Fmt), "\n"), m, Tval); - - } /* end of Print */ - -/***********************************************************************/ -/* Make string output of a int object. */ -/***********************************************************************/ -template -void TYPVAL::Print(PGLOBAL g, char *ps, uint z) - { - if (Null) - strcpy(ps, ""); - else - sprintf(ps, Fmt, Tval); - - } /* end of Print */ - /* -------------------------- Class STRING --------------------------- */ /***********************************************************************/ @@ -1384,25 +1362,25 @@ bool TYPVAL::SetValue_pval(PVAL valp, bool chktype) /***********************************************************************/ /* STRING SetValue: fill string with chars extracted from a line. */ /***********************************************************************/ -bool TYPVAL::SetValue_char(char *p, int n) +bool TYPVAL::SetValue_char(const char *cp, int n) { bool rc = false; - if (!p || n == 0) { + if (!cp || n == 0) { Reset(); Null = Nullable; - } else if (p != Strp) { + } else if (cp != Strp) { + const char *p = cp + n - 1; + + for (p; p >= cp; p--, n--) + if (*p && *p != ' ') + break; + rc = n > Len; if ((n = MY_MIN(n, Len))) { - strncpy(Strp, p, n); - -// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ; - for (p = Strp + n - 1; p >= Strp; p--) - if (*p && *p != ' ') - break; - - *(++p) = '\0'; + strncpy(Strp, cp, n); + Strp[n] = '\0'; if (trace > 1) htrc(" Setting string to: '%s'\n", Strp); @@ -1419,7 +1397,7 @@ bool TYPVAL::SetValue_char(char *p, int n) /***********************************************************************/ /* STRING SetValue: fill string with another string. */ /***********************************************************************/ -void TYPVAL::SetValue_psz(PSZ s) +void TYPVAL::SetValue_psz(PCSZ s) { if (!s) { Reset(); @@ -1455,15 +1433,7 @@ void TYPVAL::SetValue(int n) if (k > Len) { sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); -#if defined(USE_TRY) throw 138; -#else // !USE_TRY -#if defined(USE_TRY) - throw 138; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 138); -#endif // !USE_TRY -#endif // !USE_TRY } else SetValue_psz(buf); @@ -1517,11 +1487,7 @@ void TYPVAL::SetValue(longlong n) if (k > Len) { sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); -#if defined(USE_TRY) throw 138; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 138); -#endif // !USE_TRY } else SetValue_psz(buf); @@ -1564,11 +1530,7 @@ void TYPVAL::SetValue(double f) if (k > Len) { sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); -#if defined(USE_TRY) throw 138; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 138); -#endif // !USE_TRY } else SetValue_psz(buf); @@ -1598,7 +1560,7 @@ void TYPVAL::SetValue(uchar c) /***********************************************************************/ void TYPVAL::SetBinValue(void *p) { - SetValue_char((char *)p, Len); + SetValue_char((const char *)p, Len); } // end of SetBinValue /***********************************************************************/ @@ -1728,7 +1690,7 @@ bool TYPVAL::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) /* constructed from its own value formated using the fmt format. */ /* This function assumes that the format matches the value type. */ /***********************************************************************/ -bool TYPVAL::FormatValue(PVAL vp, char *fmt) +bool TYPVAL::FormatValue(PVAL vp, PCSZ fmt) { char *buf = (char*)vp->GetTo_Val(); // Should be big enough int n = sprintf(buf, fmt, Strp); @@ -1747,6 +1709,18 @@ bool TYPVAL::SetConstFormat(PGLOBAL, FORMAT& fmt) return false; } // end of SetConstFormat +/***********************************************************************/ +/* Make string output of an object value. */ +/***********************************************************************/ +void TYPVAL::Print(PGLOBAL g, char *ps, uint z) +{ + if (Null) + strncpy(ps, "null", z); + else + strcat(strncat(strncpy(ps, "\"", z), Strp, z-2), "\""); + +} // end of Print + /* -------------------------- Class DECIMAL -------------------------- */ /***********************************************************************/ @@ -1836,102 +1810,6 @@ bool DECVAL::GetBinValue(void *buf, int buflen, bool go) return false; } // end of GetBinValue -#if 0 -/***********************************************************************/ -/* DECIMAL SetValue: copy the value of another Value object. */ -/***********************************************************************/ -bool DECVAL::SetValue_pval(PVAL valp, bool chktype) - { - if (chktype && (valp->GetType() != Type || valp->GetSize() > Len)) - return true; - - char buf[64]; - - if (!(Null = valp->IsNull() && Nullable)) - strncpy(Strp, valp->GetCharString(buf), Len); - else - Reset(); - - return false; - } // end of SetValue_pval - -/***********************************************************************/ -/* DECIMAL SetValue: fill string with chars extracted from a line. */ -/***********************************************************************/ -bool DECVAL::SetValue_char(char *p, int n) - { - bool rc; - - if (p && n > 0) { - rc = n > Len; - - if ((n = MY_MIN(n, Len))) { - strncpy(Strp, p, n); - -// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ; - for (p = Strp + n - 1; p >= Strp; p--) - if (*p && *p != ' ') - break; - - *(++p) = '\0'; - - if (trace > 1) - htrc(" Setting string to: '%s'\n", Strp); - - } else - Reset(); - - Null = false; - } else { - rc = false; - Reset(); - Null = Nullable; - } // endif p - - return rc; - } // end of SetValue_char - -/***********************************************************************/ -/* DECIMAL SetValue: fill string with another string. */ -/***********************************************************************/ -void DECVAL::SetValue_psz(PSZ s) - { - if (s) { - strncpy(Strp, s, Len); - Null = false; - } else { - Reset(); - Null = Nullable; - } // endif s - - } // end of SetValue_psz - -/***********************************************************************/ -/* DECIMAL SetValue: fill string with a string extracted from a block.*/ -/***********************************************************************/ -void DECVAL::SetValue_pvblk(PVBLK blk, int n) - { - // STRBLK's can return a NULL pointer - SetValue_psz(blk->GetCharValue(n)); - } // end of SetValue_pvblk - -/***********************************************************************/ -/* DECIMAL SetBinValue: fill string with chars extracted from a line. */ -/***********************************************************************/ -void DECVAL::SetBinValue(void *p) - { - SetValue_char((char *)p, Len); - } // end of SetBinValue - -/***********************************************************************/ -/* DECIMAL GetCharString: get string representation of a char value. */ -/***********************************************************************/ -char *DECVAL::GetCharString(char *p) - { - return Strp; - } // end of GetCharString -#endif // 0 - /***********************************************************************/ /* DECIMAL compare value with another Value. */ /***********************************************************************/ @@ -1966,32 +1844,6 @@ int DECVAL::CompareValue(PVAL vp) return (f > n) ? 1 : (f < n) ? (-1) : 0; } // end of CompareValue -#if 0 -/***********************************************************************/ -/* FormatValue: This function set vp (a STRING value) to the string */ -/* constructed from its own value formated using the fmt format. */ -/* This function assumes that the format matches the value type. */ -/***********************************************************************/ -bool DECVAL::FormatValue(PVAL vp, char *fmt) - { - char *buf = (char*)vp->GetTo_Val(); // Should be big enough - int n = sprintf(buf, fmt, Strp); - - return (n > vp->GetValLen()); - } // end of FormatValue - -/***********************************************************************/ -/* DECIMAL SetFormat function (used to set SELECT output format). */ -/***********************************************************************/ -bool DECVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt) - { - fmt.Type[0] = 'C'; - fmt.Length = Len; - fmt.Prec = 0; - return false; - } // end of SetConstFormat -#endif // 0 - /* -------------------------- Class BINVAL --------------------------- */ /***********************************************************************/ @@ -2149,7 +2001,7 @@ bool BINVAL::SetValue_pval(PVAL valp, bool chktype) /***********************************************************************/ /* BINVAL SetValue: fill value with chars extracted from a line. */ /***********************************************************************/ -bool BINVAL::SetValue_char(char *p, int n) +bool BINVAL::SetValue_char(const char *p, int n) { bool rc; @@ -2170,7 +2022,7 @@ bool BINVAL::SetValue_char(char *p, int n) /***********************************************************************/ /* BINVAL SetValue: fill value with another string. */ /***********************************************************************/ -void BINVAL::SetValue_psz(PSZ s) +void BINVAL::SetValue_psz(PCSZ s) { if (s) { Len = MY_MIN(Clen, (signed)strlen(s)); @@ -2396,7 +2248,7 @@ bool BINVAL::IsEqual(PVAL vp, bool chktype) /* constructed from its own value formated using the fmt format. */ /* This function assumes that the format matches the value type. */ /***********************************************************************/ -bool BINVAL::FormatValue(PVAL vp, char *fmt) +bool BINVAL::FormatValue(PVAL vp, PCSZ fmt) { char *buf = (char*)vp->GetTo_Val(); // Should be big enough int n = sprintf(buf, fmt, Len, Binp); @@ -2420,7 +2272,7 @@ bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt) /***********************************************************************/ /* DTVAL public constructor for new void values. */ /***********************************************************************/ -DTVAL::DTVAL(PGLOBAL g, int n, int prec, PSZ fmt) +DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt) : TYPVAL((int)0, TYPE_DATE) { if (!fmt) { @@ -2449,7 +2301,7 @@ DTVAL::DTVAL(int n) : TYPVAL(n, TYPE_DATE) /***********************************************************************/ /* Set format so formatted dates can be converted on input/output. */ /***********************************************************************/ -bool DTVAL::SetFormat(PGLOBAL g, PSZ fmt, int len, int year) +bool DTVAL::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year) { Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0); Sdate = (char*)PlugSubAlloc(g, NULL, len + 1); @@ -2707,7 +2559,11 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype) ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval); MakeDate(NULL, dval, ndv); - } else + } else if (valp->GetType() == TYPE_BIGINT && + !(valp->GetBigintValue() % 1000)) { + // Assuming that this timestamp is in milliseconds + Tval = valp->GetBigintValue() / 1000; + } else Tval = valp->GetIntValue(); } else @@ -2721,14 +2577,14 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype) /***********************************************************************/ /* SetValue: convert chars extracted from a line to date value. */ /***********************************************************************/ -bool DTVAL::SetValue_char(char *p, int n) +bool DTVAL::SetValue_char(const char *p, int n) { bool rc= 0; if (Pdtp) { - char *p2; - int ndv; - int dval[6]; + const char *p2; + int ndv; + int dval[6]; if (n > 0) { // Trim trailing blanks @@ -2760,11 +2616,11 @@ bool DTVAL::SetValue_char(char *p, int n) /***********************************************************************/ /* SetValue: convert a char string to date value. */ /***********************************************************************/ -void DTVAL::SetValue_psz(PSZ p) +void DTVAL::SetValue_psz(PCSZ p) { if (Pdtp) { - int ndv; - int dval[6]; + int ndv; + int dval[6]; strncpy(Sdate, p, Len); Sdate[Len] = '\0'; @@ -2854,8 +2710,10 @@ char *DTVAL::ShowValue(char *buf, int len) strncat(p, "Error", m); } // endif n - } else - p = ""; // DEFAULT VALUE ??? + } else { + p = buf; + *p = '\0'; // DEFAULT VALUE ??? + } // endif Null return p; } else @@ -2920,7 +2778,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval) /* constructed from its own value formated using the fmt format. */ /* This function assumes that the format matches the value type. */ /***********************************************************************/ -bool DTVAL::FormatValue(PVAL vp, char *fmt) +bool DTVAL::FormatValue(PVAL vp, PCSZ fmt) { char *buf = (char*)vp->GetTo_Val(); // Should be big enough struct tm tm, *ptm = GetGmTime(&tm); diff --git a/storage/connect/value.h b/storage/connect/value.h index 14a568c3549..cf6682f56f2 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -1,7 +1,7 @@ /**************** Value H Declares Source Code File (.H) ***************/ -/* Name: VALUE.H Version 2.2 */ +/* Name: VALUE.H Version 2.3 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2001-2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */ /* */ /* This file contains the VALUE and derived classes declares. */ /***********************************************************************/ @@ -40,14 +40,14 @@ typedef struct _datpar *PDTP; // For DTVAL /* Utilities used to test types and to allocated values. */ /***********************************************************************/ // Exported functions -DllExport PSZ GetTypeName(int); +DllExport PCSZ GetTypeName(int); DllExport int GetTypeSize(int, int); #ifdef ODBC_SUPPORT /* This function is exported for use in OEM table type DLLs */ DllExport int TranslateSQLType(int stp, int prec, int& len, char& v, bool& w); #endif -DllExport char *GetFormatType(int); +DllExport const char *GetFormatType(int); DllExport int GetFormatType(char); DllExport bool IsTypeChar(int type); DllExport bool IsTypeNum(int type); @@ -55,8 +55,8 @@ DllExport int ConvertType(int, int, CONV, bool match = false); DllExport PVAL AllocateValue(PGLOBAL, void *, short, short = 2); DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0); DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0, - bool uns = false, PSZ fmt = NULL); -DllExport ulonglong CharToNumber(char *, int, ulonglong, bool, + bool uns = false, PCSZ fmt = NULL); +DllExport ulonglong CharToNumber(PCSZ, int, ulonglong, bool, bool *minus = NULL, bool *rc = NULL); DllExport BYTE OpBmp(PGLOBAL g, OPVAL opc); @@ -100,8 +100,8 @@ class DllExport VALUE : public BLOCK { // Methods virtual bool SetValue_pval(PVAL valp, bool chktype = false) = 0; - virtual bool SetValue_char(char *p, int n) = 0; - virtual void SetValue_psz(PSZ s) = 0; + virtual bool SetValue_char(const char *p, int n) = 0; + virtual void SetValue_psz(PCSZ s) = 0; virtual void SetValue_bool(bool) {assert(FALSE);} virtual int CompareValue(PVAL vp) = 0; virtual BYTE TestValue(PVAL vp); @@ -121,7 +121,9 @@ class DllExport VALUE : public BLOCK { virtual char *GetCharString(char *p) = 0; virtual bool IsEqual(PVAL vp, bool chktype) = 0; virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); - virtual bool FormatValue(PVAL vp, char *fmt) = 0; + virtual bool FormatValue(PVAL vp, PCSZ fmt) = 0; + virtual void Print(PGLOBAL g, FILE *, uint); + virtual void Print(PGLOBAL g, char *ps, uint z); /** Set value from a non-aligned in-memory value in the machine byte order. @@ -211,8 +213,8 @@ class DllExport TYPVAL : public VALUE { // Methods virtual bool SetValue_pval(PVAL valp, bool chktype); - virtual bool SetValue_char(char *p, int n); - virtual void SetValue_psz(PSZ s); + virtual bool SetValue_char(const char *p, int n); + virtual void SetValue_psz(PCSZ s); virtual void SetValue_bool(bool b) {Tval = (b) ? 1 : 0;} virtual int CompareValue(PVAL vp); virtual void SetValue(char c) {Tval = (TYPE)c; Null = false;} @@ -232,9 +234,7 @@ class DllExport TYPVAL : public VALUE { virtual bool IsEqual(PVAL vp, bool chktype); virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); virtual bool SetConstFormat(PGLOBAL, FORMAT&); - virtual bool FormatValue(PVAL vp, char *fmt); - virtual void Print(PGLOBAL g, FILE *, uint); - virtual void Print(PGLOBAL g, char *, uint); + virtual bool FormatValue(PVAL vp, PCSZ fmt); protected: static TYPE MinMaxVal(bool b); @@ -287,8 +287,8 @@ class DllExport TYPVAL: public VALUE { // Methods virtual bool SetValue_pval(PVAL valp, bool chktype); - virtual bool SetValue_char(char *p, int n); - virtual void SetValue_psz(PSZ s); + virtual bool SetValue_char(const char *p, int n); + virtual void SetValue_psz(PCSZ s); virtual void SetValue_pvblk(PVBLK blk, int n); virtual void SetValue(char c); virtual void SetValue(uchar c); @@ -306,8 +306,9 @@ class DllExport TYPVAL: public VALUE { virtual char *GetCharString(char *p); virtual bool IsEqual(PVAL vp, bool chktype); virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); - virtual bool FormatValue(PVAL vp, char *fmt); + virtual bool FormatValue(PVAL vp, PCSZ fmt); virtual bool SetConstFormat(PGLOBAL, FORMAT&); + virtual void Print(PGLOBAL g, char *ps, uint z); protected: // Members @@ -371,8 +372,8 @@ class DllExport BINVAL: public VALUE { // Methods virtual bool SetValue_pval(PVAL valp, bool chktype); - virtual bool SetValue_char(char *p, int n); - virtual void SetValue_psz(PSZ s); + virtual bool SetValue_char(const char *p, int n); + virtual void SetValue_psz(PCSZ s); virtual void SetValue_pvblk(PVBLK blk, int n); virtual void SetValue(char c); virtual void SetValue(uchar c); @@ -389,7 +390,7 @@ class DllExport BINVAL: public VALUE { virtual char *ShowValue(char *buf, int); virtual char *GetCharString(char *p); virtual bool IsEqual(PVAL vp, bool chktype); - virtual bool FormatValue(PVAL vp, char *fmt); + virtual bool FormatValue(PVAL vp, PCSZ fmt); virtual bool SetConstFormat(PGLOBAL, FORMAT&); protected: @@ -405,18 +406,18 @@ class DllExport BINVAL: public VALUE { class DllExport DTVAL : public TYPVAL { public: // Constructors - DTVAL(PGLOBAL g, int n, int p, PSZ fmt); + DTVAL(PGLOBAL g, int n, int p, PCSZ fmt); DTVAL(int n); // Implementation virtual bool SetValue_pval(PVAL valp, bool chktype); - virtual bool SetValue_char(char *p, int n); - virtual void SetValue_psz(PSZ s); + virtual bool SetValue_char(const char *p, int n); + virtual void SetValue_psz(PCSZ s); virtual void SetValue_pvblk(PVBLK blk, int n); virtual char *GetCharString(char *p); virtual char *ShowValue(char *buf, int); - virtual bool FormatValue(PVAL vp, char *fmt); - bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0); + virtual bool FormatValue(PVAL vp, PCSZ fmt); + bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0); bool SetFormat(PGLOBAL g, PVAL valp); bool IsFormatted(void) {return Pdtp != NULL;} bool MakeTime(struct tm *ptm); diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index 48edd12b3d8..e6e530c4dc2 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -446,11 +446,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp) #if 0 if (!dup->Step) { strcpy(g->Message, MSG(QUERY_CANCELLED)); -#if defined(USE_TRY) throw 99; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], 99); -#endif // !USE_TRY } // endif Step #endif // 0 @@ -823,7 +819,7 @@ bool XINDEX::Reorder(PGLOBAL g __attribute__((unused))) /***********************************************************************/ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp) { - char *ftype; + PCSZ ftype; char fn[_MAX_PATH]; int n[NZ], nof = (Mul) ? (Ndif + 1) : 0; int id = -1, size = 0; @@ -952,7 +948,7 @@ bool XINDEX::Init(PGLOBAL g) /* Table will be accessed through an index table. */ /* If sorting is required, this will be done later. */ /*********************************************************************/ - char *ftype; + PCSZ ftype; char fn[_MAX_PATH]; int k, n, nv[NZ], id = -1; bool estim = false; @@ -969,8 +965,8 @@ bool XINDEX::Init(PGLOBAL g) // For DBF tables, Cardinality includes bad or soft deleted lines // that are not included in the index, and can be larger then the // index size. - estim = (Tdbp->Ftype == RECFM_DBF || Tdbp->Txfp->GetAmType() == TYPE_AM_ZIP); - n = Tdbp->Cardinality(g); // n is exact table size + estim = (Tdbp->Ftype == RECFM_DBF || Tdbp->Txfp->GetAmType() == TYPE_AM_ZIP); + n = Tdbp->Cardinality(g); // n is exact table size } else { // Variable table not optimized estim = true; // n is an estimate of the size @@ -1416,7 +1412,7 @@ err: /***********************************************************************/ bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk) { - char *ftype; + PCSZ ftype; char fn[_MAX_PATH]; int nv[NZ], id = -1; // n //bool estim = false; @@ -2324,9 +2320,9 @@ XFILE::XFILE(void) : XLOAD() /***********************************************************************/ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode) { - char *pmod; - bool rc; - IOFF noff[MAX_INDX]; + PCSZ pmod; + bool rc; + IOFF noff[MAX_INDX]; /*********************************************************************/ /* Open the index file according to mode. */ @@ -3036,7 +3032,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln) return true; Klen = Valp->GetClen(); - Keys.Size = n * Klen; + Keys.Size = (size_t)n * (size_t)Klen; if (!PlgDBalloc(g, NULL, Keys)) { sprintf(g->Message, MSG(KEY_ALLOC_ERROR), Klen, n); diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp index 7d1b6b9c992..cdffcb2fa44 100644 --- a/storage/connect/xobject.cpp +++ b/storage/connect/xobject.cpp @@ -84,11 +84,7 @@ double XOBJECT::GetFloatValue(void) CONSTANT::CONSTANT(PGLOBAL g, void *value, short type) { if (!(Value = AllocateValue(g, value, (int)type))) -#if defined(USE_TRY) throw TYPE_CONST; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_CONST); -#endif // !USE_TRY Constant = true; } // end of CONSTANT constructor @@ -99,11 +95,7 @@ CONSTANT::CONSTANT(PGLOBAL g, void *value, short type) CONSTANT::CONSTANT(PGLOBAL g, int n) { if (!(Value = AllocateValue(g, &n, TYPE_INT))) -#if defined(USE_TRY) throw TYPE_CONST; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_CONST); -#endif // !USE_TRY Constant = true; } // end of CONSTANT constructor @@ -125,11 +117,7 @@ void CONSTANT::Convert(PGLOBAL g, int newtype) { if (Value->GetType() != newtype) if (!(Value = AllocateValue(g, Value, newtype))) -#if defined(USE_TRY) throw TYPE_CONST; -#else // !USE_TRY - longjmp(g->jumper[g->jump_level], TYPE_CONST); -#endif // !USE_TRY } // end of Convert @@ -204,7 +192,7 @@ void CONSTANT::Print(PGLOBAL g, char *ps, uint z) /* STRING public constructor for new char values. Alloc Size must be */ /* calculated because PlugSubAlloc rounds up size to multiple of 8. */ /***********************************************************************/ -STRING::STRING(PGLOBAL g, uint n, char *str) +STRING::STRING(PGLOBAL g, uint n, PCSZ str) { G = g; Length = (str) ? strlen(str) : 0; @@ -217,10 +205,12 @@ STRING::STRING(PGLOBAL g, uint n, char *str) Next = GetNext(); Size = Next - Strp; + Trc = false; } else { // This should normally never happen Next = NULL; Size = 0; + Trc = true; } // endif Strp } // end of STRING constructor @@ -241,6 +231,7 @@ char *STRING::Realloc(uint len) if (!p) { // No more room in Sarea; this is very unlikely strcpy(G->Message, "No more room in work area"); + Trc = true; return NULL; } // endif p @@ -255,7 +246,7 @@ char *STRING::Realloc(uint len) /***********************************************************************/ /* Set a STRING new PSZ value. */ /***********************************************************************/ -bool STRING::Set(PSZ s) +bool STRING::Set(PCSZ s) { if (!s) return false; @@ -345,9 +336,9 @@ bool STRING::Append(const char *s, uint ln, bool nq) } // end of Append /***********************************************************************/ -/* Append a PSZ to a STRING. */ +/* Append a PCSZ to a STRING. */ /***********************************************************************/ -bool STRING::Append(PSZ s) +bool STRING::Append(PCSZ s) { if (!s) return false; @@ -404,11 +395,11 @@ bool STRING::Append(char c) /***********************************************************************/ /* Append a quoted PSZ to a STRING. */ /***********************************************************************/ -bool STRING::Append_quoted(PSZ s) +bool STRING::Append_quoted(PCSZ s) { bool b = Append('\''); - if (s) for (char *p = s; !b && *p; p++) + if (s) for (const char *p = s; !b && *p; p++) switch (*p) { case '\'': case '\\': diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h index 8f6c23c4aeb..204144182c8 100644 --- a/storage/connect/xobject.h +++ b/storage/connect/xobject.h @@ -123,24 +123,25 @@ class DllExport CONSTANT : public XOBJECT { class DllExport STRING : public BLOCK { public: // Constructor - STRING(PGLOBAL g, uint n, PSZ str = NULL); + STRING(PGLOBAL g, uint n, PCSZ str = NULL); // Implementation inline int GetLength(void) {return (int)Length;} inline void SetLength(uint n) {Length = n;} inline PSZ GetStr(void) {return Strp;} inline uint32 GetSize(void) {return Size;} + inline bool IsTruncated(void) {return Trc;} // Methods inline void Reset(void) {*Strp = 0;} - bool Set(PSZ s); + bool Set(PCSZ s); bool Set(char *s, uint n); bool Append(const char *s, uint ln, bool nq = false); - bool Append(PSZ s); + bool Append(PCSZ s); bool Append(STRING &str); bool Append(char c); bool Resize(uint n); - bool Append_quoted(PSZ s); + bool Append_quoted(PCSZ s); inline void Trim(void) {(void)Resize(Length + 1);} inline void Chop(void) {if (Length) Strp[--Length] = 0;} inline void RepLast(char c) {if (Length) Strp[Length-1] = c;} @@ -156,6 +157,7 @@ class DllExport STRING : public BLOCK { PSZ Strp; // The char string uint Length; // String length uint Size; // Allocated size + bool Trc; // When truncated char *Next; // Next alloc position }; // end of class STRING diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h index 4aeea05946a..3da0c17bdfe 100644 --- a/storage/connect/xtable.h +++ b/storage/connect/xtable.h @@ -33,29 +33,6 @@ class CMD : public BLOCK { char *Cmd; }; // end of class CMD -#if 0 -// Condition filter structure -class CONDFIL : public BLOCK { - public: - // Constructor - CONDFIL(const Item *cond, uint idx, AMT type) - { - Cond = cond; Idx = idx; Type = type; Op = OP_XX; - Cmds = NULL; All = true; Body = NULL, Having = NULL; - } - - // Members - const Item *Cond; - AMT Type; - uint Idx; - OPVAL Op; - PCMD Cmds; - bool All; - char *Body; - char *Having; -}; // end of class CONDFIL -#endif // 0 - typedef class EXTCOL *PEXTCOL; typedef class CONDFIL *PCFIL; typedef class TDBCAT *PTDBCAT; @@ -84,7 +61,6 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. inline PFIL GetFilter(void) {return To_Filter;} inline PCOL GetSetCols(void) {return To_SetCols;} inline void SetSetCols(PCOL colp) {To_SetCols = colp;} - inline void SetFilter(PFIL fp) {To_Filter = fp;} inline void SetOrig(PTDB txp) {To_Orig = txp;} inline void SetUse(TUSE n) {Use = n;} inline void SetCondFil(PCFIL cfp) {To_CondFil = cfp;} @@ -94,11 +70,14 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. inline void SetColumns(PCOL colp) {Columns = colp;} inline void SetDegree(int degree) {Degree = degree;} inline void SetMode(MODE mode) {Mode = mode;} + inline const Item *GetCond(void) {return Cond;} + inline void SetCond(const Item *cond) {Cond = cond;} // Properties virtual AMT GetAmType(void) {return TYPE_AM_ERROR;} virtual bool IsRemote(void) {return false;} virtual bool IsIndexed(void) {return false;} + virtual void SetFilter(PFIL fp) {To_Filter = fp;} virtual int GetTdb_No(void) {return Tdb_No;} virtual PTDB GetNext(void) {return Next;} virtual PCATLG GetCat(void) {return NULL;} @@ -110,7 +89,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. virtual bool IsSpecial(PSZ name); virtual bool IsReadOnly(void) {return Read_Only;} virtual bool IsView(void) {return FALSE;} - virtual PSZ GetPath(void); + virtual PCSZ GetPath(void); virtual RECFM GetFtype(void) {return RECFM_NAF;} virtual bool GetBlockValues(PGLOBAL) { return false; } virtual int Cardinality(PGLOBAL) {return 0;} @@ -119,11 +98,12 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. virtual int GetMaxSize(PGLOBAL) = 0; virtual int GetProgMax(PGLOBAL) = 0; virtual int GetProgCur(void) {return GetRecpos();} - virtual PSZ GetFile(PGLOBAL) {return "Not a file";} - virtual void SetFile(PGLOBAL, PSZ) {} + virtual PCSZ GetFile(PGLOBAL) {return "Not a file";} + virtual void SetFile(PGLOBAL, PCSZ) {} virtual void ResetDB(void) {} virtual void ResetSize(void) {MaxSize = -1;} virtual int RowNumber(PGLOBAL g, bool b = false); + virtual bool CanBeFiltered(void) {return true;} virtual PTDB Duplicate(PGLOBAL) {return NULL;} virtual PTDB Clone(PTABS) {return this;} virtual PTDB Copy(PTABS t); @@ -131,7 +111,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. {fprintf(f, "%s AM(%d)\n", m, GetAmType());} virtual void Print(PGLOBAL g, FILE *f, uint n); virtual void Print(PGLOBAL g, char *ps, uint z); - virtual PSZ GetServer(void) = 0; + virtual PCSZ GetServer(void) = 0; virtual int GetBadLines(void) {return 0;} virtual CHARSET_INFO *data_charset(void); @@ -157,6 +137,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. TUSE Use; PFIL To_Filter; PCFIL To_CondFil; // To condition filter structure + const Item *Cond; // The condition used to make filters static int Tnum; // Used to generate Tdb_no's const int Tdb_No; // GetTdb_No() is always 0 for OPJOIN PTDB Next; // Next in linearized queries @@ -187,9 +168,6 @@ class DllExport TDBASE : public TDB { // Implementation inline int GetKnum(void) {return Knum;} -//inline PTABDEF GetDef(void) {return To_Def;} -//inline PCOL GetSetCols(void) {return To_SetCols;} -//inline void SetSetCols(PCOL colp) {To_SetCols = colp;} inline void SetKey_Col(PCOL *cpp) {To_Key_Col = cpp;} inline void SetXdp(PIXDEF xdp) {To_Xdp = xdp;} inline void SetKindex(PKXBASE kxp) {To_Kindex = kxp;} @@ -201,36 +179,14 @@ class DllExport TDBASE : public TDB { // Methods virtual bool IsUsingTemp(PGLOBAL) {return false;} -//virtual bool IsIndexed(void) {return false;} -//virtual bool IsSpecial(PSZ name); virtual PCATLG GetCat(void); -//virtual PSZ GetPath(void); virtual void PrintAM(FILE *f, char *m); -//virtual RECFM GetFtype(void) {return RECFM_NAF;} -//virtual int GetAffectedRows(void) {return -1;} -//virtual int GetRecpos(void) = 0; -//virtual bool SetRecpos(PGLOBAL g, int recpos); -//virtual bool IsReadOnly(void) {return Read_Only;} -//virtual bool IsView(void) {return FALSE;} -//virtual CHARSET_INFO *data_charset(void); virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);} -//virtual int GetProgCur(void) {return GetRecpos();} -//virtual PSZ GetFile(PGLOBAL) {return "Not a file";} -//virtual int GetRemote(void) {return 0;} -//virtual void SetFile(PGLOBAL, PSZ) {} -//virtual void ResetDB(void) {} -//virtual void ResetSize(void) {MaxSize = -1;} virtual void RestoreNrec(void) {} virtual int ResetTableOpt(PGLOBAL g, bool dop, bool dox); - virtual PSZ GetServer(void) {return "Current";} + virtual PCSZ GetServer(void) {return "Current";} // Database routines -//virtual PCOL ColDB(PGLOBAL g, PSZ name, int num); -//virtual PCOL MakeCol(PGLOBAL, PCOLDEF, PCOL, int) -// {assert(false); return NULL;} -//virtual PCOL InsertSpecialColumn(PCOL colp); -//virtual PCOL InsertSpcBlk(PGLOBAL g, PCOLDEF cdp); -//virtual void MarkDB(PGLOBAL g, PTDB tdb2); virtual int MakeIndex(PGLOBAL g, PIXDEF, bool) {strcpy(g->Message, "Remote index"); return RC_INFO;} virtual bool ReadKey(PGLOBAL, OPVAL, const key_range *) @@ -241,18 +197,12 @@ class DllExport TDBASE : public TDB { "This function should not be called for this table"); return true;} // Members -//PTABDEF To_Def; // Points to catalog description block PXOB *To_Link; // Points to column of previous relations PCOL *To_Key_Col; // Points to key columns in current file PKXBASE To_Kindex; // Points to table key index PIXDEF To_Xdp; // To the index definition block -//PCOL To_SetCols; // Points to updated columns RECFM Ftype; // File type: 0-var 1-fixed 2-binary (VCT) -//int MaxSize; // Max size in number of lines int Knum; // Size of key arrays -//bool Read_Only; // True for read only tables -//const CHARSET_INFO *m_data_charset; -//const char *csname; // Table charset name }; // end of class TDBASE /***********************************************************************/ diff --git a/storage/connect/zip.c b/storage/connect/zip.c index ea54853e858..4bbe31ab7dd 100644 --- a/storage/connect/zip.c +++ b/storage/connect/zip.c @@ -637,7 +637,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib return relativeOffset; } -int LoadCentralDirectoryRecord(zip64_internal* pziinit) +static int LoadCentralDirectoryRecord(zip64_internal* pziinit) { int err=ZIP_OK; ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ @@ -846,7 +846,7 @@ int LoadCentralDirectoryRecord(zip64_internal* pziinit) /************************************************************/ -extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) +static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) { zip64_internal ziinit; zip64_internal* zi; @@ -955,7 +955,7 @@ extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) return zipOpen3(pathname,append,NULL,NULL); } -int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) +static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) { /* write the local header */ int err; @@ -1752,7 +1752,7 @@ extern int ZEXPORT zipCloseFileInZip (zipFile file) return zipCloseFileInZipRaw (file,0,0); } -int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) +static int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { int err = ZIP_OK; ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; @@ -1774,7 +1774,7 @@ int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eo return err; } -int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +static int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; @@ -1813,7 +1813,7 @@ int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centra } return err; } -int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +static int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; @@ -1861,7 +1861,7 @@ int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, return err; } -int Write_GlobalComment(zip64_internal* zi, const char* global_comment) +static int Write_GlobalComment(zip64_internal* zi, const char* global_comment) { int err = ZIP_OK; uInt size_global_comment = 0; From 436070c6e106d22f2afce3a28fc15e33a2241ef9 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 12 May 2017 00:33:33 +0200 Subject: [PATCH 092/148] Fix failing test connect.json for MariaDB 10.0 Suppressing Uri and dsn from json tables (was MGO) modified: storage/connect/ha_connect.cc modified: storage/connect/tabdos.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/tabjson.h --- storage/connect/ha_connect.cc | 8 +++----- storage/connect/tabdos.cpp | 2 -- storage/connect/tabjson.cpp | 9 ++++----- storage/connect/tabjson.h | 3 +-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 240625d03fb..d20fa05a463 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -209,7 +209,7 @@ pthread_mutex_t parmut = PTHREAD_MUTEX_INITIALIZER; /***********************************************************************/ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); PQRYRES VirColumns(PGLOBAL g, bool info); -PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info); +PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info); PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info); int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v); void PushWarning(PGLOBAL g, THD *thd, int level); @@ -5557,9 +5557,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_XML: #endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT case TAB_JSON: - dsn = strz(g, create_info->connect_string); - - if (!fn && !zfn && !mul && !dsn) + if (!fn && !zfn && !mul) sprintf(g->Message, "Missing %s file name", topt->type); else ok = true; @@ -5705,7 +5703,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, qrp = VirColumns(g, fnc == FNC_COL); break; case TAB_JSON: - qrp = JSONColumns(g, (char*)db, dsn, topt, fnc == FNC_COL); + qrp = JSONColumns(g, (char*)db, topt, fnc == FNC_COL); break; #if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT) case TAB_XML: diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 6f95eafe838..87925161320 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -132,7 +132,6 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int) bool map = (am && (*am == 'M' || *am == 'm')); LPCSTR dfm = (am && (*am == 'F' || *am == 'f')) ? "F" : (am && (*am == 'B' || *am == 'b')) ? "B" - : (am && (*am == 'X' || *am == 'x')) ? "X" : (am && !stricmp(am, "DBF")) ? "D" : "V"; if ((Zipped = GetBoolCatInfo("Zipped", false))) { @@ -149,7 +148,6 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int) GetCharCatInfo("Recfm", (PSZ)dfm, buf, sizeof(buf)); Recfm = (toupper(*buf) == 'F') ? RECFM_FIX : (toupper(*buf) == 'B') ? RECFM_BIN : - (toupper(*buf) == 'X') ? RECFM_NAF : // MGO (toupper(*buf) == 'D') ? RECFM_DBF : RECFM_VAR; Lrecl = GetIntCatInfo("Lrecl", 0); diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index edfe710bc92..5853425a4e5 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -63,7 +63,7 @@ typedef struct _jncol { /* JSONColumns: construct the result blocks containing the description */ /* of all the columns of a table contained inside a JSON file. */ /***********************************************************************/ -PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info) +PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; @@ -112,7 +112,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info) #endif // ZIP_SUPPORT tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); - if (!tdp->Fn && !dsn) { + if (!tdp->Fn) { strcpy(g->Message, MSG(MISSING_FNAME)); return NULL; } // endif Fn @@ -424,7 +424,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff) Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 10); Base = GetIntCatInfo("Base", 0) ? 1 : 0; - return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff); + return DOSDEF::DefineAM(g, "DOS", poff); } // end of DefineAM /***********************************************************************/ @@ -2048,7 +2048,6 @@ TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) { Topt = tdp->GetTopt(); Db = (char*)tdp->GetDB(); - Dsn = (char*)tdp->Uri; } // end of TDBJCL constructor /***********************************************************************/ @@ -2056,7 +2055,7 @@ TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) /***********************************************************************/ PQRYRES TDBJCL::GetResult(PGLOBAL g) { - return JSONColumns(g, Db, Dsn, Topt, false); + return JSONColumns(g, Db, Topt, false); } // end of GetResult /* --------------------------- End of json --------------------------- */ diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index 2c8f226b5ca..c16cf6846b6 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -36,7 +36,7 @@ class DllExport JSONDEF : public DOSDEF { /* Table description */ friend class TDBJSON; friend class TDBJSN; friend class TDBJCL; - friend PQRYRES JSONColumns(PGLOBAL, char*, char*, PTOS, bool); + friend PQRYRES JSONColumns(PGLOBAL, char*, PTOS, bool); public: // Constructor JSONDEF(void); @@ -58,7 +58,6 @@ public: int Level; /* Used for catalog table */ int Base; /* The array index base */ bool Strict; /* Strict syntax checking */ - const char *Uri; /* MongoDB connection URI */ }; // end of JSONDEF /* -------------------------- TDBJSN class --------------------------- */ From 9495e018fbd88d094a71cb054cf468c31ebd6957 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Fri, 12 May 2017 11:09:27 +0530 Subject: [PATCH 093/148] MDEV-11718 Post-fix A better way of finding mysqld --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 0d9626b77e1..1e27f31989f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -6190,7 +6190,8 @@ sub valgrind_arguments { mtr_add_arg($args, "--num-callers=16"); mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir) if -f "$glob_mysql_test_dir/valgrind.supp"; - my $temp= `ldd $ENV{MTR_BINDIR}/sql/mysqld | grep 'libjemalloc'`; + my $exe_mysqld= find_mysqld($bindir) || ""; + my $temp= `ldd $exe_mysqld | grep 'libjemalloc'`; if ($temp) { mtr_add_arg($args, "--soname-synonyms=somalloc=libjemalloc*"); From ff166093741df0bd91ba24e02714ef882073c51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 11 May 2017 21:12:37 +0300 Subject: [PATCH 094/148] MDEV-12674 Innodb_row_lock_current_waits has overflow There is a race condition related to the variable srv_stats.n_lock_wait_current_count, which is only incremented and decremented by the function lock_wait_suspend_thread(), The incrementing is protected by lock_sys->wait_mutex, but the decrementing does not appear to be protected by anything. This mismatch could allow the counter to be corrupted when a transactional InnoDB table or record lock wait is terminating roughly at the same time with the start of a wait on a (possibly different) lock. ib_counter_t: Remove some unused methods. Prevent instantiation for N=1. Add an inc() method that takes a slot index as a parameter. single_indexer_t: Remove. simple_counter: A new counter wrapper. Optionally use atomic memory operations for modifying the counter. Aligned to the cache line size. lsn_ctr_1_t, ulint_ctr_1_t, int64_ctr_1_t: Define as simple_counter. These counters are either only incremented (and we do not care about losing some increment operations), or the increment/decrement operations are protected by some mutex. srv_stats_t::os_log_pending_writes: Document that the number is protected by log_sys->mutex. srv_stats_t::n_lock_wait_current_count: Use simple_counter, that is, atomic inc() and dec() operations. lock_wait_suspend_thread(): Release the mutexes before incrementing the counters. Avoid acquiring the lock mutex if the lock wait has already been resolved. Atomically increment and decrement srv_stats.n_lock_wait_current_count. row_insert_for_mysql(), row_update_for_mysql(), row_update_cascade_for_mysql(): Use the inc() method with the trx->id as the slot index. This is a non-functional change, just using inc() instead of add(1). buf_LRU_get_free_block(): Replace the method add(index, n) with inc(). There is no slot index in the simple_counter. --- storage/innobase/buf/buf0lru.cc | 3 +- storage/innobase/include/os0sync.h | 59 ++++++++++++++-- storage/innobase/include/srv0srv.h | 16 ++--- storage/innobase/include/ut0counter.h | 98 ++++++--------------------- storage/innobase/lock/lock0wait.cc | 22 +++--- storage/innobase/row/row0mysql.cc | 25 +++---- storage/xtradb/buf/buf0lru.cc | 5 +- storage/xtradb/include/os0sync.h | 58 ++++++++++++++-- storage/xtradb/include/srv0srv.h | 16 ++--- storage/xtradb/include/ut0counter.h | 98 ++++++--------------------- storage/xtradb/lock/lock0wait.cc | 22 +++--- storage/xtradb/row/row0mysql.cc | 25 +++---- 12 files changed, 214 insertions(+), 233 deletions(-) diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index f981eb31ba8..6ec443b4600 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1369,7 +1370,7 @@ loop: ++flush_failures; } - srv_stats.buf_pool_wait_free.add(n_iterations, 1); + srv_stats.buf_pool_wait_free.inc(); n_iterations++; diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index dd6de43dc0b..54032b5ad31 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -2,6 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -36,14 +37,13 @@ Created 9/6/1995 Heikki Tuuri #include "univ.i" #include "ut0lst.h" -#include "sync0types.h" -#if defined __i386__ || defined __x86_64__ || defined _M_IX86 \ - || defined _M_X64 || defined __WIN__ - -#define IB_STRONG_MEMORY_MODEL - -#endif /* __i386__ || __x86_64__ || _M_IX86 || _M_X64 || __WIN__ */ +/** CPU cache line size */ +#ifdef __powerpc__ +#define CACHE_LINE_SIZE 128 +#else +#define CACHE_LINE_SIZE 64 +#endif #ifdef HAVE_WINDOWS_ATOMICS typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates @@ -889,6 +889,51 @@ for synchronization */ "Memory barrier is not used" #endif + +/** Simple counter aligned to CACHE_LINE_SIZE +@tparam Type the integer type of the counter +@tparam atomic whether to use atomic memory access */ +template +struct MY_ALIGNED(CACHE_LINE_SIZE) simple_counter +{ + /** Increment the counter */ + Type inc() { return add(1); } + /** Decrement the counter */ + Type dec() { return sub(1); } + + /** Add to the counter + @param[in] i amount to be added + @return the value of the counter after adding */ + Type add(Type i) + { + compile_time_assert(!atomic || sizeof(Type) == sizeof(ulint)); + if (atomic) { + return os_atomic_increment_ulint(&m_counter, i); + } else { + return m_counter += i; + } + } + /** Subtract from the counter + @param[in] i amount to be subtracted + @return the value of the counter after adding */ + Type sub(Type i) + { + compile_time_assert(!atomic || sizeof(Type) == sizeof(ulint)); + if (atomic) { + return os_atomic_decrement_ulint(&m_counter, i); + } else { + return m_counter -= i; + } + } + + /** @return the value of the counter (non-atomic access)! */ + operator Type() const { return m_counter; } + +private: + /** The counter */ + Type m_counter; +}; + #ifndef UNIV_NONINL #include "os0sync.ic" #endif diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index ec528495742..11e7a7b9a0a 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2017, MariaDB Corporation Ab. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -55,11 +55,10 @@ Created 10/10/1995 Heikki Tuuri /* Global counters used inside InnoDB. */ struct srv_stats_t { - typedef ib_counter_t lsn_ctr_1_t; - typedef ib_counter_t ulint_ctr_1_t; - typedef ib_counter_t lint_ctr_1_t; typedef ib_counter_t ulint_ctr_64_t; - typedef ib_counter_t ib_int64_ctr_1_t; + typedef simple_counter lsn_ctr_1_t; + typedef simple_counter ulint_ctr_1_t; + typedef simple_counter ib_int64_ctr_1_t; /** Count the amount of data written in total (in bytes) */ ulint_ctr_1_t data_written; @@ -73,8 +72,9 @@ struct srv_stats_t { /** Amount of data written to the log files in bytes */ lsn_ctr_1_t os_log_written; - /** Number of writes being done to the log files */ - lint_ctr_1_t os_log_pending_writes; + /** Number of writes being done to the log files. + Protected by log_sys->write_mutex. */ + ulint_ctr_1_t os_log_pending_writes; /** We increase this counter, when we don't have enough space in the log buffer and have to flush it */ @@ -113,7 +113,7 @@ struct srv_stats_t { ulint_ctr_1_t n_lock_wait_count; /** Number of threads currently waiting on database locks */ - lint_ctr_1_t n_lock_wait_current_count; + simple_counter n_lock_wait_current_count; /** Number of rows read. */ ulint_ctr_64_t n_rows_read; diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index 63a133a175d..edc0db3b03d 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,13 +31,7 @@ Created 2012/04/12 by Sunny Bains #include "univ.i" #include #include "os0thread.h" - -/** CPU cache line size */ -#ifdef __powerpc__ -#define CACHE_LINE_SIZE 128 -#else -#define CACHE_LINE_SIZE 64 -#endif +#include "os0sync.h" /** Default number of slots to use in ib_counter_t */ #define IB_N_SLOTS 64 @@ -44,8 +39,6 @@ Created 2012/04/12 by Sunny Bains /** Get the offset into the counter array. */ template struct generic_indexer_t { - /** Default constructor/destructor should be OK. */ - /** @return offset within m_counter */ size_t offset(size_t index) const UNIV_NOTHROW { return(((index % N) + 1) * (CACHE_LINE_SIZE / sizeof(Type))); @@ -58,8 +51,6 @@ struct generic_indexer_t { use the thread id. */ template struct get_sched_indexer_t : public generic_indexer_t { - /** Default constructor/destructor should be OK. */ - /* @return result from sched_getcpu(), the thread id if it fails. */ size_t get_rnd_index() const UNIV_NOTHROW { @@ -76,31 +67,17 @@ struct get_sched_indexer_t : public generic_indexer_t { /** Use the thread id to index into the counter array. */ template struct thread_id_indexer_t : public generic_indexer_t { - /** Default constructor/destructor should are OK. */ - /* @return a random number, currently we use the thread id. Where thread id is represented as a pointer, it may not work as effectively. */ size_t get_rnd_index() const UNIV_NOTHROW { return((lint) os_thread_get_curr_id()); } -}; -/** For counters wher N=1 */ -template -struct single_indexer_t { - /** Default constructor/destructor should are OK. */ - - /** @return offset within m_counter */ - size_t offset(size_t index) const UNIV_NOTHROW { - ut_ad(N == 1); - return((CACHE_LINE_SIZE / sizeof(Type))); - } - - /* @return 1 */ - size_t get_rnd_index() const UNIV_NOTHROW { - ut_ad(N == 1); - return(1); + /** @return a random offset to the array */ + size_t get_rnd_offset() const UNIV_NOTHROW + { + return(generic_indexer_t::offset(get_rnd_index())); } }; @@ -112,17 +89,11 @@ template < typename Type, int N = IB_N_SLOTS, template class Indexer = thread_id_indexer_t> -class ib_counter_t { -public: - ib_counter_t() { memset(m_counter, 0x0, sizeof(m_counter)); } - +struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t +{ +#ifdef UNIV_DEBUG ~ib_counter_t() { - ut_ad(validate()); - } - - bool validate() UNIV_NOTHROW { -#ifdef UNIV_DEBUG size_t n = (CACHE_LINE_SIZE / sizeof(Type)); /* Check that we aren't writing outside our defined bounds. */ @@ -131,27 +102,23 @@ public: ut_ad(m_counter[i + j] == 0); } } -#endif /* UNIV_DEBUG */ - return(true); } +#endif /* UNIV_DEBUG */ - /** If you can't use a good index id. Increment by 1. */ + /** Increment the counter by 1. */ void inc() UNIV_NOTHROW { add(1); } - /** If you can't use a good index id. - * @param n - is the amount to increment */ - void add(Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(m_policy.get_rnd_index()); + /** Increment the counter by 1. + @param[in] index a reasonably thread-unique identifier */ + void inc(size_t index) UNIV_NOTHROW { add(index, 1); } - ut_ad(i < UT_ARR_SIZE(m_counter)); + /** Add to the counter. + @param[in] n amount to be added */ + void add(Type n) UNIV_NOTHROW { add(m_policy.get_rnd_offset(), n); } - m_counter[i] += n; - } - - /** Use this if you can use a unique indentifier, saves a - call to get_rnd_index(). - @param i - index into a slot - @param n - amount to increment */ + /** Add to the counter. + @param[in] index a reasonably thread-unique identifier + @param[in] n amount to be added */ void add(size_t index, Type n) UNIV_NOTHROW { size_t i = m_policy.offset(index); @@ -160,31 +127,6 @@ public: m_counter[i] += n; } - /** If you can't use a good index id. Decrement by 1. */ - void dec() UNIV_NOTHROW { sub(1); } - - /** If you can't use a good index id. - * @param - n is the amount to decrement */ - void sub(Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(m_policy.get_rnd_index()); - - ut_ad(i < UT_ARR_SIZE(m_counter)); - - m_counter[i] -= n; - } - - /** Use this if you can use a unique indentifier, saves a - call to get_rnd_index(). - @param i - index into a slot - @param n - amount to decrement */ - void sub(size_t index, Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(index); - - ut_ad(i < UT_ARR_SIZE(m_counter)); - - m_counter[i] -= n; - } - /* @return total value - not 100% accurate, since it is not atomic. */ operator Type() const UNIV_NOTHROW { Type total = 0; diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index 4ca048a50d5..5b67fbe72b7 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 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 @@ -248,6 +249,9 @@ lock_wait_suspend_thread( slot = lock_wait_table_reserve_slot(thr, lock_wait_timeout); + lock_wait_mutex_exit(); + trx_mutex_exit(trx); + if (thr->lock_state == QUE_THR_LOCK_ROW) { srv_stats.n_lock_wait_count.inc(); srv_stats.n_lock_wait_current_count.inc(); @@ -259,19 +263,21 @@ lock_wait_suspend_thread( } } - lock_wait_mutex_exit(); - trx_mutex_exit(trx); - ulint lock_type = ULINT_UNDEFINED; - lock_mutex_enter(); - + /* The wait_lock can be cleared by another thread when the + lock is released. But the wait can only be initiated by the + current thread which owns the transaction. Only acquire the + mutex if the wait_lock is still active. */ if (const lock_t* wait_lock = trx->lock.wait_lock) { - lock_type = lock_get_type_low(wait_lock); + lock_mutex_enter(); + wait_lock = trx->lock.wait_lock; + if (wait_lock) { + lock_type = lock_get_type_low(wait_lock); + } + lock_mutex_exit(); } - lock_mutex_exit(); - had_dict_lock = trx->dict_operation_lock_mode; switch (had_dict_lock) { diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 6eb93f9e22d..a3f4355ec6c 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1451,9 +1452,9 @@ error_exit: que_thr_stop_for_mysql_no_error(thr, trx); if (table->is_system_db) { - srv_stats.n_system_rows_inserted.add((size_t)trx->id, 1); + srv_stats.n_system_rows_inserted.inc(size_t(trx->id)); } else { - srv_stats.n_rows_inserted.add((size_t)trx->id, 1); + srv_stats.n_rows_inserted.inc(size_t(trx->id)); } /* Not protected by dict_table_stats_lock() for performance @@ -1847,18 +1848,16 @@ run_again: dict_table_n_rows_dec(prebuilt->table); if (table->is_system_db) { - srv_stats.n_system_rows_deleted.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_deleted.inc(size_t(trx->id)); } else { - srv_stats.n_rows_deleted.add((size_t)trx->id, 1); + srv_stats.n_rows_deleted.inc(size_t(trx->id)); } } else { if (table->is_system_db) { - srv_stats.n_system_rows_updated.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_updated.inc(size_t(trx->id)); } else { - srv_stats.n_rows_updated.add((size_t)trx->id, 1); + srv_stats.n_rows_updated.inc(size_t(trx->id)); } } @@ -2091,17 +2090,15 @@ run_again: dict_table_n_rows_dec(table); if (table->is_system_db) { - srv_stats.n_system_rows_deleted.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_deleted.inc(size_t(trx->id)); } else { - srv_stats.n_rows_deleted.add((size_t)trx->id, 1); + srv_stats.n_rows_deleted.inc(size_t(trx->id)); } } else { if (table->is_system_db) { - srv_stats.n_system_rows_updated.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_updated.inc(size_t(trx->id)); } else { - srv_stats.n_rows_updated.add((size_t)trx->id, 1); + srv_stats.n_rows_updated.inc(size_t(trx->id)); } } diff --git a/storage/xtradb/buf/buf0lru.cc b/storage/xtradb/buf/buf0lru.cc index 1aa2e7a9eb7..d31773c96cc 100644 --- a/storage/xtradb/buf/buf0lru.cc +++ b/storage/xtradb/buf/buf0lru.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1501,7 +1502,7 @@ loop: n_iterations++; - srv_stats.buf_pool_wait_free.add(n_iterations, 1); + srv_stats.buf_pool_wait_free.inc(); /* In case of backoff, do not ever attempt single page flushes and wait for the cleaner to free some pages instead. */ @@ -1595,7 +1596,7 @@ loop: ++flush_failures; } - srv_stats.buf_pool_wait_free.add(n_iterations, 1); + srv_stats.buf_pool_wait_free.inc(); n_iterations++; diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h index 48c56a73369..b152ab53e68 100644 --- a/storage/xtradb/include/os0sync.h +++ b/storage/xtradb/include/os0sync.h @@ -2,6 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -38,12 +39,12 @@ Created 9/6/1995 Heikki Tuuri #include "ut0lst.h" #include "sync0types.h" -#if defined __i386__ || defined __x86_64__ || defined _M_IX86 \ - || defined _M_X64 || defined __WIN__ - -#define IB_STRONG_MEMORY_MODEL - -#endif /* __i386__ || __x86_64__ || _M_IX86 || _M_X64 || __WIN__ */ +/** CPU cache line size */ +#ifdef __powerpc__ +#define CACHE_LINE_SIZE 128 +#else +#define CACHE_LINE_SIZE 64 +#endif #ifdef HAVE_WINDOWS_ATOMICS typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates @@ -940,6 +941,51 @@ for synchronization */ "Memory barrier is not used" #endif + +/** Simple counter aligned to CACHE_LINE_SIZE +@tparam Type the integer type of the counter +@tparam atomic whether to use atomic memory access */ +template +struct MY_ALIGNED(CACHE_LINE_SIZE) simple_counter +{ + /** Increment the counter */ + Type inc() { return add(1); } + /** Decrement the counter */ + Type dec() { return sub(1); } + + /** Add to the counter + @param[in] i amount to be added + @return the value of the counter after adding */ + Type add(Type i) + { + compile_time_assert(!atomic || sizeof(Type) == sizeof(ulint)); + if (atomic) { + return os_atomic_increment_ulint(&m_counter, i); + } else { + return m_counter += i; + } + } + /** Subtract from the counter + @param[in] i amount to be subtracted + @return the value of the counter after adding */ + Type sub(Type i) + { + compile_time_assert(!atomic || sizeof(Type) == sizeof(ulint)); + if (atomic) { + return os_atomic_decrement_ulint(&m_counter, i); + } else { + return m_counter -= i; + } + } + + /** @return the value of the counter (non-atomic access)! */ + operator Type() const { return m_counter; } + +private: + /** The counter */ + Type m_counter; +}; + #ifndef UNIV_NONINL #include "os0sync.ic" #endif diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 0923c9a88d7..1ca8e6de591 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2017, MariaDB Corporation Ab. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -55,11 +55,10 @@ Created 10/10/1995 Heikki Tuuri /* Global counters used inside InnoDB. */ struct srv_stats_t { - typedef ib_counter_t lsn_ctr_1_t; - typedef ib_counter_t ulint_ctr_1_t; - typedef ib_counter_t lint_ctr_1_t; typedef ib_counter_t ulint_ctr_64_t; - typedef ib_counter_t ib_int64_ctr_1_t; + typedef simple_counter lsn_ctr_1_t; + typedef simple_counter ulint_ctr_1_t; + typedef simple_counter ib_int64_ctr_1_t; /** Count the amount of data written in total (in bytes) */ ulint_ctr_1_t data_written; @@ -73,8 +72,9 @@ struct srv_stats_t { /** Amount of data written to the log files in bytes */ lsn_ctr_1_t os_log_written; - /** Number of writes being done to the log files */ - lint_ctr_1_t os_log_pending_writes; + /** Number of writes being done to the log files. + Protected by log_sys->write_mutex. */ + ulint_ctr_1_t os_log_pending_writes; /** We increase this counter, when we don't have enough space in the log buffer and have to flush it */ @@ -113,7 +113,7 @@ struct srv_stats_t { ulint_ctr_1_t n_lock_wait_count; /** Number of threads currently waiting on database locks */ - lint_ctr_1_t n_lock_wait_current_count; + simple_counter n_lock_wait_current_count; /** Number of rows read. */ ulint_ctr_64_t n_rows_read; diff --git a/storage/xtradb/include/ut0counter.h b/storage/xtradb/include/ut0counter.h index 63a133a175d..edc0db3b03d 100644 --- a/storage/xtradb/include/ut0counter.h +++ b/storage/xtradb/include/ut0counter.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,13 +31,7 @@ Created 2012/04/12 by Sunny Bains #include "univ.i" #include #include "os0thread.h" - -/** CPU cache line size */ -#ifdef __powerpc__ -#define CACHE_LINE_SIZE 128 -#else -#define CACHE_LINE_SIZE 64 -#endif +#include "os0sync.h" /** Default number of slots to use in ib_counter_t */ #define IB_N_SLOTS 64 @@ -44,8 +39,6 @@ Created 2012/04/12 by Sunny Bains /** Get the offset into the counter array. */ template struct generic_indexer_t { - /** Default constructor/destructor should be OK. */ - /** @return offset within m_counter */ size_t offset(size_t index) const UNIV_NOTHROW { return(((index % N) + 1) * (CACHE_LINE_SIZE / sizeof(Type))); @@ -58,8 +51,6 @@ struct generic_indexer_t { use the thread id. */ template struct get_sched_indexer_t : public generic_indexer_t { - /** Default constructor/destructor should be OK. */ - /* @return result from sched_getcpu(), the thread id if it fails. */ size_t get_rnd_index() const UNIV_NOTHROW { @@ -76,31 +67,17 @@ struct get_sched_indexer_t : public generic_indexer_t { /** Use the thread id to index into the counter array. */ template struct thread_id_indexer_t : public generic_indexer_t { - /** Default constructor/destructor should are OK. */ - /* @return a random number, currently we use the thread id. Where thread id is represented as a pointer, it may not work as effectively. */ size_t get_rnd_index() const UNIV_NOTHROW { return((lint) os_thread_get_curr_id()); } -}; -/** For counters wher N=1 */ -template -struct single_indexer_t { - /** Default constructor/destructor should are OK. */ - - /** @return offset within m_counter */ - size_t offset(size_t index) const UNIV_NOTHROW { - ut_ad(N == 1); - return((CACHE_LINE_SIZE / sizeof(Type))); - } - - /* @return 1 */ - size_t get_rnd_index() const UNIV_NOTHROW { - ut_ad(N == 1); - return(1); + /** @return a random offset to the array */ + size_t get_rnd_offset() const UNIV_NOTHROW + { + return(generic_indexer_t::offset(get_rnd_index())); } }; @@ -112,17 +89,11 @@ template < typename Type, int N = IB_N_SLOTS, template class Indexer = thread_id_indexer_t> -class ib_counter_t { -public: - ib_counter_t() { memset(m_counter, 0x0, sizeof(m_counter)); } - +struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t +{ +#ifdef UNIV_DEBUG ~ib_counter_t() { - ut_ad(validate()); - } - - bool validate() UNIV_NOTHROW { -#ifdef UNIV_DEBUG size_t n = (CACHE_LINE_SIZE / sizeof(Type)); /* Check that we aren't writing outside our defined bounds. */ @@ -131,27 +102,23 @@ public: ut_ad(m_counter[i + j] == 0); } } -#endif /* UNIV_DEBUG */ - return(true); } +#endif /* UNIV_DEBUG */ - /** If you can't use a good index id. Increment by 1. */ + /** Increment the counter by 1. */ void inc() UNIV_NOTHROW { add(1); } - /** If you can't use a good index id. - * @param n - is the amount to increment */ - void add(Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(m_policy.get_rnd_index()); + /** Increment the counter by 1. + @param[in] index a reasonably thread-unique identifier */ + void inc(size_t index) UNIV_NOTHROW { add(index, 1); } - ut_ad(i < UT_ARR_SIZE(m_counter)); + /** Add to the counter. + @param[in] n amount to be added */ + void add(Type n) UNIV_NOTHROW { add(m_policy.get_rnd_offset(), n); } - m_counter[i] += n; - } - - /** Use this if you can use a unique indentifier, saves a - call to get_rnd_index(). - @param i - index into a slot - @param n - amount to increment */ + /** Add to the counter. + @param[in] index a reasonably thread-unique identifier + @param[in] n amount to be added */ void add(size_t index, Type n) UNIV_NOTHROW { size_t i = m_policy.offset(index); @@ -160,31 +127,6 @@ public: m_counter[i] += n; } - /** If you can't use a good index id. Decrement by 1. */ - void dec() UNIV_NOTHROW { sub(1); } - - /** If you can't use a good index id. - * @param - n is the amount to decrement */ - void sub(Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(m_policy.get_rnd_index()); - - ut_ad(i < UT_ARR_SIZE(m_counter)); - - m_counter[i] -= n; - } - - /** Use this if you can use a unique indentifier, saves a - call to get_rnd_index(). - @param i - index into a slot - @param n - amount to decrement */ - void sub(size_t index, Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(index); - - ut_ad(i < UT_ARR_SIZE(m_counter)); - - m_counter[i] -= n; - } - /* @return total value - not 100% accurate, since it is not atomic. */ operator Type() const UNIV_NOTHROW { Type total = 0; diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index 4ca048a50d5..5b67fbe72b7 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 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 @@ -248,6 +249,9 @@ lock_wait_suspend_thread( slot = lock_wait_table_reserve_slot(thr, lock_wait_timeout); + lock_wait_mutex_exit(); + trx_mutex_exit(trx); + if (thr->lock_state == QUE_THR_LOCK_ROW) { srv_stats.n_lock_wait_count.inc(); srv_stats.n_lock_wait_current_count.inc(); @@ -259,19 +263,21 @@ lock_wait_suspend_thread( } } - lock_wait_mutex_exit(); - trx_mutex_exit(trx); - ulint lock_type = ULINT_UNDEFINED; - lock_mutex_enter(); - + /* The wait_lock can be cleared by another thread when the + lock is released. But the wait can only be initiated by the + current thread which owns the transaction. Only acquire the + mutex if the wait_lock is still active. */ if (const lock_t* wait_lock = trx->lock.wait_lock) { - lock_type = lock_get_type_low(wait_lock); + lock_mutex_enter(); + wait_lock = trx->lock.wait_lock; + if (wait_lock) { + lock_type = lock_get_type_low(wait_lock); + } + lock_mutex_exit(); } - lock_mutex_exit(); - had_dict_lock = trx->dict_operation_lock_mode; switch (had_dict_lock) { diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 68b4e1ecea5..c0c2b6fbabe 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -1452,11 +1452,10 @@ error_exit: que_thr_stop_for_mysql_no_error(thr, trx); if (UNIV_LIKELY(!(trx->fake_changes))) { - if (table->is_system_db) { - srv_stats.n_system_rows_inserted.add((size_t)trx->id, 1); + srv_stats.n_system_rows_inserted.inc(size_t(trx->id)); } else { - srv_stats.n_rows_inserted.add((size_t)trx->id, 1); + srv_stats.n_rows_inserted.inc(size_t(trx->id)); } if (prebuilt->clust_index_was_generated) { @@ -1858,17 +1857,15 @@ run_again: dict_table_n_rows_dec(prebuilt->table); if (table->is_system_db) { - srv_stats.n_system_rows_deleted.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_deleted.inc(size_t(trx->id)); } else { - srv_stats.n_rows_deleted.add((size_t)trx->id, 1); + srv_stats.n_rows_deleted.inc(size_t(trx->id)); } } else { if (table->is_system_db) { - srv_stats.n_system_rows_updated.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_updated.inc(size_t(trx->id)); } else { - srv_stats.n_rows_updated.add((size_t)trx->id, 1); + srv_stats.n_rows_updated.inc(size_t(trx->id)); } } @@ -2106,17 +2103,15 @@ run_again: dict_table_n_rows_dec(table); if (table->is_system_db) { - srv_stats.n_system_rows_deleted.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_deleted.inc(size_t(trx->id)); } else { - srv_stats.n_rows_deleted.add((size_t)trx->id, 1); + srv_stats.n_rows_deleted.inc(size_t(trx->id)); } } else { if (table->is_system_db) { - srv_stats.n_system_rows_updated.add( - (size_t)trx->id, 1); + srv_stats.n_system_rows_updated.inc(size_t(trx->id)); } else { - srv_stats.n_rows_updated.add((size_t)trx->id, 1); + srv_stats.n_rows_updated.inc(size_t(trx->id)); } } From fd0335686b050dc9ba091fe664aa5cd99bd20739 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 12 May 2017 11:35:57 +0200 Subject: [PATCH 095/148] MDEV-12651: change error code to ER_ILLEGAL_HA in rnd_pos (ha_connect.cc) --- storage/connect/ha_connect.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index d20fa05a463..a0dfbaceca0 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3998,7 +3998,7 @@ int ha_connect::rnd_pos(uchar *buf, uchar *pos) } else { PGLOBAL g = GetPlug((table) ? table->in_use : NULL, xp); strcpy(g->Message, "Not supported by this table type"); - my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + my_message(ER_ILLEGAL_HA, g->Message, MYF(0)); rc= HA_ERR_INTERNAL_ERROR; } // endif SetRecpos From 8417252b04404496c33cf049c1914a92653acd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 15 May 2017 10:26:42 +0300 Subject: [PATCH 096/148] Fix the Solaris compilation after MDEV-12674 simple_counter::add(): Add a type cast to the os_atomic_increment_ulint() call, because GCC would check the type compatibility even when the code branch is not being instantiated (atomic=false). On Solaris, os_atomic_increment_ulint() actually needs a compatible parameter type, and an error would be emitted due to an incompatible 64-bit type, for srv_stats.n_lock_wait_time.add(diff_time). --- storage/innobase/include/os0sync.h | 9 ++++++++- storage/xtradb/include/os0sync.h | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 54032b5ad31..bb225c53dfe 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -908,7 +908,14 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) simple_counter { compile_time_assert(!atomic || sizeof(Type) == sizeof(ulint)); if (atomic) { - return os_atomic_increment_ulint(&m_counter, i); + /* GCC would perform a type check in this code + also in case the template is instantiated with + simple_counter. + On Solaris, os_atomic_increment_ulint() maps + to atomic_add_long_nv(), which expects the + parameter to be correctly typed. */ + return os_atomic_increment_ulint( + reinterpret_cast(&m_counter), i); } else { return m_counter += i; } diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h index b152ab53e68..7bc591b2911 100644 --- a/storage/xtradb/include/os0sync.h +++ b/storage/xtradb/include/os0sync.h @@ -960,7 +960,14 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) simple_counter { compile_time_assert(!atomic || sizeof(Type) == sizeof(ulint)); if (atomic) { - return os_atomic_increment_ulint(&m_counter, i); + /* GCC would perform a type check in this code + also in case the template is instantiated with + simple_counter. + On Solaris, os_atomic_increment_ulint() maps + to atomic_add_long_nv(), which expects the + parameter to be correctly typed. */ + return os_atomic_increment_ulint( + reinterpret_cast(&m_counter), i); } else { return m_counter += i; } From 0af9818240a0745aca3fd94891664fe008de24fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 15 May 2017 17:17:16 +0300 Subject: [PATCH 097/148] 5.6.36 --- storage/innobase/btr/btr0sea.cc | 2 +- storage/innobase/buf/buf0buf.cc | 2 +- storage/innobase/buf/buf0dblwr.cc | 4 +- storage/innobase/buf/buf0dump.cc | 4 +- storage/innobase/buf/buf0flu.cc | 4 +- storage/innobase/dict/dict0boot.cc | 7 +- storage/innobase/dict/dict0stats.cc | 15 +- storage/innobase/dict/dict0stats_bg.cc | 4 +- storage/innobase/fil/fil0fil.cc | 20 ++- storage/innobase/handler/ha_innodb.cc | 7 +- storage/innobase/include/buf0dblwr.h | 4 +- storage/innobase/include/fil0fil.h | 14 +- storage/innobase/include/ha0ha.h | 6 +- storage/innobase/include/os0file.h | 134 ++++++++++---- storage/innobase/include/os0file.ic | 130 +++++++++++--- storage/innobase/include/row0mysql.h | 8 + storage/innobase/include/srv0srv.h | 9 +- storage/innobase/include/srv0start.h | 4 +- storage/innobase/include/trx0xa.h | 15 +- storage/innobase/include/univ.i | 10 +- storage/innobase/log/log0log.cc | 9 +- storage/innobase/log/log0recv.cc | 4 +- storage/innobase/os/os0file.cc | 128 +++++++------- storage/innobase/row/row0log.cc | 17 +- storage/innobase/row/row0merge.cc | 35 ++-- storage/innobase/row/row0sel.cc | 235 ++++++++++++++++++++----- storage/innobase/srv/srv0srv.cc | 26 ++- storage/innobase/srv/srv0start.cc | 66 +++++-- storage/innobase/trx/trx0purge.cc | 5 +- storage/innobase/trx/trx0roll.cc | 4 +- storage/innobase/trx/trx0sys.cc | 18 +- 31 files changed, 658 insertions(+), 292 deletions(-) diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index dd28f50f4f6..01f03b2eaf7 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -175,7 +175,7 @@ btr_search_sys_create( btr_search_sys = (btr_search_sys_t*) mem_alloc(sizeof(btr_search_sys_t)); - btr_search_sys->hash_index = ha_create(hash_size, 0, + btr_search_sys->hash_index = ib_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0); #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG btr_search_sys->hash_index->adaptive = TRUE; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 6f206918212..fa73e80b358 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1366,7 +1366,7 @@ buf_pool_init_instance( ut_a(srv_n_page_hash_locks != 0); ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS); - buf_pool->page_hash = ha_create(2 * buf_pool->curr_size, + buf_pool->page_hash = ib_create(2 * buf_pool->curr_size, srv_n_page_hash_locks, MEM_HEAP_FOR_PAGE_HASH, SYNC_BUF_PAGE_HASH); diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 62222993622..a752c3dfda5 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -355,7 +355,7 @@ recovery, this function loads the pages from double write buffer into memory. */ void buf_dblwr_init_or_load_pages( /*=========================*/ - os_file_t file, + pfs_os_file_t file, char* path, bool load_corrupt_pages) { diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index ed27a70307d..6c830205e2b 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2017, 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 @@ -597,6 +597,7 @@ DECLARE_THREAD(buf_dump_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_ad(!srv_read_only_mode); srv_buf_dump_thread_active = TRUE; @@ -632,6 +633,7 @@ DECLARE_THREAD(buf_dump_thread)( srv_buf_dump_thread_active = FALSE; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 1cdd1610c4f..6550f916805 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -2388,6 +2388,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ulint next_loop_time = ut_time_ms() + 1000; ulint n_flushed = 0; ulint last_activity = srv_get_activity_count(); @@ -2506,6 +2507,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( thread_exit: buf_page_cleaner_is_active = FALSE; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 1a1dd29a202..7873da30207 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -454,7 +454,10 @@ dict_boot(void) dberr_t err = DB_SUCCESS; - if (srv_read_only_mode && !ibuf_is_empty()) { + /** If innodb_force_recovery is set to 6 then allow + the server to start even though ibuf is not empty. */ + if (srv_force_recovery != SRV_FORCE_NO_LOG_REDO + && srv_read_only_mode && !ibuf_is_empty()) { ib_logf(IB_LOG_LEVEL_ERROR, "Change buffer must be empty when --innodb-read-only " diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index b0ba98308be..55a26268579 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2017, 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 @@ -690,6 +690,9 @@ dict_stats_copy( && (src_idx = dict_table_get_next_index(src_idx)))) { if (dict_stats_should_ignore_index(dst_idx)) { + if (!(dst_idx->type & DICT_FTS)) { + dict_stats_empty_index(dst_idx); + } continue; } @@ -1096,10 +1099,10 @@ dict_stats_analyze_index_level( leaf-level delete marks because delete marks on non-leaf level do not make sense. */ - if (level == 0 && srv_stats_include_delete_marked? 0: + if (level == 0 && (srv_stats_include_delete_marked ? 0: rec_get_deleted_flag( rec, - page_is_comp(btr_pcur_get_page(&pcur)))) { + page_is_comp(btr_pcur_get_page(&pcur))))) { if (rec_is_last_on_page && !prev_rec_is_copied @@ -3229,12 +3232,6 @@ dict_stats_update( dict_table_stats_lock(table, RW_X_LATCH); - /* Initialize all stats to dummy values before - copying because dict_stats_table_clone_create() does - skip corrupted indexes so our dummy object 't' may - have less indexes than the real object 'table'. */ - dict_stats_empty_table(table); - dict_stats_copy(table, t); dict_stats_assert_initialized(table); diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 6f01c379776..975c8a50803 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, 2017, 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 @@ -334,6 +334,7 @@ DECLARE_THREAD(dict_stats_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_a(!srv_read_only_mode); srv_dict_stats_thread_active = TRUE; @@ -359,6 +360,7 @@ DECLARE_THREAD(dict_stats_thread)( srv_dict_stats_thread_active = FALSE; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit instead of return(). */ os_thread_exit(NULL); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 5e1a9d6c05e..20c6cc6201e 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -146,7 +146,7 @@ struct fil_node_t { belongs */ char* name; /*!< path to the file */ ibool open; /*!< TRUE if file open */ - os_file_t handle; /*!< OS handle to the file, if file open */ + pfs_os_file_t handle; /*!< OS handle to the file, if file open */ os_event_t sync_event;/*!< Condition event to group and serialize calls to fsync */ ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw @@ -316,7 +316,8 @@ initialized. */ static fil_system_t* fil_system = NULL; /** Determine if (i) is a user tablespace id or not. */ -# define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open) +# define fil_is_user_tablespace_id(i) (i != 0 \ + && !srv_is_undo_tablespace(i)) /** Determine if user has explicitly disabled fsync(). */ #ifndef __WIN__ @@ -2025,7 +2026,7 @@ UNIV_INTERN const char* fil_read_first_page( /*================*/ - os_file_t data_file, /*!< in: open data file */ + pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ @@ -3360,7 +3361,7 @@ fil_open_linked_file( /*===============*/ const char* tablename, /*!< in: database/tablename */ char** remote_filepath,/*!< out: remote filepath */ - os_file_t* remote_file) /*!< out: remote file handle */ + pfs_os_file_t* remote_file) /*!< out: remote file handle */ { ibool success; @@ -3420,7 +3421,8 @@ fil_create_new_single_table_tablespace( tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE */ { - os_file_t file; + pfs_os_file_t file; + ibool ret; dberr_t err; byte* buf2; @@ -5862,7 +5864,7 @@ fil_flush( { fil_space_t* space; fil_node_t* node; - os_file_t file; + pfs_os_file_t file; mutex_enter(&fil_system->mutex); @@ -6224,7 +6226,7 @@ fil_buf_block_init( } struct fil_iterator_t { - os_file_t file; /*!< File handle */ + pfs_os_file_t file; /*!< File handle */ const char* filepath; /*!< File path name */ os_offset_t start; /*!< From where to start */ os_offset_t end; /*!< Where to stop */ @@ -6359,7 +6361,7 @@ fil_tablespace_iterate( PageCallback& callback) { dberr_t err; - os_file_t file; + pfs_os_file_t file; char* filepath; ut_a(n_io_buffers > 0); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 41c767a4bfc..7843c328bc8 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -5052,6 +5052,8 @@ table_opened: prebuilt->default_rec = table->s->default_values; ut_ad(prebuilt->default_rec); + prebuilt->mysql_handler = this; + /* Looks like MySQL-3.23 sometimes has primary key number != 0 */ primary_key = table->s->primary_key; key_used_on_scan = primary_key; @@ -10168,7 +10170,8 @@ ha_innobase::delete_table( extension, in contrast to ::create */ normalize_table_name(norm_name, name); - if (srv_read_only_mode) { + if (srv_read_only_mode + || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) { DBUG_RETURN(HA_ERR_TABLE_READONLY); } else if (row_is_magic_monitor_table(norm_name) && check_global_access(thd, PROCESS_ACL)) { diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h index a62a6400d97..18e124b7437 100644 --- a/storage/innobase/include/buf0dblwr.h +++ b/storage/innobase/include/buf0dblwr.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -55,7 +55,7 @@ recovery, this function loads the pages from double write buffer into memory. */ void buf_dblwr_init_or_load_pages( /*=========================*/ - os_file_t file, + pfs_os_file_t file, char* path, bool load_corrupt_pages); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 4d2913846b5..5806863f926 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -181,7 +181,7 @@ struct fsp_open_info { ibool success; /*!< Has the tablespace been opened? */ const char* check_msg; /*!< fil_check_first_page() message */ ibool valid; /*!< Is the tablespace valid? */ - os_file_t file; /*!< File handle */ + pfs_os_file_t file; /*!< File handle */ char* filepath; /*!< File path to open */ lsn_t lsn; /*!< Flushed LSN from header page */ ulint id; /*!< Space ID */ @@ -384,7 +384,7 @@ UNIV_INTERN const char* fil_read_first_page( /*================*/ - os_file_t data_file, /*!< in: open data file */ + pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ @@ -902,12 +902,12 @@ struct PageCallback { Called for every page in the tablespace. If the page was not updated then its state must be set to BUF_PAGE_NOT_USED. For compressed tables the page descriptor memory will be at offset: - block->frame + UNIV_PAGE_SIZE; + block->frame + UNIV_PAGE_SIZE; @param offset - physical offset within the file @param block - block read from file, note it is not from the buffer pool @retval DB_SUCCESS or error code. */ virtual dberr_t operator()( - os_offset_t offset, + os_offset_t offset, buf_block_t* block) UNIV_NOTHROW = 0; /** @@ -915,7 +915,7 @@ struct PageCallback { to open it for the file that is being iterated over. @param filename - then physical name of the tablespace file. @param file - OS file handle */ - void set_file(const char* filename, os_file_t file) UNIV_NOTHROW + void set_file(const char* filename, pfs_os_file_t file) UNIV_NOTHROW { m_file = file; m_filepath = filename; @@ -951,7 +951,7 @@ struct PageCallback { ulint m_page_size; /** File handle to the tablespace */ - os_file_t m_file; + pfs_os_file_t m_file; /** Physical file path. */ const char* m_filepath; diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h index 7351b407e8c..58eb581e76a 100644 --- a/storage/innobase/include/ha0ha.h +++ b/storage/innobase/include/ha0ha.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -107,7 +107,7 @@ chosen to be a slightly bigger prime number. @param level in: level of the mutexes in the latching order @param n_m in: number of mutexes to protect the hash table; must be a power of 2, or 0 */ -# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type) +# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type) #else /* UNIV_SYNC_DEBUG */ /** Creates a hash table. @return own: created table @@ -116,7 +116,7 @@ chosen to be a slightly bigger prime number. @param level in: level of the mutexes in the latching order @param n_m in: number of mutexes to protect the hash table; must be a power of 2, or 0 */ -# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type) +# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type) #endif /* UNIV_SYNC_DEBUG */ /*************************************************************//** diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index f047302c60c..76a389f9051 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -1,6 +1,6 @@ /*********************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted @@ -89,6 +89,16 @@ typedef int os_file_t; # define OS_FILE_FROM_FD(fd) fd #endif +/*Common file descriptor for file IO instrumentation with PFS +on windows and other platforms */ +struct pfs_os_file_t +{ + os_file_t m_file; +#ifdef UNIV_PFS_IO + struct PSI_file *m_psi; +#endif +}; + /** Umask for creating files */ extern ulint os_innodb_umask; @@ -216,6 +226,8 @@ extern mysql_pfs_key_t innodb_file_temp_key; various file I/O operations with performance schema. 1) register_pfs_file_open_begin() and register_pfs_file_open_end() are used to register file creation, opening, closing and renaming. +2) register_pfs_file_rename_begin() and register_pfs_file_rename_end() +are used to register file renaming 2) register_pfs_file_io_begin() and register_pfs_file_io_end() are used to register actual file read, write and flush 3) register_pfs_file_close_begin() and register_pfs_file_close_end() @@ -225,17 +237,30 @@ are used to register file deletion operations*/ do { \ locker = PSI_FILE_CALL(get_thread_file_name_locker)( \ state, key, op, name, &locker); \ - if (UNIV_LIKELY(locker != NULL)) { \ + if (locker != NULL) { \ PSI_FILE_CALL(start_file_open_wait)( \ locker, src_file, src_line); \ } \ } while (0) -# define register_pfs_file_open_end(locker, file) \ +# define register_pfs_file_open_end(locker, file, result) \ do { \ - if (UNIV_LIKELY(locker != NULL)) { \ - PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(\ - locker, file); \ + if (locker != NULL) { \ + file.m_psi = PSI_FILE_CALL( \ + end_file_open_wait)( \ + locker, result); \ + } \ +} while (0) + +# define register_pfs_file_rename_begin(state, locker, key, op, name, \ + src_file, src_line) \ + register_pfs_file_open_begin(state, locker, key, op, name, \ + src_file, src_line) \ + +# define register_pfs_file_rename_end(locker, result) \ +do { \ + if (locker != NULL) { \ + PSI_FILE_CALL(end_file_open_wait)(locker, result); \ } \ } while (0) @@ -261,9 +286,9 @@ do { \ # define register_pfs_file_io_begin(state, locker, file, count, op, \ src_file, src_line) \ do { \ - locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( \ - state, file, op); \ - if (UNIV_LIKELY(locker != NULL)) { \ + locker = PSI_FILE_CALL(get_thread_file_stream_locker)( \ + state, file.m_psi, op); \ + if (locker != NULL) { \ PSI_FILE_CALL(start_file_wait)( \ locker, count, src_file, src_line); \ } \ @@ -271,7 +296,7 @@ do { \ # define register_pfs_file_io_end(locker, count) \ do { \ - if (UNIV_LIKELY(locker != NULL)) { \ + if (locker != NULL) { \ PSI_FILE_CALL(end_file_wait)(locker, count); \ } \ } while (0) @@ -289,7 +314,9 @@ os_file_rename os_aio os_file_read os_file_read_no_error_handling +os_file_read_no_error_handling_int_fd os_file_write +os_file_write_int_fd The wrapper functions have the prefix of "innodb_". */ @@ -307,7 +334,7 @@ The wrapper functions have the prefix of "innodb_". */ pfs_os_file_create_simple_no_error_handling_func( \ key, name, create_mode, access, success, __FILE__, __LINE__) -# define os_file_close(file) \ +# define os_file_close_pfs(file) \ pfs_os_file_close_func(file, __FILE__, __LINE__) # define os_aio(type, mode, name, file, buf, offset, \ @@ -315,18 +342,27 @@ The wrapper functions have the prefix of "innodb_". */ pfs_os_aio_func(type, mode, name, file, buf, offset, \ n, message1, message2, __FILE__, __LINE__) -# define os_file_read(file, buf, offset, n) \ +# define os_file_read_pfs(file, buf, offset, n) \ pfs_os_file_read_func(file, buf, offset, n, __FILE__, __LINE__) # define os_file_read_no_error_handling(file, buf, offset, n) \ pfs_os_file_read_no_error_handling_func(file, buf, offset, n, \ __FILE__, __LINE__) -# define os_file_write(name, file, buf, offset, n) \ +# define os_file_read_no_error_handling_int_fd( \ + file, buf, offset, n) \ + pfs_os_file_read_no_error_handling_int_fd_func( \ + file, buf, offset, n, __FILE__, __LINE__) + +# define os_file_write_pfs(name, file, buf, offset, n) \ pfs_os_file_write_func(name, file, buf, offset, \ n, __FILE__, __LINE__) -# define os_file_flush(file) \ +# define os_file_write_int_fd(name, file, buf, offset, n) \ + pfs_os_file_write_int_fd_func(name, file, buf, offset, \ + n, __FILE__, __LINE__) + +# define os_file_flush_pfs(file) \ pfs_os_file_flush_func(file, __FILE__, __LINE__) # define os_file_rename(key, oldpath, newpath) \ @@ -352,22 +388,29 @@ to original un-instrumented file I/O APIs */ os_file_create_simple_no_error_handling_func( \ name, create_mode, access, success) -# define os_file_close(file) os_file_close_func(file) +# define os_file_close_pfs(file) \ + os_file_close_func(file) # define os_aio(type, mode, name, file, buf, offset, n, message1, message2) \ os_aio_func(type, mode, name, file, buf, offset, n, \ message1, message2) -# define os_file_read(file, buf, offset, n) \ +# define os_file_read_pfs(file, buf, offset, n) \ os_file_read_func(file, buf, offset, n) # define os_file_read_no_error_handling(file, buf, offset, n) \ os_file_read_no_error_handling_func(file, buf, offset, n) +# define os_file_read_no_error_handling_int_fd( \ + file, buf, offset, n) \ + os_file_read_no_error_handling_func(file, buf, offset, n) -# define os_file_write(name, file, buf, offset, n) \ +# define os_file_write_int_fd(name, file, buf, offset, n) \ + os_file_write_func(name, file, buf, offset, n) +# define os_file_write_pfs(name, file, buf, offset, n) \ os_file_write_func(name, file, buf, offset, n) -# define os_file_flush(file) os_file_flush_func(file) + +# define os_file_flush_pfs(file) os_file_flush_func(file) # define os_file_rename(key, oldpath, newpath) \ os_file_rename_func(oldpath, newpath) @@ -379,6 +422,33 @@ to original un-instrumented file I/O APIs */ #endif /* UNIV_PFS_IO */ +#ifdef UNIV_PFS_IO + #define os_file_close(file) os_file_close_pfs(file) +#else + #define os_file_close(file) os_file_close_pfs((file).m_file) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_read(file, buf, offset, n) \ + os_file_read_pfs(file, buf, offset, n) +#else + #define os_file_read(file, buf, offset, n) \ + os_file_read_pfs(file.m_file, buf, offset, n) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_flush(file) os_file_flush_pfs(file) +#else + #define os_file_flush(file) os_file_flush_pfs(file.m_file) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_write(name, file, buf, offset, n) \ + os_file_write_pfs(name, file, buf, offset, n) +#else + #define os_file_write(name, file, buf, offset, n) \ + os_file_write_pfs(name, file.m_file, buf, offset, n) +#endif /* File types for directory entry data type */ enum os_file_type_t { @@ -518,7 +588,7 @@ A simple function to open or create a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_simple_no_error_handling_func( /*=========================================*/ const char* name, /*!< in: name of the file or path as a @@ -548,7 +618,7 @@ Opens an existing file or creates a new. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_func( /*================*/ const char* name, /*!< in: name of the file or path as a @@ -617,7 +687,7 @@ os_file_create_simple() which opens or creates a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_func( /*===========================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -640,7 +710,7 @@ monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_no_error_handling_func( /*=============================================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -664,7 +734,7 @@ Add instrumentation to monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_func( /*====================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -693,7 +763,7 @@ UNIV_INLINE ibool pfs_os_file_close_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line);/*!< in: line where the func invoked */ /*******************************************************************//** @@ -706,7 +776,7 @@ UNIV_INLINE ibool pfs_os_file_read_func( /*==================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -724,7 +794,7 @@ UNIV_INLINE ibool pfs_os_file_read_no_error_handling_func( /*====================================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -745,7 +815,7 @@ pfs_os_aio_func( ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ @@ -772,7 +842,7 @@ pfs_os_file_write_func( /*===================*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ const void* buf, /*!< in: buffer from which to write */ os_offset_t offset, /*!< in: file offset where to write */ ulint n, /*!< in: number of bytes to write */ @@ -789,7 +859,7 @@ UNIV_INLINE ibool pfs_os_file_flush_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line);/*!< in: line where the func invoked */ @@ -860,7 +930,7 @@ UNIV_INTERN os_offset_t os_file_get_size( /*=============*/ - os_file_t file) /*!< in: handle to a file */ + pfs_os_file_t file) /*!< in: handle to a file */ MY_ATTRIBUTE((warn_unused_result)); /***********************************************************************//** Write the specified number of zeros to a newly created file. @@ -871,7 +941,7 @@ os_file_set_size( /*=============*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ os_offset_t size) /*!< in: file size */ MY_ATTRIBUTE((nonnull, warn_unused_result)); /***********************************************************************//** @@ -1109,7 +1179,7 @@ os_aio_func( caution! */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ diff --git a/storage/innobase/include/os0file.ic b/storage/innobase/include/os0file.ic index defd8204ba3..31d5cc1d6a2 100644 --- a/storage/innobase/include/os0file.ic +++ b/storage/innobase/include/os0file.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2010, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2010, 2017, 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 @@ -34,7 +34,7 @@ os_file_create_simple() which opens or creates a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_func( /*===========================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -47,7 +47,7 @@ pfs_os_file_create_simple_func( const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { - os_file_t file; + pfs_os_file_t file; struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; @@ -58,11 +58,13 @@ pfs_os_file_create_simple_func( : PSI_FILE_OPEN), name, src_file, src_line); - file = os_file_create_simple_func(name, create_mode, + file.m_file = os_file_create_simple_func(name, create_mode, access_type, success); + file.m_psi = NULL; - /* Regsiter the returning "file" value with the system */ - register_pfs_file_open_end(locker, file); + /* Regsiter psi value for the file */ + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); return(file); } @@ -76,7 +78,7 @@ monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_no_error_handling_func( /*=============================================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -91,7 +93,7 @@ pfs_os_file_create_simple_no_error_handling_func( const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { - os_file_t file; + pfs_os_file_t file; struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; @@ -104,8 +106,10 @@ pfs_os_file_create_simple_no_error_handling_func( file = os_file_create_simple_no_error_handling_func( name, create_mode, access_type, success); + file.m_psi = NULL; - register_pfs_file_open_end(locker, file); + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); return(file); } @@ -118,7 +122,7 @@ Add instrumentation to monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_func( /*====================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -137,7 +141,7 @@ pfs_os_file_create_func( const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { - os_file_t file; + pfs_os_file_t file; struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; @@ -149,8 +153,10 @@ pfs_os_file_create_func( name, src_file, src_line); file = os_file_create_func(name, create_mode, purpose, type, success); + file.m_psi = NULL; - register_pfs_file_open_end(locker, file); + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); return(file); } @@ -164,7 +170,7 @@ UNIV_INLINE ibool pfs_os_file_close_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { @@ -176,7 +182,7 @@ pfs_os_file_close_func( register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE, src_file, src_line); - result = os_file_close_func(file); + result = os_file_close_func(file.m_file); register_pfs_file_io_end(locker, 0); @@ -197,7 +203,7 @@ pfs_os_aio_func( ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ @@ -242,7 +248,7 @@ UNIV_INLINE ibool pfs_os_file_read_func( /*==================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -256,7 +262,7 @@ pfs_os_file_read_func( register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ, src_file, src_line); - result = os_file_read_func(file, buf, offset, n); + result = os_file_read_func(file.m_file, buf, offset, n); register_pfs_file_io_end(locker, n); @@ -275,7 +281,7 @@ UNIV_INLINE ibool pfs_os_file_read_no_error_handling_func( /*====================================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -289,13 +295,50 @@ pfs_os_file_read_no_error_handling_func( register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ, src_file, src_line); - result = os_file_read_no_error_handling_func(file, buf, offset, n); + result = os_file_read_no_error_handling_func(file.m_file, buf, offset, n); register_pfs_file_io_end(locker, n); return(result); } +/** NOTE! Please use the corresponding macro +os_file_read_no_error_handling_int_fd(), not directly this function! +This is the performance schema instrumented wrapper function for +os_file_read_no_error_handling_int_fd_func() which requests a +synchronous read operation. +@return TRUE if request was successful, FALSE if fail */ +UNIV_INLINE +ibool +pfs_os_file_read_no_error_handling_int_fd_func( + int file, /*!< in: handle to a file */ + void* buf, /*!< in: buffer where to read */ + os_offset_t offset, /*!< in: file offset where to read */ + ulint n, /*!< in: number of bytes to read */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line)/*!< in: line where the func invoked */ +{ + + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &state, file, PSI_FILE_READ); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, n, + __FILE__, __LINE__); + } + ibool result = os_file_read_no_error_handling_func( + OS_FILE_FROM_FD(file), buf, offset, n); + + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, n); + } + + return(result); +} + /*******************************************************************//** NOTE! Please use the corresponding macro os_file_write(), not directly this function! @@ -308,7 +351,7 @@ pfs_os_file_write_func( /*===================*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ const void* buf, /*!< in: buffer from which to write */ os_offset_t offset, /*!< in: file offset where to write */ ulint n, /*!< in: number of bytes to write */ @@ -322,13 +365,50 @@ pfs_os_file_write_func( register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_WRITE, src_file, src_line); - result = os_file_write_func(name, file, buf, offset, n); + result = os_file_write_func(name, file.m_file, buf, offset, n); register_pfs_file_io_end(locker, n); return(result); } +/** NOTE! Please use the corresponding macro os_file_write(), not +directly this function! +This is the performance schema instrumented wrapper function for +os_file_write() which requests a synchronous write operation. +@return TRUE if request was successful, FALSE if fail */ +UNIV_INLINE +ibool +pfs_os_file_write_int_fd_func( + const char* name, /*!< in: name of the file or path as a + null-terminated string */ + int file, /*!< in: handle to a file */ + const void* buf, /*!< in: buffer from which to write */ + os_offset_t offset, /*!< in: file offset where to write */ + ulint n, /*!< in: number of bytes to write */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line)/*!< in: line where the func invoked */ +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &state, file, PSI_FILE_WRITE); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, n, + __FILE__, __LINE__); + } + ibool result = os_file_write_func( + name, OS_FILE_FROM_FD(file), buf, offset, n); + + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, n); + } + + return(result); +} + /***********************************************************************//** NOTE! Please use the corresponding macro os_file_flush(), not directly this function! @@ -339,7 +419,7 @@ UNIV_INLINE ibool pfs_os_file_flush_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { @@ -349,7 +429,7 @@ pfs_os_file_flush_func( register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_SYNC, src_file, src_line); - result = os_file_flush_func(file); + result = os_file_flush_func(file.m_file); register_pfs_file_io_end(locker, 0); @@ -377,12 +457,12 @@ pfs_os_file_rename_func( struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; - register_pfs_file_open_begin(&state, locker, key, PSI_FILE_RENAME, newpath, + register_pfs_file_rename_begin(&state, locker, key, PSI_FILE_RENAME, newpath, src_file, src_line); result = os_file_rename_func(oldpath, newpath); - register_pfs_file_open_end(locker, 0); + register_pfs_file_rename_end(locker, 0); return(result); } diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index fc1846b76f3..d0c1bdaa585 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -652,6 +652,8 @@ struct mysql_row_templ_t { #define ROW_PREBUILT_ALLOCATED 78540783 #define ROW_PREBUILT_FREED 26423527 +class ha_innobase; + /** A struct for (sometimes lazily) prebuilt structures in an Innobase table handle used within MySQL; these are used to save CPU time. */ @@ -879,6 +881,12 @@ struct row_prebuilt_t { to InnoDB format.*/ uint srch_key_val_len; /*!< Size of search key */ + /** MySQL handler object. */ + ha_innobase* mysql_handler; + + /** True if exceeded the end_range while filling the prefetch cache. */ + bool end_range; + }; /** Callback for row_mysql_sys_index_iterate() */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 042ced75d10..7d701536341 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. @@ -785,6 +785,13 @@ void srv_purge_wakeup(void); /*==================*/ +/** Check whether given space id is undo tablespace id +@param[in] space_id space id to check +@return true if it is undo tablespace else false. */ +bool +srv_is_undo_tablespace( + ulint space_id); + /** Status variables to be passed to MySQL */ struct export_var_t{ ulint innodb_data_pending_reads; /*!< Pending reads */ diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index 963b767f0fb..a60776a4665 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -139,6 +139,8 @@ extern ibool srv_startup_is_before_trx_rollback_phase; /** TRUE if a raw partition is in use */ extern ibool srv_start_raw_disk_in_use; +/** Undo tablespaces starts with space_id. */ +extern ulint srv_undo_space_id_start; /** Shutdown state */ enum srv_shutdown_state { diff --git a/storage/innobase/include/trx0xa.h b/storage/innobase/include/trx0xa.h index 7caddfb7ba4..255431293f5 100644 --- a/storage/innobase/include/trx0xa.h +++ b/storage/innobase/include/trx0xa.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,6 +24,8 @@ this program; if not, write to the Free Software Foundation, Inc., #ifndef XA_H #define XA_H +#include "xa.h" + /* * Transaction branch identification: XID and NULLXID: */ @@ -35,17 +37,6 @@ this program; if not, write to the Free Software Foundation, Inc., #define MAXGTRIDSIZE 64 /*!< maximum size in bytes of gtrid */ #define MAXBQUALSIZE 64 /*!< maximum size in bytes of bqual */ -/** X/Open XA distributed transaction identifier */ -struct xid_t { - long formatID; /*!< format identifier; -1 - means that the XID is null */ - long gtrid_length; /*!< value from 1 through 64 */ - long bqual_length; /*!< value from 1 through 64 */ - char data[XIDDATASIZE]; /*!< distributed transaction - identifier */ -}; -/** X/Open XA distributed transaction identifier */ -typedef struct xid_t XID; #endif /** X/Open XA distributed transaction status codes */ /* @{ */ diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index dfb59673f0b..5d3dcafb322 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -133,14 +133,8 @@ HAVE_PSI_INTERFACE is defined. */ #if defined HAVE_PSI_INTERFACE && !defined UNIV_HOTBACKUP # define UNIV_PFS_MUTEX # define UNIV_PFS_RWLOCK -/* For I/O instrumentation, performance schema rely -on a native descriptor to identify the file, this -descriptor could conflict with our OS level descriptor. -Disable IO instrumentation on Windows until this is -resolved */ -# ifndef __WIN__ -# define UNIV_PFS_IO -# endif + +# define UNIV_PFS_IO # define UNIV_PFS_THREAD /* There are mutexes/rwlocks that we want to exclude from diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 8ff8e39d352..51b057ec09a 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -3406,7 +3406,12 @@ loop: lsn = log_sys->lsn; - if (lsn != log_sys->last_checkpoint_lsn + const bool is_last = ((srv_force_recovery == SRV_FORCE_NO_LOG_REDO + && lsn == log_sys->last_checkpoint_lsn + + LOG_BLOCK_HDR_SIZE) + || lsn == log_sys->last_checkpoint_lsn); + + if (!is_last #ifdef UNIV_LOG_ARCHIVE || (srv_log_archive_on && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 85f4f6ea671..69d74a99ab5 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -332,6 +332,7 @@ DECLARE_THREAD(recv_writer_thread)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_ad(!srv_read_only_mode); #ifdef UNIV_PFS_THREAD @@ -364,6 +365,7 @@ DECLARE_THREAD(recv_writer_thread)( recv_writer_thread_active = false; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 46a7b801521..dbd30c3d658 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -1,6 +1,6 @@ /*********************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted @@ -163,7 +163,7 @@ struct os_aio_slot_t{ byte* buf; /*!< buffer used in i/o */ ulint type; /*!< OS_FILE_READ or OS_FILE_WRITE */ os_offset_t offset; /*!< file offset in bytes */ - os_file_t file; /*!< file where to read or write */ + pfs_os_file_t file; /*!< file where to read or write */ const char* name; /*!< file name or path */ ibool io_already_done;/*!< used only in simulated aio: TRUE if the physical i/o already @@ -1306,7 +1306,7 @@ A simple function to open or create a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_simple_no_error_handling_func( /*=========================================*/ const char* name, /*!< in: name of the file or path as a @@ -1318,7 +1318,7 @@ os_file_create_simple_no_error_handling_func( used by a backup program reading the file */ ibool* success)/*!< out: TRUE if succeed, FALSE if error */ { - os_file_t file; + pfs_os_file_t file; *success = FALSE; #ifdef __WIN__ @@ -1326,7 +1326,6 @@ os_file_create_simple_no_error_handling_func( DWORD create_flag; DWORD attributes = 0; DWORD share_mode = FILE_SHARE_READ; - ut_a(name); ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); @@ -1343,8 +1342,8 @@ os_file_create_simple_no_error_handling_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown file create mode (%lu) for file '%s'", create_mode, name); - - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); } if (access_type == OS_FILE_READ_ONLY) { @@ -1367,11 +1366,11 @@ os_file_create_simple_no_error_handling_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown file access type (%lu) for file '%s'", access_type, name); - - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); } - file = CreateFile((LPCTSTR) name, + file.m_file = CreateFile((LPCTSTR) name, access, share_mode, NULL, // Security attributes @@ -1379,11 +1378,10 @@ os_file_create_simple_no_error_handling_func( attributes, NULL); // No template file - *success = (file != INVALID_HANDLE_VALUE); + *success = (file.m_file != INVALID_HANDLE_VALUE); #else /* __WIN__ */ int create_flag; const char* mode_str = NULL; - ut_a(name); ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); @@ -1425,13 +1423,13 @@ os_file_create_simple_no_error_handling_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown file create mode (%lu) for file '%s'", create_mode, name); - - return((os_file_t) -1); + file.m_file = -1; + return(file); } - file = ::open(name, create_flag, os_innodb_umask); + file.m_file = ::open(name, create_flag, os_innodb_umask); - *success = file == -1 ? FALSE : TRUE; + *success = file.m_file == -1 ? FALSE : TRUE; /* This function is always called for data files, we should disable OS caching (O_DIRECT) here as we do in os_file_create_func(), so @@ -1441,18 +1439,18 @@ os_file_create_simple_no_error_handling_func( && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) { - os_file_set_nocache(file, name, mode_str); + os_file_set_nocache(file.m_file, name, mode_str); } #ifdef USE_FILE_LOCK if (!srv_read_only_mode && *success && access_type == OS_FILE_READ_WRITE - && os_file_lock(file, name)) { + && os_file_lock(file.m_file, name)) { *success = FALSE; - close(file); - file = -1; + close(file.m_file); + file.m_file = -1; } #endif /* USE_FILE_LOCK */ @@ -1527,7 +1525,7 @@ Opens an existing file or creates a new. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_func( /*================*/ const char* name, /*!< in: name of the file or path as a @@ -1543,24 +1541,25 @@ os_file_create_func( ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */ ibool* success)/*!< out: TRUE if succeed, FALSE if error */ { - os_file_t file; + pfs_os_file_t file; ibool retry; ibool on_error_no_exit; ibool on_error_silent; - #ifdef __WIN__ DBUG_EXECUTE_IF( "ib_create_table_fail_disk_full", *success = FALSE; SetLastError(ERROR_DISK_FULL); - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); ); #else /* __WIN__ */ DBUG_EXECUTE_IF( "ib_create_table_fail_disk_full", *success = FALSE; errno = ENOSPC; - return((os_file_t) -1); + file.m_file = -1; + return(file); ); #endif /* __WIN__ */ @@ -1611,7 +1610,8 @@ os_file_create_func( "Unknown file create mode (%lu) for file '%s'", create_mode, name); - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); } DWORD attributes = 0; @@ -1636,8 +1636,8 @@ os_file_create_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown purpose flag (%lu) while opening file '%s'", purpose, name); - - return((os_file_t)(-1)); + file.m_file = (os_file_t)-1; + return(file); } #ifdef UNIV_NON_BUFFERED_IO @@ -1664,11 +1664,11 @@ os_file_create_func( do { /* Use default security attributes and no template file. */ - file = CreateFile( + file.m_file = CreateFile( (LPCTSTR) name, access, share_mode, NULL, create_flag, attributes, NULL); - if (file == INVALID_HANDLE_VALUE) { + if (file.m_file == INVALID_HANDLE_VALUE) { const char* operation; operation = (create_mode == OS_FILE_CREATE @@ -1693,7 +1693,6 @@ os_file_create_func( #else /* __WIN__ */ int create_flag; const char* mode_str = NULL; - on_error_no_exit = create_mode & OS_FILE_ON_ERROR_NO_EXIT ? TRUE : FALSE; on_error_silent = create_mode & OS_FILE_ON_ERROR_SILENT @@ -1731,7 +1730,8 @@ os_file_create_func( "Unknown file create mode (%lu) for file '%s'", create_mode, name); - return((os_file_t) -1); + file.m_file = -1; + return(file); } ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE); @@ -1751,9 +1751,9 @@ os_file_create_func( #endif /* O_SYNC */ do { - file = ::open(name, create_flag, os_innodb_umask); + file.m_file = ::open(name, create_flag, os_innodb_umask); - if (file == -1) { + if (file.m_file == -1) { const char* operation; operation = (create_mode == OS_FILE_CREATE @@ -1783,14 +1783,14 @@ os_file_create_func( && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) { - os_file_set_nocache(file, name, mode_str); + os_file_set_nocache(file.m_file, name, mode_str); } #ifdef USE_FILE_LOCK if (!srv_read_only_mode && *success && create_mode != OS_FILE_OPEN_RAW - && os_file_lock(file, name)) { + && os_file_lock(file.m_file, name)) { if (create_mode == OS_FILE_OPEN_RETRY) { @@ -1802,7 +1802,7 @@ os_file_create_func( for (int i = 0; i < 100; i++) { os_thread_sleep(1000000); - if (!os_file_lock(file, name)) { + if (!os_file_lock(file.m_file, name)) { *success = TRUE; return(file); } @@ -1813,8 +1813,8 @@ os_file_create_func( } *success = FALSE; - close(file); - file = -1; + close(file.m_file); + file.m_file = -1; } #endif /* USE_FILE_LOCK */ @@ -2086,14 +2086,14 @@ UNIV_INTERN os_offset_t os_file_get_size( /*=============*/ - os_file_t file) /*!< in: handle to a file */ + pfs_os_file_t file) /*!< in: handle to a file */ { #ifdef __WIN__ os_offset_t offset; DWORD high; DWORD low; - low = GetFileSize(file, &high); + low = GetFileSize(file.m_file, &high); if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) { return((os_offset_t) -1); @@ -2103,7 +2103,8 @@ os_file_get_size( return(offset); #else - return((os_offset_t) lseek(file, 0, SEEK_END)); + return((os_offset_t) lseek(file.m_file, 0, SEEK_END)); + #endif /* __WIN__ */ } @@ -2116,7 +2117,7 @@ os_file_set_size( /*=============*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ os_offset_t size) /*!< in: file size */ { os_offset_t current_size; @@ -4187,7 +4188,7 @@ os_aio_array_reserve_slot( the aio operation */ void* message2,/*!< in: message to be passed along with the aio operation */ - os_file_t file, /*!< in: file handle */ + pfs_os_file_t file, /*!< in: file handle */ const char* name, /*!< in: name of the file or path as a null-terminated string */ void* buf, /*!< in: buffer where to read or from which @@ -4307,10 +4308,10 @@ found: iocb = &slot->control; if (type == OS_FILE_READ) { - io_prep_pread(iocb, file, buf, len, aio_offset); + io_prep_pread(iocb, file.m_file, buf, len, aio_offset); } else { ut_a(type == OS_FILE_WRITE); - io_prep_pwrite(iocb, file, buf, len, aio_offset); + io_prep_pwrite(iocb, file.m_file, buf, len, aio_offset); } iocb->data = (void*) slot; @@ -4548,7 +4549,7 @@ os_aio_func( caution! */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ @@ -4573,8 +4574,7 @@ os_aio_func( ulint dummy_type; #endif /* WIN_ASYNC_IO */ ulint wake_later; - - ut_ad(file); + ut_ad(file.m_file); ut_ad(buf); ut_ad(n > 0); ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0); @@ -4606,13 +4606,11 @@ os_aio_func( and os_file_write_func() */ if (type == OS_FILE_READ) { - return(os_file_read_func(file, buf, offset, n)); + return(os_file_read_func(file.m_file, buf, offset, n)); } - ut_ad(!srv_read_only_mode); ut_a(type == OS_FILE_WRITE); - - return(os_file_write_func(name, file, buf, offset, n)); + return(os_file_write_func(name, file.m_file, buf, offset, n)); } try_again: @@ -4664,9 +4662,8 @@ try_again: os_n_file_reads++; os_bytes_read_since_printout += n; #ifdef WIN_ASYNC_IO - ret = ReadFile(file, buf, (DWORD) n, &len, + ret = ReadFile(file.m_file, buf, (DWORD) n, &len, &(slot->control)); - #elif defined(LINUX_NATIVE_AIO) if (!os_aio_linux_dispatch(array, slot)) { goto err_exit; @@ -4684,9 +4681,8 @@ try_again: if (srv_use_native_aio) { os_n_file_writes++; #ifdef WIN_ASYNC_IO - ret = WriteFile(file, buf, (DWORD) n, &len, + ret = WriteFile(file.m_file, buf, (DWORD) n, &len, &(slot->control)); - #elif defined(LINUX_NATIVE_AIO) if (!os_aio_linux_dispatch(array, slot)) { goto err_exit; @@ -4840,8 +4836,7 @@ os_aio_windows_handle( srv_set_io_thread_op_info( orig_seg, "get windows aio return value"); } - - ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE); + ret = GetOverlappedResult(slot->file.m_file, &(slot->control), &len, TRUE); *message1 = slot->message1; *message2 = slot->message2; @@ -4870,7 +4865,8 @@ os_aio_windows_handle( and os_file_write APIs, need to register with performance schema explicitly here. */ struct PSI_file_locker* locker = NULL; - register_pfs_file_io_begin(locker, slot->file, slot->len, + PSI_file_locker_state state; + register_pfs_file_io_begin(&state, locker, slot->file, slot->len, (slot->type == OS_FILE_WRITE) ? PSI_FILE_WRITE : PSI_FILE_READ, @@ -4881,16 +4877,14 @@ os_aio_windows_handle( switch (slot->type) { case OS_FILE_WRITE: - ret = WriteFile(slot->file, slot->buf, + ret = WriteFile(slot->file.m_file, slot->buf, (DWORD) slot->len, &len, &(slot->control)); - break; case OS_FILE_READ: - ret = ReadFile(slot->file, slot->buf, + ret = ReadFile(slot->file.m_file, slot->buf, (DWORD) slot->len, &len, &(slot->control)); - break; default: ut_error; @@ -4906,8 +4900,7 @@ os_aio_windows_handle( file where we also use async i/o: in Windows we must use the same wait mechanism as for async i/o */ - - ret = GetOverlappedResult(slot->file, + ret = GetOverlappedResult(slot->file.m_file, &(slot->control), &len, TRUE); } @@ -5354,12 +5347,11 @@ consecutive_loop: os_aio_slot_t* slot; slot = os_aio_array_get_nth_slot(array, i + segment * n); - if (slot->reserved && slot != aio_slot && slot->offset == aio_slot->offset + aio_slot->len && slot->type == aio_slot->type - && slot->file == aio_slot->file) { + && slot->file.m_file == aio_slot->file.m_file) { /* Found a consecutive i/o request */ diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 54183759e8d..4596e2fb951 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -363,9 +363,9 @@ row_log_online_op( goto err_exit; } - ret = os_file_write( + ret = os_file_write_int_fd( "(modification log)", - OS_FILE_FROM_FD(log->fd), + log->fd, log->tail.block, byte_offset, srv_sort_buf_size); log->tail.blocks++; if (!ret) { @@ -479,9 +479,9 @@ row_log_table_close_func( goto err_exit; } - ret = os_file_write( + ret = os_file_write_int_fd( "(modification log)", - OS_FILE_FROM_FD(log->fd), + log->fd, log->tail.block, byte_offset, srv_sort_buf_size); log->tail.blocks++; if (!ret) { @@ -2609,11 +2609,10 @@ all_done: goto func_exit; } - success = os_file_read_no_error_handling( - OS_FILE_FROM_FD(index->online_log->fd), + success = os_file_read_no_error_handling_int_fd( + index->online_log->fd, index->online_log->head.block, ofs, srv_sort_buf_size); - if (!success) { fprintf(stderr, "InnoDB: unable to read temporary file" " for table %s\n", index->table_name); @@ -3436,8 +3435,8 @@ all_done: goto func_exit; } - success = os_file_read_no_error_handling( - OS_FILE_FROM_FD(index->online_log->fd), + success = os_file_read_no_error_handling_int_fd( + index->online_log->fd, index->online_log->head.block, ofs, srv_sort_buf_size); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index f8bea67906c..2d63352feaf 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -869,8 +869,9 @@ row_merge_read( } #endif /* UNIV_DEBUG */ - success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, + success = os_file_read_no_error_handling_int_fd(fd, buf, ofs, srv_sort_buf_size); + #ifdef POSIX_FADV_DONTNEED /* Each block is read exactly once. Free up the file cache. */ posix_fadvise(fd, ofs, srv_sort_buf_size, POSIX_FADV_DONTNEED); @@ -904,7 +905,7 @@ row_merge_write( DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE);); - ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, ofs, buf_len); + ret = os_file_write_int_fd("(merge)", fd, buf, ofs, buf_len); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -3121,14 +3122,21 @@ row_merge_file_create_low( performance schema */ struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; - register_pfs_file_open_begin(&state, locker, innodb_file_temp_key, - PSI_FILE_OPEN, - "Innodb Merge Temp File", - __FILE__, __LINE__); + locker = PSI_FILE_CALL(get_thread_file_name_locker)( + &state, innodb_file_temp_key, PSI_FILE_OPEN, + "Innodb Merge Temp File", &locker); + if (locker != NULL) { + PSI_FILE_CALL(start_file_open_wait)(locker, + __FILE__, + __LINE__); + } #endif fd = innobase_mysql_tmpfile(path); #ifdef UNIV_PFS_IO - register_pfs_file_open_end(locker, fd); + if (locker != NULL) { + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)( + locker, fd); + } #endif if (fd < 0) { @@ -3175,15 +3183,20 @@ row_merge_file_destroy_low( #ifdef UNIV_PFS_IO struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; - register_pfs_file_io_begin(&state, locker, - fd, 0, PSI_FILE_CLOSE, - __FILE__, __LINE__); + locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &state, fd, PSI_FILE_CLOSE); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, 0, __FILE__, __LINE__); + } #endif if (fd >= 0) { close(fd); } #ifdef UNIV_PFS_IO - register_pfs_file_io_end(locker, 0); + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, 0); + } #endif } /*********************************************************************//** diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 42b1ab57630..c53c1154f60 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -61,6 +61,9 @@ Created 12/19/1997 Heikki Tuuri #include "my_sys.h" /* DEBUG_SYNC_C */ #include "my_compare.h" /* enum icp_result */ +#include "thr_lock.h" +#include "handler.h" +#include "ha_innodb.h" /* Maximum number of rows to prefetch; MySQL interface has another parameter */ #define SEL_MAX_N_PREFETCH 16 @@ -2743,34 +2746,43 @@ row_sel_field_store_in_mysql_format_func( #ifdef UNIV_DEBUG /** Convert a field from Innobase format to MySQL format. */ -# define row_sel_store_mysql_field(m,p,r,i,o,f,t) \ - row_sel_store_mysql_field_func(m,p,r,i,o,f,t) +# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \ + row_sel_store_mysql_field_func(m,p,r,i,o,f,t,c) #else /* UNIV_DEBUG */ /** Convert a field from Innobase format to MySQL format. */ -# define row_sel_store_mysql_field(m,p,r,i,o,f,t) \ - row_sel_store_mysql_field_func(m,p,r,o,f,t) +# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \ + row_sel_store_mysql_field_func(m,p,r,o,f,t,c) #endif /* UNIV_DEBUG */ -/**************************************************************//** -Convert a field in the Innobase format to a field in the MySQL format. */ +/** Convert a field in the Innobase format to a field in the MySQL format. +@param[out] mysql_rec record in the MySQL format +@param[in,out] prebuilt prebuilt struct +@param[in] rec InnoDB record; must be protected + by a page latch +@param[in] index index of rec +@param[in] offsets array returned by rec_get_offsets() +@param[in] field_no templ->rec_field_no or + templ->clust_rec_field_no + or templ->icp_rec_field_no + or sec field no if clust_templ_for_sec + is TRUE +@param[in] templ row template +@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index + but prebuilt template is in clustered + index format and used only for end + range comparison. */ static MY_ATTRIBUTE((warn_unused_result)) ibool row_sel_store_mysql_field_func( -/*===========================*/ - byte* mysql_rec, /*!< out: record in the - MySQL format */ - row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */ - const rec_t* rec, /*!< in: InnoDB record; - must be protected by - a page latch */ + byte* mysql_rec, + row_prebuilt_t* prebuilt, + const rec_t* rec, #ifdef UNIV_DEBUG - const dict_index_t* index, /*!< in: index of rec */ + const dict_index_t* index, #endif - const ulint* offsets, /*!< in: array returned by - rec_get_offsets() */ - ulint field_no, /*!< in: templ->rec_field_no or - templ->clust_rec_field_no or - templ->icp_rec_field_no */ - const mysql_row_templ_t*templ) /*!< in: row template */ + const ulint* offsets, + ulint field_no, + const mysql_row_templ_t*templ, + bool clust_templ_for_sec) { const byte* data; ulint len; @@ -2779,10 +2791,12 @@ row_sel_store_mysql_field_func( ut_ad(templ); ut_ad(templ >= prebuilt->mysql_template); ut_ad(templ < &prebuilt->mysql_template[prebuilt->n_template]); - ut_ad(field_no == templ->clust_rec_field_no + ut_ad(clust_templ_for_sec + || field_no == templ->clust_rec_field_no || field_no == templ->rec_field_no || field_no == templ->icp_rec_field_no); - ut_ad(rec_offs_validate(rec, index, offsets)); + ut_ad(rec_offs_validate(rec, + clust_templ_for_sec == true ? prebuilt->index : index, offsets)); if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) { @@ -2896,30 +2910,37 @@ row_sel_store_mysql_field_func( return(TRUE); } -/**************************************************************//** -Convert a row in the Innobase format to a row in the MySQL format. +/** Convert a row in the Innobase format to a row in the MySQL format. Note that the template in prebuilt may advise us to copy only a few columns to mysql_rec, other columns are left blank. All columns may not be needed in the query. +@param[out] mysql_rec row in the MySQL format +@param[in] prebuilt prebuilt structure +@param[in] rec Innobase record in the index + which was described in prebuilt's + template, or in the clustered index; + must be protected by a page latch +@param[in] rec_clust TRUE if the rec in the clustered index +@param[in] index index of rec +@param[in] offsets array returned by rec_get_offsets(rec) +@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index + but the prebuilt->template is in + clustered index format and it is + used only for end range comparison @return TRUE on success, FALSE if not all columns could be retrieved */ static MY_ATTRIBUTE((warn_unused_result)) ibool row_sel_store_mysql_rec( -/*====================*/ - byte* mysql_rec, /*!< out: row in the MySQL format */ - row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ - const rec_t* rec, /*!< in: Innobase record in the index - which was described in prebuilt's - template, or in the clustered index; - must be protected by a page latch */ - ibool rec_clust, /*!< in: TRUE if rec is in the - clustered index instead of - prebuilt->index */ - const dict_index_t* index, /*!< in: index of rec */ - const ulint* offsets) /*!< in: array returned by - rec_get_offsets(rec) */ + byte* mysql_rec, + row_prebuilt_t* prebuilt, + const rec_t* rec, + ibool rec_clust, + const dict_index_t* index, + const ulint* offsets, + bool clust_templ_for_sec) { - ulint i; + ulint i; + std::vector template_col; ut_ad(rec_clust || index == prebuilt->index); ut_ad(!rec_clust || dict_index_is_clust(index)); @@ -2929,9 +2950,20 @@ row_sel_store_mysql_rec( prebuilt->blob_heap = NULL; } + if (clust_templ_for_sec) { + /* Store all clustered index field of + secondary index record. */ + for (i = 0; i < dict_index_get_n_fields( + prebuilt->index); i++) { + ulint sec_field = dict_index_get_nth_field_pos( + index, prebuilt->index, i); + template_col.push_back(sec_field); + } + } + for (i = 0; i < prebuilt->n_template; i++) { const mysql_row_templ_t*templ = &prebuilt->mysql_template[i]; - const ulint field_no + ulint field_no = rec_clust ? templ->clust_rec_field_no : templ->rec_field_no; @@ -2940,9 +2972,24 @@ row_sel_store_mysql_rec( ut_ad(dict_index_get_nth_field(index, field_no)->prefix_len == 0); + if (clust_templ_for_sec) { + std::vector::iterator it; + it = std::find(template_col.begin(), + template_col.end(), field_no); + + if (it == template_col.end()) { + continue; + } + + ut_ad(templ->rec_field_no == templ->clust_rec_field_no); + + field_no = it - template_col.begin(); + } + if (!row_sel_store_mysql_field(mysql_rec, prebuilt, rec, index, offsets, - field_no, templ)) { + field_no, templ, + clust_templ_for_sec)) { return(FALSE); } } @@ -3582,7 +3629,7 @@ row_search_idx_cond_check( if (!row_sel_store_mysql_field(mysql_rec, prebuilt, rec, prebuilt->index, offsets, templ->icp_rec_field_no, - templ)) { + templ, false)) { return(ICP_NO_MATCH); } } @@ -3603,7 +3650,7 @@ row_search_idx_cond_check( || dict_index_is_clust(prebuilt->index)) { if (!row_sel_store_mysql_rec( mysql_rec, prebuilt, rec, FALSE, - prebuilt->index, offsets)) { + prebuilt->index, offsets, false)) { ut_ad(dict_index_is_clust(prebuilt->index)); return(ICP_NO_MATCH); } @@ -3622,6 +3669,27 @@ row_search_idx_cond_check( return(result); } +/** Check the pushed down end range condition to avoid extra traversal +if records are not within view and also to avoid prefetching in the +cache buffer. +@param[in] mysql_rec record in MySQL format +@param[in,out] handler the MySQL handler performing the scan +@retval true if the row in mysql_rec is out of range +@retval false if the row in mysql_rec is in range */ +static +bool +row_search_end_range_check( + const byte* mysql_rec, + ha_innobase* handler) +{ + if (handler->end_range && + handler->compare_key_in_buffer(mysql_rec) > 0) { + return(true); + } + + return(false); +} + /********************************************************************//** Searches for rows in the database. This is used in the interface to MySQL. This function opens a cursor, and also implements fetch next @@ -3659,7 +3727,9 @@ row_search_for_mysql( trx_t* trx = prebuilt->trx; dict_index_t* clust_index; que_thr_t* thr; - const rec_t* rec; + const rec_t* prev_rec = NULL; + const rec_t* rec = NULL; + byte* end_range_cache = NULL; const rec_t* result_rec = NULL; const rec_t* clust_rec; dberr_t err = DB_SUCCESS; @@ -3684,6 +3754,7 @@ row_search_for_mysql( ulint* offsets = offsets_; ibool table_lock_waited = FALSE; byte* next_buf = 0; + ulint end_loop = 0; rec_offs_init(offsets_); @@ -3823,6 +3894,10 @@ row_search_for_mysql( err = DB_SUCCESS; goto func_exit; + } else if (prebuilt->end_range == true) { + prebuilt->end_range = false; + err = DB_RECORD_NOT_FOUND; + goto func_exit; } if (prebuilt->fetch_cache_first > 0 @@ -3956,7 +4031,8 @@ row_search_for_mysql( if (!row_sel_store_mysql_rec( buf, prebuilt, - rec, FALSE, index, offsets)) { + rec, FALSE, index, + offsets, false)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such @@ -4205,11 +4281,62 @@ rec_loop: and neither can a record lock be placed on it: we skip such a record. */ + prev_rec = NULL; goto next_rec; } if (page_rec_is_supremum(rec)) { + /** Compare the last record of the page with end range + passed to InnoDB when there is no ICP and number of loops + in row_search_for_mysql for rows found but not + reporting due to search views etc. */ + if (prev_rec != NULL + && prebuilt->mysql_handler->end_range != NULL + && prebuilt->idx_cond == NULL + && end_loop >= 100) { + + dict_index_t* key_index = prebuilt->index; + bool clust_templ_for_sec = false; + + if (end_range_cache == NULL) { + end_range_cache = static_cast( + ut_malloc(prebuilt->mysql_row_len)); + } + + if (index != clust_index + && prebuilt->need_to_access_clustered) { + /** Secondary index record but the template + based on PK. */ + key_index = clust_index; + clust_templ_for_sec = true; + } + + /** Create offsets based on prebuilt index. */ + offsets = rec_get_offsets(prev_rec, prebuilt->index, + offsets, ULINT_UNDEFINED, &heap); + + if (row_sel_store_mysql_rec( + end_range_cache, prebuilt, prev_rec, + clust_templ_for_sec, key_index, offsets, + clust_templ_for_sec)) { + + if (row_search_end_range_check( + end_range_cache, + prebuilt->mysql_handler)) { + + /** In case of prebuilt->fetch, + set the error in prebuilt->end_range. */ + if (prebuilt->n_fetch_cached > 0) { + prebuilt->end_range = true; + } + + err = DB_RECORD_NOT_FOUND; + goto normal_return; + } + } + } + if (set_also_gap_locks && !(srv_locks_unsafe_for_binlog || trx->isolation_level <= TRX_ISO_READ_COMMITTED) @@ -4241,6 +4368,7 @@ rec_loop: /* A page supremum record cannot be in the result set: skip it now that we have placed a possible lock on it */ + prev_rec = NULL; goto next_rec; } @@ -4308,6 +4436,7 @@ wrong_offs: btr_pcur_move_to_last_on_page(pcur, &mtr); + prev_rec = NULL; goto next_rec; } } @@ -4334,10 +4463,13 @@ wrong_offs: fputs(". We try to skip the record.\n", stderr); + prev_rec = NULL; goto next_rec; } } + prev_rec = rec; + /* Note that we cannot trust the up_match value in the cursor at this place because we can arrive here after moving the cursor! Thus we have to recompare rec and search_tuple to determine if they @@ -4562,6 +4694,7 @@ no_gap_lock: did_semi_consistent_read = TRUE; rec = old_vers; + prev_rec = rec; break; default: @@ -4608,6 +4741,7 @@ no_gap_lock: } rec = old_vers; + prev_rec = rec; } } else { /* We are looking into a non-clustered index, @@ -4785,7 +4919,7 @@ requires_clust_rec: appropriate version of the clustered index record. */ if (!row_sel_store_mysql_rec( buf, prebuilt, result_rec, - TRUE, clust_index, offsets)) { + TRUE, clust_index, offsets, false)) { goto next_rec; } } @@ -4853,7 +4987,7 @@ requires_clust_rec: next_buf, prebuilt, result_rec, result_rec != rec, result_rec != rec ? clust_index : index, - offsets)) { + offsets, false)) { if (next_buf == buf) { ut_a(prebuilt->n_fetch_cached == 0); @@ -4908,7 +5042,7 @@ requires_clust_rec: buf, prebuilt, result_rec, result_rec != rec, result_rec != rec ? clust_index : index, - offsets)) { + offsets, false)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such records do @@ -4960,6 +5094,8 @@ idx_cond_failed: goto normal_return; next_rec: + end_loop++; + /* Reset the old and new "did semi-consistent read" flags. */ if (UNIV_UNLIKELY(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT)) { @@ -5146,6 +5282,11 @@ normal_return: func_exit: trx->op_info = ""; + + if (end_range_cache != NULL) { + ut_free(end_range_cache); + } + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index a67f3a776c5..173577740f8 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -2315,6 +2315,8 @@ DECLARE_THREAD(srv_master_thread)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); + srv_slot_t* slot; ulint old_activity_count = srv_get_activity_count(); ib_time_t last_print_time; @@ -2376,6 +2378,7 @@ suspend_thread: os_event_wait(slot->event); if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + my_thread_end(); os_thread_exit(NULL); } @@ -2458,6 +2461,8 @@ DECLARE_THREAD(srv_worker_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); + srv_slot_t* slot; ut_ad(!srv_read_only_mode); @@ -2516,6 +2521,7 @@ DECLARE_THREAD(srv_worker_thread)( os_thread_pf(os_thread_get_curr_id())); #endif /* UNIV_DEBUG_THREAD_CREATION */ + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); @@ -2716,6 +2722,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); + srv_slot_t* slot; ulint n_total_purged = ULINT_UNDEFINED; @@ -2821,6 +2829,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( srv_release_threads(SRV_WORKER, srv_n_purge_threads - 1); } + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); @@ -2889,3 +2898,18 @@ srv_purge_wakeup(void) } } +/** Check whether given space id is undo tablespace id +@param[in] space_id space id to check +@return true if it is undo tablespace else false. */ +bool +srv_is_undo_tablespace( + ulint space_id) +{ + if (srv_undo_space_id_start == 0) { + return (false); + } + + return(space_id >= srv_undo_space_id_start + && space_id < (srv_undo_space_id_start + + srv_undo_tablespaces_open)); +} diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 697107a1e0d..f6b68a73b74 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. @@ -109,6 +109,9 @@ UNIV_INTERN ibool srv_have_fullfsync = FALSE; /** TRUE if a raw partition is in use */ UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE; +/** UNDO tablespaces starts with space id. */ +ulint srv_undo_space_id_start; + /** TRUE if the server is being started, before rolling back any incomplete transactions */ UNIV_INTERN ibool srv_startup_is_before_trx_rollback_phase = FALSE; @@ -124,7 +127,7 @@ SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */ UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE; /** Files comprising the system tablespace */ -static os_file_t files[1000]; +static pfs_os_file_t files[1000]; /** io_handler_thread parameters for thread identification */ static ulint n[SRV_MAX_N_IO_THREADS + 6]; @@ -530,7 +533,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t create_log_file( /*============*/ - os_file_t* file, /*!< out: file handle */ + pfs_os_file_t* file, /*!< out: file handle */ const char* name) /*!< in: log file name */ { ibool ret; @@ -737,7 +740,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t open_log_file( /*==========*/ - os_file_t* file, /*!< out: file handle */ + pfs_os_file_t* file, /*!< out: file handle */ const char* name, /*!< in: log file name */ os_offset_t* size) /*!< out: file size */ { @@ -853,7 +856,7 @@ open_or_create_data_files( && os_file_get_last_error(false) != OS_FILE_ALREADY_EXISTS #ifdef UNIV_AIX - /* AIX 5.1 after security patch ML7 may have + /* AIX 5.1 after security patch ML7 may have errno set to 0 here, which causes our function to return 100; work around that AIX problem */ @@ -1156,7 +1159,7 @@ srv_undo_tablespace_create( const char* name, /*!< in: tablespace name */ ulint size) /*!< in: tablespace size in pages */ { - os_file_t fh; + pfs_os_file_t fh; ibool ret; dberr_t err = DB_SUCCESS; @@ -1233,7 +1236,7 @@ srv_undo_tablespace_open( const char* name, /*!< in: tablespace name */ ulint space) /*!< in: tablespace id */ { - os_file_t fh; + pfs_os_file_t fh; dberr_t err = DB_ERROR; ibool ret; ulint flags; @@ -1332,13 +1335,23 @@ srv_undo_tablespaces_init( for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) { char name[OS_FILE_MAX_PATH]; + ulint space_id = i + 1; + + DBUG_EXECUTE_IF("innodb_undo_upgrade", + space_id = i + 3;); ut_snprintf( name, sizeof(name), "%s%cundo%03lu", - srv_undo_dir, SRV_PATH_SEPARATOR, i + 1); + srv_undo_dir, SRV_PATH_SEPARATOR, space_id); + + if (i == 0) { + srv_undo_space_id_start = space_id; + prev_space_id = srv_undo_space_id_start - 1; + } + + undo_tablespace_ids[i] = space_id; - /* Undo space ids start from 1. */ err = srv_undo_tablespace_create( name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES); @@ -1360,14 +1373,16 @@ srv_undo_tablespaces_init( if (!create_new_db) { n_undo_tablespaces = trx_rseg_get_n_undo_tablespaces( undo_tablespace_ids); + + if (n_undo_tablespaces != 0) { + srv_undo_space_id_start = undo_tablespace_ids[0]; + prev_space_id = srv_undo_space_id_start - 1; + } + } else { n_undo_tablespaces = n_conf_tablespaces; - for (i = 1; i <= n_undo_tablespaces; ++i) { - undo_tablespace_ids[i - 1] = i; - } - - undo_tablespace_ids[i] = ULINT_UNDEFINED; + undo_tablespace_ids[n_conf_tablespaces] = ULINT_UNDEFINED; } /* Open all the undo tablespaces that are currently in use. If we @@ -1391,8 +1406,6 @@ srv_undo_tablespaces_init( ut_a(undo_tablespace_ids[i] != 0); ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED); - /* Undo space ids start from 1. */ - err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); if (err != DB_SUCCESS) { @@ -1427,11 +1440,23 @@ srv_undo_tablespaces_init( break; } + /** Note the first undo tablespace id in case of + no active undo tablespace. */ + if (n_undo_tablespaces == 0) { + srv_undo_space_id_start = i; + } + ++n_undo_tablespaces; ++*n_opened; } + /** Explictly specify the srv_undo_space_id_start + as zero when there are no undo tablespaces. */ + if (n_undo_tablespaces == 0) { + srv_undo_space_id_start = 0; + } + /* If the user says that there are fewer than what we find we tolerate that discrepancy but not the inverse. Because there could be unused undo tablespaces for future use. */ @@ -1476,10 +1501,11 @@ srv_undo_tablespaces_init( mtr_start(&mtr); /* The undo log tablespace */ - for (i = 1; i <= n_undo_tablespaces; ++i) { + for (i = 0; i < n_undo_tablespaces; ++i) { fsp_header_init( - i, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr); + undo_tablespace_ids[i], + SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr); } mtr_commit(&mtr); @@ -1554,6 +1580,10 @@ innobase_start_or_create_for_mysql(void) char* logfile0 = NULL; size_t dirnamelen; + if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { + srv_read_only_mode = 1; + } + high_level_read_only = srv_read_only_mode || srv_force_recovery > SRV_FORCE_NO_TRX_UNDO; diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index efc600d16b1..55af54991c6 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -692,7 +692,8 @@ trx_purge_get_rseg_with_min_trx_id( /* We assume in purge of externally stored fields that space id is in the range of UNDO tablespace space ids */ - ut_a(purge_sys->rseg->space <= srv_undo_tablespaces_open); + ut_a(purge_sys->rseg->space == 0 + || srv_is_undo_tablespace(purge_sys->rseg->space)); zip_size = purge_sys->rseg->zip_size; diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index e1e253cbb76..09e8e018c4f 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -800,6 +800,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_ad(!srv_read_only_mode); #ifdef UNIV_PFS_THREAD @@ -810,6 +811,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)( trx_rollback_or_clean_is_active = false; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index e5f03f4b96a..00d79e7ff51 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -909,18 +909,12 @@ trx_sys_create_rsegs( ulint new_rsegs = n_rsegs - n_used; for (i = 0; i < new_rsegs; ++i) { - ulint space; + ulint space_id; + space_id = (n_spaces == 0) ? 0 + : (srv_undo_space_id_start + i % n_spaces); - /* Tablespace 0 is the system tablespace. All UNDO - log tablespaces start from 1. */ - - if (n_spaces > 0) { - space = (i % n_spaces) + 1; - } else { - space = 0; /* System tablespace */ - } - - if (trx_rseg_create(space) != NULL) { + /* Tablespace 0 is the system tablespace. */ + if (trx_rseg_create(space_id) != NULL) { ++n_used; } else { break; From 217b8115c8c8392fa1781dfd88bd1a77e728d5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 15 May 2017 12:02:19 +0300 Subject: [PATCH 098/148] MDEV-12188 information schema - errors populating fail to free memory, unlock mutexes Given the OK macro used in innodb does a DBUG_RETURN(1) on expression failure the innodb implementation has a number of errors in i_s.cc. We introduce a new macro BREAK_IF that replaces some use of the OK macro. Also, do some other cleanup detailed below. When invoking Field::store() on integers, always pass the parameter is_unsigned=true to avoid an unnecessary conversion to double. i_s_fts_deleted_generic_fill(), i_s_fts_config_fill(): Use the BREAK_IF macro instead of OK. i_s_fts_index_cache_fill_one_index(), i_s_fts_index_table_fill_one_index(): Add a parameter for conv_string, and let the caller allocate that buffer. i_s_fts_index_cache_fill(): Check the return status of i_s_fts_index_cache_fill_one_index(). i_s_fts_index_table_fill(): Check the return status of i_s_fts_index_table_fill_one_index(). i_s_fts_index_table_fill_one_fetch(): Always let the caller invoke i_s_fts_index_table_free_one_fetch(). i_s_innodb_buffer_page_fill(), i_s_innodb_buf_page_lru_fill(): Do release dict_sys->mutex if filling the buffers fails. i_s_innodb_buf_page_lru_fill(): Also display the value INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.PAGE_IO_FIX='IO_PIN' when a block is in that state. Remove the unnecessary variable 'heap'. --- storage/innobase/handler/i_s.cc | 285 ++++++++++++++++---------------- storage/xtradb/handler/i_s.cc | 285 ++++++++++++++++---------------- 2 files changed, 284 insertions(+), 286 deletions(-) diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 50340e05860..2f5fe45656e 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -143,6 +144,7 @@ struct buf_page_info_t{ if ((expr) != 0) { \ DBUG_RETURN(1); \ } +#define BREAK_IF(expr) if ((expr)) break #define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \ do { \ @@ -2994,14 +2996,16 @@ i_s_fts_deleted_generic_fill( fields = table->field; + int ret = 0; + for (ulint j = 0; j < ib_vector_size(deleted->doc_ids); ++j) { doc_id_t doc_id; doc_id = *(doc_id_t*) ib_vector_get_const(deleted->doc_ids, j); - OK(fields[I_S_FTS_DOC_ID]->store((longlong) doc_id, true)); + BREAK_IF(ret = fields[I_S_FTS_DOC_ID]->store(doc_id, true)); - OK(schema_table_store_record(thd, table)); + BREAK_IF(ret = schema_table_store_record(thd, table)); } trx_free_for_background(trx); @@ -3012,7 +3016,7 @@ i_s_fts_deleted_generic_fill( rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** @@ -3252,13 +3256,13 @@ i_s_fts_index_cache_fill_one_index( /*===============================*/ fts_index_cache_t* index_cache, /*!< in: FTS index cache */ THD* thd, /*!< in: thread */ + fts_string_t* conv_str, /*!< in/out: buffer */ TABLE_LIST* tables) /*!< in/out: tables to fill */ { TABLE* table = (TABLE*) tables->table; Field** fields; CHARSET_INFO* index_charset; const ib_rbt_node_t* rbt_node; - fts_string_t conv_str; uint dummy_errors; char* word_str; @@ -3267,10 +3271,9 @@ i_s_fts_index_cache_fill_one_index( fields = table->field; index_charset = index_cache->charset; - conv_str.f_len = system_charset_info->mbmaxlen - * FTS_MAX_WORD_LEN_IN_CHAR; - conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); - conv_str.f_n_char = 0; + conv_str->f_n_char = 0; + + int ret = 0; /* Go through each word in the index cache */ for (rbt_node = rbt_first(index_cache->words); @@ -3282,16 +3285,16 @@ i_s_fts_index_cache_fill_one_index( /* Convert word from index charset to system_charset_info */ if (index_charset->cset != system_charset_info->cset) { - conv_str.f_n_char = my_convert( - reinterpret_cast(conv_str.f_str), - static_cast(conv_str.f_len), + conv_str->f_n_char = my_convert( + reinterpret_cast(conv_str->f_str), + static_cast(conv_str->f_len), system_charset_info, reinterpret_cast(word->text.f_str), static_cast(word->text.f_len), index_charset, &dummy_errors); - ut_ad(conv_str.f_n_char <= conv_str.f_len); - conv_str.f_str[conv_str.f_n_char] = 0; - word_str = reinterpret_cast(conv_str.f_str); + ut_ad(conv_str->f_n_char <= conv_str->f_len); + conv_str->f_str[conv_str->f_n_char] = 0; + word_str = reinterpret_cast(conv_str->f_str); } else { word_str = reinterpret_cast(word->text.f_str); } @@ -3349,9 +3352,7 @@ i_s_fts_index_cache_fill_one_index( } } - ut_free(conv_str.f_str); - - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED @@ -3395,18 +3396,27 @@ i_s_fts_index_cache_fill( ut_a(cache); + int ret = 0; + fts_string_t conv_str; + conv_str.f_len = system_charset_info->mbmaxlen + * FTS_MAX_WORD_LEN_IN_CHAR; + conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); + for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) { fts_index_cache_t* index_cache; index_cache = static_cast ( ib_vector_get(cache->indexes, i)); - i_s_fts_index_cache_fill_one_index(index_cache, thd, tables); + BREAK_IF(ret = i_s_fts_index_cache_fill_one_index( + index_cache, thd, &conv_str, tables)); } + ut_free(conv_str.f_str); + dict_table_close(user_table, FALSE, FALSE); - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** @@ -3710,8 +3720,6 @@ i_s_fts_index_table_fill_one_fetch( } } - i_s_fts_index_table_free_one_fetch(words); - DBUG_RETURN(ret); } @@ -3725,13 +3733,13 @@ i_s_fts_index_table_fill_one_index( /*===============================*/ dict_index_t* index, /*!< in: FTS index */ THD* thd, /*!< in: thread */ + fts_string_t* conv_str, /*!< in/out: buffer */ TABLE_LIST* tables) /*!< in/out: tables to fill */ { ib_vector_t* words; mem_heap_t* heap; fts_string_t word; CHARSET_INFO* index_charset; - fts_string_t conv_str; dberr_t error; int ret = 0; @@ -3748,10 +3756,6 @@ i_s_fts_index_table_fill_one_index( word.f_n_char = 0; index_charset = fts_index_get_charset(index); - conv_str.f_len = system_charset_info->mbmaxlen - * FTS_MAX_WORD_LEN_IN_CHAR; - conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); - conv_str.f_n_char = 0; /* Iterate through each auxiliary table as described in fts_index_selector */ @@ -3785,17 +3789,17 @@ i_s_fts_index_table_fill_one_index( /* Fill into tables */ ret = i_s_fts_index_table_fill_one_fetch( - index_charset, thd, tables, words, &conv_str, has_more); + index_charset, thd, tables, words, conv_str, + has_more); + i_s_fts_index_table_free_one_fetch(words); if (ret != 0) { - i_s_fts_index_table_free_one_fetch(words); goto func_exit; } } while (has_more); } func_exit: - ut_free(conv_str.f_str); mem_heap_free(heap); DBUG_RETURN(ret); @@ -3837,10 +3841,17 @@ i_s_fts_index_table_fill( DBUG_RETURN(0); } + int ret = 0; + fts_string_t conv_str; + conv_str.f_len = system_charset_info->mbmaxlen + * FTS_MAX_WORD_LEN_IN_CHAR; + conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); + for (index = dict_table_get_first_index(user_table); index; index = dict_table_get_next_index(index)) { if (index->type & DICT_FTS) { - i_s_fts_index_table_fill_one_index(index, thd, tables); + BREAK_IF(ret = i_s_fts_index_table_fill_one_index( + index, thd, &conv_str, tables)); } } @@ -3848,7 +3859,9 @@ i_s_fts_index_table_fill( rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); + ut_free(conv_str.f_str); + + DBUG_RETURN(ret); } /*******************************************************************//** @@ -4014,6 +4027,8 @@ i_s_fts_config_fill( DBUG_ASSERT(!dict_index_is_online_ddl(index)); } + int ret = 0; + while (fts_config_key[i]) { fts_string_t value; char* key_name; @@ -4038,13 +4053,14 @@ i_s_fts_config_fill( ut_free(key_name); } - OK(field_store_string( - fields[FTS_CONFIG_KEY], fts_config_key[i])); + BREAK_IF(ret = field_store_string( + fields[FTS_CONFIG_KEY], fts_config_key[i])); - OK(field_store_string( - fields[FTS_CONFIG_VALUE], (const char*) value.f_str)); + BREAK_IF(ret = field_store_string( + fields[FTS_CONFIG_VALUE], + reinterpret_cast(value.f_str))); - OK(schema_table_store_record(thd, table)); + BREAK_IF(ret = schema_table_store_record(thd, table)); i++; } @@ -4057,7 +4073,7 @@ i_s_fts_config_fill( rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** @@ -4895,34 +4911,29 @@ i_s_innodb_buffer_page_fill( state_str = NULL; OK(fields[IDX_BUFFER_POOL_ID]->store( - static_cast(page_info->pool_id))); + page_info->pool_id, true)); OK(fields[IDX_BUFFER_BLOCK_ID]->store( - static_cast(page_info->block_id))); + page_info->block_id, true)); OK(fields[IDX_BUFFER_PAGE_SPACE]->store( - static_cast(page_info->space_id))); + page_info->space_id, true)); OK(fields[IDX_BUFFER_PAGE_NUM]->store( - static_cast(page_info->page_num))); + page_info->page_num, true)); OK(field_store_string( fields[IDX_BUFFER_PAGE_TYPE], i_s_page_type[page_info->page_type].type_str)); OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store( - page_info->flush_type)); + page_info->flush_type, true)); OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( - page_info->fix_count)); + page_info->fix_count, true)); - if (page_info->hashed) { - OK(field_store_string( - fields[IDX_BUFFER_PAGE_HASHED], "YES")); - } else { - OK(field_store_string( - fields[IDX_BUFFER_PAGE_HASHED], "NO")); - } + OK(field_store_string(fields[IDX_BUFFER_PAGE_HASHED], + page_info->hashed ? "YES" : "NO")); OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store( (longlong) page_info->newest_mod, true)); @@ -4931,7 +4942,7 @@ i_s_innodb_buffer_page_fill( (longlong) page_info->oldest_mod, true)); OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store( - page_info->access_time)); + page_info->access_time, true)); fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_null(); @@ -4940,44 +4951,48 @@ i_s_innodb_buffer_page_fill( /* If this is an index page, fetch the index name and table name */ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { - const dict_index_t* index; + bool ret = false; mutex_enter(&dict_sys->mutex); - index = dict_index_get_if_in_cache_low( - page_info->index_id); - - if (index) { + if (const dict_index_t* index = + dict_index_get_if_in_cache_low( + page_info->index_id)) { table_name_end = innobase_convert_name( table_name, sizeof(table_name), index->table_name, strlen(index->table_name), thd, TRUE); - OK(fields[IDX_BUFFER_PAGE_TABLE_NAME]->store( - table_name, - static_cast(table_name_end - table_name), - system_charset_info)); - fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull(); - - OK(field_store_index_name( - fields[IDX_BUFFER_PAGE_INDEX_NAME], - index->name)); + ret = fields[IDX_BUFFER_PAGE_TABLE_NAME] + ->store(table_name, + static_cast( + table_name_end + - table_name), + system_charset_info) + || field_store_index_name( + fields + [IDX_BUFFER_PAGE_INDEX_NAME], + index->name); } mutex_exit(&dict_sys->mutex); + + OK(ret); + + fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull(); } OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store( - page_info->num_recs)); + page_info->num_recs, true)); OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store( - page_info->data_size)); + page_info->data_size, true)); OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store( - page_info->zip_ssize - ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize - : 0)); + page_info->zip_ssize + ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize + : 0, true)); #if BUF_PAGE_STATE_BITS > 3 # error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<io_fix) { case BUF_IO_NONE: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_NONE")); + state_str = "IO_NONE"; break; case BUF_IO_READ: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_READ")); + state_str = "IO_READ"; break; case BUF_IO_WRITE: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_WRITE")); + state_str = "IO_WRITE"; break; case BUF_IO_PIN: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_PIN")); + state_str = "IO_PIN"; break; } + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + state_str)); + OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD], (page_info->is_old) ? "YES" : "NO")); OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store( page_info->freed_page_clock)); - if (schema_table_store_record(thd, table)) { - DBUG_RETURN(1); - } + OK(schema_table_store_record(thd, table)); } DBUG_RETURN(0); @@ -5584,17 +5596,10 @@ i_s_innodb_buf_page_lru_fill( ulint num_page) /*!< in: number of page info cached */ { - TABLE* table; - Field** fields; - mem_heap_t* heap; - DBUG_ENTER("i_s_innodb_buf_page_lru_fill"); - table = tables->table; - - fields = table->field; - - heap = mem_heap_create(1000); + TABLE* table = tables->table; + Field** fields = table->field; /* Iterate through the cached array and fill the I_S table rows */ for (ulint i = 0; i < num_page; i++) { @@ -5609,43 +5614,37 @@ i_s_innodb_buf_page_lru_fill( page_info = info_array + i; OK(fields[IDX_BUF_LRU_POOL_ID]->store( - static_cast(page_info->pool_id))); - + page_info->pool_id, true)); OK(fields[IDX_BUF_LRU_POS]->store( - static_cast(page_info->block_id))); + page_info->block_id, true)); OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store( - static_cast(page_info->space_id))); + page_info->space_id, true)); OK(fields[IDX_BUF_LRU_PAGE_NUM]->store( - static_cast(page_info->page_num))); + page_info->page_num, true)); OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_TYPE], - i_s_page_type[page_info->page_type].type_str)); + fields[IDX_BUF_LRU_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store( - static_cast(page_info->flush_type))); + page_info->flush_type, true)); OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( - static_cast(page_info->fix_count))); + page_info->fix_count, true)); - if (page_info->hashed) { - OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_HASHED], "YES")); - } else { - OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_HASHED], "NO")); - } + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_HASHED], + page_info->hashed ? "YES" : "NO")); OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store( - page_info->newest_mod, true)); + page_info->newest_mod, true)); OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store( - page_info->oldest_mod, true)); + page_info->oldest_mod, true)); OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store( - page_info->access_time)); + page_info->access_time, true)); fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_null(); @@ -5654,43 +5653,47 @@ i_s_innodb_buf_page_lru_fill( /* If this is an index page, fetch the index name and table name */ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { - const dict_index_t* index; + bool ret = false; mutex_enter(&dict_sys->mutex); - index = dict_index_get_if_in_cache_low( - page_info->index_id); - - if (index) { + if (const dict_index_t* index = + dict_index_get_if_in_cache_low( + page_info->index_id)) { table_name_end = innobase_convert_name( table_name, sizeof(table_name), index->table_name, strlen(index->table_name), thd, TRUE); - OK(fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->store( - table_name, - static_cast(table_name_end - table_name), - system_charset_info)); - fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull(); - - OK(field_store_index_name( - fields[IDX_BUF_LRU_PAGE_INDEX_NAME], - index->name)); + ret = fields[IDX_BUF_LRU_PAGE_TABLE_NAME] + ->store(table_name, + static_cast( + table_name_end + - table_name), + system_charset_info) + || field_store_index_name( + fields + [IDX_BUF_LRU_PAGE_INDEX_NAME], + index->name); } mutex_exit(&dict_sys->mutex); + + OK(ret); + + fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull(); } OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store( - page_info->num_recs)); + page_info->num_recs, true)); OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store( - page_info->data_size)); + page_info->data_size, true)); OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store( - page_info->zip_ssize ? - 512 << page_info->zip_ssize : 0)); + page_info->zip_ssize + ? 512 << page_info->zip_ssize : 0, true)); state = static_cast(page_info->page_state); @@ -5719,35 +5722,31 @@ i_s_innodb_buf_page_lru_fill( switch (page_info->io_fix) { case BUF_IO_NONE: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], - "IO_NONE")); + state_str = "IO_NONE"; break; case BUF_IO_READ: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], - "IO_READ")); + state_str = "IO_READ"; break; case BUF_IO_WRITE: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], - "IO_WRITE")); + state_str = "IO_WRITE"; + break; + case BUF_IO_PIN: + state_str = "IO_PIN"; break; } + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + state_str)); + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD], - (page_info->is_old) ? "YES" : "NO")); + page_info->is_old ? "YES" : "NO")); OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store( - page_info->freed_page_clock)); + page_info->freed_page_clock, true)); - if (schema_table_store_record(thd, table)) { - mem_heap_free(heap); - DBUG_RETURN(1); - } - - mem_heap_empty(heap); + OK(schema_table_store_record(thd, table)); } - mem_heap_free(heap); - DBUG_RETURN(0); } diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index f2686f1049b..aac1074e152 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -155,6 +156,7 @@ struct buf_page_info_t{ if ((expr) != 0) { \ DBUG_RETURN(1); \ } +#define BREAK_IF(expr) if ((expr)) break #define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \ do { \ @@ -2989,14 +2991,16 @@ i_s_fts_deleted_generic_fill( fields = table->field; + int ret = 0; + for (ulint j = 0; j < ib_vector_size(deleted->doc_ids); ++j) { doc_id_t doc_id; doc_id = *(doc_id_t*) ib_vector_get_const(deleted->doc_ids, j); - OK(fields[I_S_FTS_DOC_ID]->store((longlong) doc_id, true)); + BREAK_IF(ret = fields[I_S_FTS_DOC_ID]->store(doc_id, true)); - OK(schema_table_store_record(thd, table)); + BREAK_IF(ret = schema_table_store_record(thd, table)); } trx_free_for_background(trx); @@ -3007,7 +3011,7 @@ i_s_fts_deleted_generic_fill( rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** @@ -3245,13 +3249,13 @@ i_s_fts_index_cache_fill_one_index( /*===============================*/ fts_index_cache_t* index_cache, /*!< in: FTS index cache */ THD* thd, /*!< in: thread */ + fts_string_t* conv_str, /*!< in/out: buffer */ TABLE_LIST* tables) /*!< in/out: tables to fill */ { TABLE* table = (TABLE*) tables->table; Field** fields; CHARSET_INFO* index_charset; const ib_rbt_node_t* rbt_node; - fts_string_t conv_str; uint dummy_errors; char* word_str; @@ -3260,10 +3264,9 @@ i_s_fts_index_cache_fill_one_index( fields = table->field; index_charset = index_cache->charset; - conv_str.f_len = system_charset_info->mbmaxlen - * FTS_MAX_WORD_LEN_IN_CHAR; - conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); - conv_str.f_n_char = 0; + conv_str->f_n_char = 0; + + int ret = 0; /* Go through each word in the index cache */ for (rbt_node = rbt_first(index_cache->words); @@ -3275,16 +3278,16 @@ i_s_fts_index_cache_fill_one_index( /* Convert word from index charset to system_charset_info */ if (index_charset->cset != system_charset_info->cset) { - conv_str.f_n_char = my_convert( - reinterpret_cast(conv_str.f_str), - static_cast(conv_str.f_len), + conv_str->f_n_char = my_convert( + reinterpret_cast(conv_str->f_str), + static_cast(conv_str->f_len), system_charset_info, reinterpret_cast(word->text.f_str), static_cast(word->text.f_len), index_charset, &dummy_errors); - ut_ad(conv_str.f_n_char <= conv_str.f_len); - conv_str.f_str[conv_str.f_n_char] = 0; - word_str = reinterpret_cast(conv_str.f_str); + ut_ad(conv_str->f_n_char <= conv_str->f_len); + conv_str->f_str[conv_str->f_n_char] = 0; + word_str = reinterpret_cast(conv_str->f_str); } else { word_str = reinterpret_cast(word->text.f_str); } @@ -3342,9 +3345,7 @@ i_s_fts_index_cache_fill_one_index( } } - ut_free(conv_str.f_str); - - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED @@ -3388,18 +3389,27 @@ i_s_fts_index_cache_fill( ut_a(cache); + int ret = 0; + fts_string_t conv_str; + conv_str.f_len = system_charset_info->mbmaxlen + * FTS_MAX_WORD_LEN_IN_CHAR; + conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); + for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) { fts_index_cache_t* index_cache; index_cache = static_cast ( ib_vector_get(cache->indexes, i)); - i_s_fts_index_cache_fill_one_index(index_cache, thd, tables); + BREAK_IF(ret = i_s_fts_index_cache_fill_one_index( + index_cache, thd, &conv_str, tables)); } + ut_free(conv_str.f_str); + dict_table_close(user_table, FALSE, FALSE); - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** @@ -3702,8 +3712,6 @@ i_s_fts_index_table_fill_one_fetch( } } - i_s_fts_index_table_free_one_fetch(words); - DBUG_RETURN(ret); } @@ -3717,13 +3725,13 @@ i_s_fts_index_table_fill_one_index( /*===============================*/ dict_index_t* index, /*!< in: FTS index */ THD* thd, /*!< in: thread */ + fts_string_t* conv_str, /*!< in/out: buffer */ TABLE_LIST* tables) /*!< in/out: tables to fill */ { ib_vector_t* words; mem_heap_t* heap; fts_string_t word; CHARSET_INFO* index_charset; - fts_string_t conv_str; dberr_t error; int ret = 0; @@ -3740,10 +3748,6 @@ i_s_fts_index_table_fill_one_index( word.f_n_char = 0; index_charset = fts_index_get_charset(index); - conv_str.f_len = system_charset_info->mbmaxlen - * FTS_MAX_WORD_LEN_IN_CHAR; - conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); - conv_str.f_n_char = 0; /* Iterate through each auxiliary table as described in fts_index_selector */ @@ -3777,17 +3781,17 @@ i_s_fts_index_table_fill_one_index( /* Fill into tables */ ret = i_s_fts_index_table_fill_one_fetch( - index_charset, thd, tables, words, &conv_str, has_more); + index_charset, thd, tables, words, conv_str, + has_more); + i_s_fts_index_table_free_one_fetch(words); if (ret != 0) { - i_s_fts_index_table_free_one_fetch(words); goto func_exit; } } while (has_more); } func_exit: - ut_free(conv_str.f_str); mem_heap_free(heap); DBUG_RETURN(ret); @@ -3829,10 +3833,17 @@ i_s_fts_index_table_fill( DBUG_RETURN(0); } + int ret = 0; + fts_string_t conv_str; + conv_str.f_len = system_charset_info->mbmaxlen + * FTS_MAX_WORD_LEN_IN_CHAR; + conv_str.f_str = static_cast(ut_malloc(conv_str.f_len)); + for (index = dict_table_get_first_index(user_table); index; index = dict_table_get_next_index(index)) { if (index->type & DICT_FTS) { - i_s_fts_index_table_fill_one_index(index, thd, tables); + BREAK_IF(ret = i_s_fts_index_table_fill_one_index( + index, thd, &conv_str, tables)); } } @@ -3840,7 +3851,9 @@ i_s_fts_index_table_fill( rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); + ut_free(conv_str.f_str); + + DBUG_RETURN(ret); } /*******************************************************************//** @@ -4005,6 +4018,8 @@ i_s_fts_config_fill( DBUG_ASSERT(!dict_index_is_online_ddl(index)); } + int ret = 0; + while (fts_config_key[i]) { fts_string_t value; char* key_name; @@ -4029,13 +4044,14 @@ i_s_fts_config_fill( ut_free(key_name); } - OK(field_store_string( - fields[FTS_CONFIG_KEY], fts_config_key[i])); + BREAK_IF(ret = field_store_string( + fields[FTS_CONFIG_KEY], fts_config_key[i])); - OK(field_store_string( - fields[FTS_CONFIG_VALUE], (const char*) value.f_str)); + BREAK_IF(ret = field_store_string( + fields[FTS_CONFIG_VALUE], + reinterpret_cast(value.f_str))); - OK(schema_table_store_record(thd, table)); + BREAK_IF(ret = schema_table_store_record(thd, table)); i++; } @@ -4048,7 +4064,7 @@ i_s_fts_config_fill( rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); + DBUG_RETURN(ret); } /*******************************************************************//** @@ -4883,34 +4899,29 @@ i_s_innodb_buffer_page_fill( state_str = NULL; OK(fields[IDX_BUFFER_POOL_ID]->store( - static_cast(page_info->pool_id))); + page_info->pool_id, true)); OK(fields[IDX_BUFFER_BLOCK_ID]->store( - static_cast(page_info->block_id))); + page_info->block_id, true)); OK(fields[IDX_BUFFER_PAGE_SPACE]->store( - static_cast(page_info->space_id))); + page_info->space_id, true)); OK(fields[IDX_BUFFER_PAGE_NUM]->store( - static_cast(page_info->page_num))); + page_info->page_num, true)); OK(field_store_string( fields[IDX_BUFFER_PAGE_TYPE], i_s_page_type[page_info->page_type].type_str)); OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store( - page_info->flush_type)); + page_info->flush_type, true)); OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( - page_info->fix_count)); + page_info->fix_count, true)); - if (page_info->hashed) { - OK(field_store_string( - fields[IDX_BUFFER_PAGE_HASHED], "YES")); - } else { - OK(field_store_string( - fields[IDX_BUFFER_PAGE_HASHED], "NO")); - } + OK(field_store_string(fields[IDX_BUFFER_PAGE_HASHED], + page_info->hashed ? "YES" : "NO")); OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store( (longlong) page_info->newest_mod, true)); @@ -4919,7 +4930,7 @@ i_s_innodb_buffer_page_fill( (longlong) page_info->oldest_mod, true)); OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store( - page_info->access_time)); + page_info->access_time, true)); fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_null(); @@ -4928,44 +4939,48 @@ i_s_innodb_buffer_page_fill( /* If this is an index page, fetch the index name and table name */ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { - const dict_index_t* index; + bool ret = false; mutex_enter(&dict_sys->mutex); - index = dict_index_get_if_in_cache_low( - page_info->index_id); - - if (index) { + if (const dict_index_t* index = + dict_index_get_if_in_cache_low( + page_info->index_id)) { table_name_end = innobase_convert_name( table_name, sizeof(table_name), index->table_name, strlen(index->table_name), thd, TRUE); - OK(fields[IDX_BUFFER_PAGE_TABLE_NAME]->store( - table_name, - static_cast(table_name_end - table_name), - system_charset_info)); - fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull(); - - OK(field_store_index_name( - fields[IDX_BUFFER_PAGE_INDEX_NAME], - index->name)); + ret = fields[IDX_BUFFER_PAGE_TABLE_NAME] + ->store(table_name, + static_cast( + table_name_end + - table_name), + system_charset_info) + || field_store_index_name( + fields + [IDX_BUFFER_PAGE_INDEX_NAME], + index->name); } mutex_exit(&dict_sys->mutex); + + OK(ret); + + fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull(); } OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store( - page_info->num_recs)); + page_info->num_recs, true)); OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store( - page_info->data_size)); + page_info->data_size, true)); OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store( - page_info->zip_ssize - ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize - : 0)); + page_info->zip_ssize + ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize + : 0, true)); #if BUF_PAGE_STATE_BITS > 3 # error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<io_fix) { case BUF_IO_NONE: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_NONE")); + state_str = "IO_NONE"; break; case BUF_IO_READ: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_READ")); + state_str = "IO_READ"; break; case BUF_IO_WRITE: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_WRITE")); + state_str = "IO_WRITE"; break; case BUF_IO_PIN: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], - "IO_PIN")); + state_str = "IO_PIN"; break; } + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + state_str)); + OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD], (page_info->is_old) ? "YES" : "NO")); OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store( page_info->freed_page_clock)); - if (schema_table_store_record(thd, table)) { - DBUG_RETURN(1); - } + OK(schema_table_store_record(thd, table)); } DBUG_RETURN(0); @@ -5569,17 +5581,10 @@ i_s_innodb_buf_page_lru_fill( ulint num_page) /*!< in: number of page info cached */ { - TABLE* table; - Field** fields; - mem_heap_t* heap; - DBUG_ENTER("i_s_innodb_buf_page_lru_fill"); - table = tables->table; - - fields = table->field; - - heap = mem_heap_create(1000); + TABLE* table = tables->table; + Field** fields = table->field; /* Iterate through the cached array and fill the I_S table rows */ for (ulint i = 0; i < num_page; i++) { @@ -5594,43 +5599,37 @@ i_s_innodb_buf_page_lru_fill( page_info = info_array + i; OK(fields[IDX_BUF_LRU_POOL_ID]->store( - static_cast(page_info->pool_id))); - + page_info->pool_id, true)); OK(fields[IDX_BUF_LRU_POS]->store( - static_cast(page_info->block_id))); + page_info->block_id, true)); OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store( - static_cast(page_info->space_id))); + page_info->space_id, true)); OK(fields[IDX_BUF_LRU_PAGE_NUM]->store( - static_cast(page_info->page_num))); + page_info->page_num, true)); OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_TYPE], - i_s_page_type[page_info->page_type].type_str)); + fields[IDX_BUF_LRU_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store( - static_cast(page_info->flush_type))); + page_info->flush_type, true)); OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( - static_cast(page_info->fix_count))); + page_info->fix_count, true)); - if (page_info->hashed) { - OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_HASHED], "YES")); - } else { - OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_HASHED], "NO")); - } + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_HASHED], + page_info->hashed ? "YES" : "NO")); OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store( - page_info->newest_mod, true)); + page_info->newest_mod, true)); OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store( - page_info->oldest_mod, true)); + page_info->oldest_mod, true)); OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store( - page_info->access_time)); + page_info->access_time, true)); fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_null(); @@ -5639,43 +5638,47 @@ i_s_innodb_buf_page_lru_fill( /* If this is an index page, fetch the index name and table name */ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { - const dict_index_t* index; + bool ret = false; mutex_enter(&dict_sys->mutex); - index = dict_index_get_if_in_cache_low( - page_info->index_id); - - if (index) { + if (const dict_index_t* index = + dict_index_get_if_in_cache_low( + page_info->index_id)) { table_name_end = innobase_convert_name( table_name, sizeof(table_name), index->table_name, strlen(index->table_name), thd, TRUE); - OK(fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->store( - table_name, - static_cast(table_name_end - table_name), - system_charset_info)); - fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull(); - - OK(field_store_index_name( - fields[IDX_BUF_LRU_PAGE_INDEX_NAME], - index->name)); + ret = fields[IDX_BUF_LRU_PAGE_TABLE_NAME] + ->store(table_name, + static_cast( + table_name_end + - table_name), + system_charset_info) + || field_store_index_name( + fields + [IDX_BUF_LRU_PAGE_INDEX_NAME], + index->name); } mutex_exit(&dict_sys->mutex); + + OK(ret); + + fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull(); } OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store( - page_info->num_recs)); + page_info->num_recs, true)); OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store( - page_info->data_size)); + page_info->data_size, true)); OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store( - page_info->zip_ssize ? - 512 << page_info->zip_ssize : 0)); + page_info->zip_ssize + ? 512 << page_info->zip_ssize : 0, true)); state = static_cast(page_info->page_state); @@ -5704,35 +5707,31 @@ i_s_innodb_buf_page_lru_fill( switch (page_info->io_fix) { case BUF_IO_NONE: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], - "IO_NONE")); + state_str = "IO_NONE"; break; case BUF_IO_READ: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], - "IO_READ")); + state_str = "IO_READ"; break; case BUF_IO_WRITE: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], - "IO_WRITE")); + state_str = "IO_WRITE"; + break; + case BUF_IO_PIN: + state_str = "IO_PIN"; break; } + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + state_str)); + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD], - (page_info->is_old) ? "YES" : "NO")); + page_info->is_old ? "YES" : "NO")); OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store( - page_info->freed_page_clock)); + page_info->freed_page_clock, true)); - if (schema_table_store_record(thd, table)) { - mem_heap_free(heap); - DBUG_RETURN(1); - } - - mem_heap_empty(heap); + OK(schema_table_store_record(thd, table)); } - mem_heap_free(heap); - DBUG_RETURN(0); } From e0352fb07961f09ff6481136dc22f3c0db376def Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 15 May 2017 09:51:01 -0700 Subject: [PATCH 099/148] Fixed the bug mdev-7599. At some conditions the function opt_sum_query() can apply MIN/MAX optimizations to to Item_sum objects of a select These optimizations becomes invalid if this select is the subquery of an IN subquery predicate that is converted to a EXISTS subquery. Thus in this case the MIX/MAX optimizations that have been applied in opt_sum_query() must be rolled back. This bug appeared in 5.3 when the code for the cost base choice between materialization and in-to-exists transformation of non-correlated IN subqueries was introduced. Before this code in-to-exists transformations were always performed before the call of opt_sum_query(). --- mysql-test/r/subselect_mat_cost_bugs.result | 43 ++++++++++++++++++++ mysql-test/t/subselect_mat_cost_bugs.test | 44 +++++++++++++++++++++ sql/item_subselect.cc | 21 ++++++++++ sql/item_sum.h | 1 + sql/opt_sum.cc | 9 +++++ sql/sql_lex.cc | 1 + sql/sql_lex.h | 5 +++ 7 files changed, 124 insertions(+) diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result index 9bfd5bd67b5..dba4d049da3 100644 --- a/mysql-test/r/subselect_mat_cost_bugs.result +++ b/mysql-test/r/subselect_mat_cost_bugs.result @@ -379,6 +379,7 @@ drop table t3, t4, t5; # # LP BUG#858038 The result of a query with NOT IN subquery depends on the state of the optimizer switch # +set @optimizer_switch_save= @@optimizer_switch; create table t1 (c1 char(2) not null, c2 char(2)); create table t2 (c3 char(2), c4 char(2)); insert into t1 values ('a1', 'b1'); @@ -400,6 +401,7 @@ id select_type table type possible_keys key key_len ref rows Extra select * from t1 where c1 = 'a2' and (c1, c2) not in (select * from t2); c1 c2 drop table t1, t2; +set optimizer_switch= @optimizer_switch_save; # # MDEV-12673: cost-based choice between materialization and in-to-exists # @@ -442,3 +444,44 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t3 const PRIMARY PRIMARY 4 const 1 2 DEPENDENT SUBQUERY t2 index NULL i2 11 NULL 2 Using where; Using index DROP TABLE t1,t2,t3; +# +# MDEV-7599: in-to-exists chosen after min/max optimization +# +set @optimizer_switch_save= @@optimizer_switch; +CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT, c INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,6),(2,4), (8,9); +SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b); +b c +EXPLAIN EXTENDED SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where +2 MATERIALIZED t1 index NULL a 5 NULL 2 100.00 Using index +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (not(<`test`.`t2`.`b`>((`test`.`t2`.`b`,`test`.`t2`.`b` in ( (select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`c` = `test`.`t2`.`b`) ), (`test`.`t2`.`b` in on distinct_key where ((`test`.`t2`.`b` = ``.`MIN(a)`)))))))) +set optimizer_switch= 'materialization=off'; +SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b); +b c +EXPLAIN EXTENDED SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where +2 DEPENDENT SUBQUERY t1 index NULL a 5 NULL 2 100.00 Using index +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (not(<`test`.`t2`.`b`>((`test`.`t2`.`b`,(select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`c` = `test`.`t2`.`b`) having trigcond(((`test`.`t2`.`b`) = (min(`test`.`t1`.`a`))))))))) +set optimizer_switch= @optimizer_switch_save; +DROP TABLE t1,t2; +CREATE TABLE t1 (f1 varchar(10)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE TABLE t2 (f2 varchar(10), key(f2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('baz'),('qux'); +CREATE TABLE t3 (f3 varchar(10)) ENGINE=MyISAM; +INSERT INTO t3 VALUES ('abc'),('def'); +SELECT * FROM t1 +WHERE f1 = ALL( SELECT MAX(t2a.f2) +FROM t2 AS t2a INNER JOIN t2 t2b INNER JOIN t3 +ON (f3 = t2b.f2) ); +f1 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/subselect_mat_cost_bugs.test b/mysql-test/t/subselect_mat_cost_bugs.test index 316ac707bef..9e3ac603ec6 100644 --- a/mysql-test/t/subselect_mat_cost_bugs.test +++ b/mysql-test/t/subselect_mat_cost_bugs.test @@ -406,6 +406,8 @@ drop table t3, t4, t5; --echo # LP BUG#858038 The result of a query with NOT IN subquery depends on the state of the optimizer switch --echo # +set @optimizer_switch_save= @@optimizer_switch; + create table t1 (c1 char(2) not null, c2 char(2)); create table t2 (c3 char(2), c4 char(2)); @@ -425,6 +427,8 @@ select * from t1 where c1 = 'a2' and (c1, c2) not in (select * from t2); drop table t1, t2; +set optimizer_switch= @optimizer_switch_save; + --echo # --echo # MDEV-12673: cost-based choice between materialization and in-to-exists --echo # @@ -463,3 +467,43 @@ SELECT * FROM t1 WHERE i1 NOT IN ( ); DROP TABLE t1,t2,t3; + +--echo # +--echo # MDEV-7599: in-to-exists chosen after min/max optimization +--echo # + +set @optimizer_switch_save= @@optimizer_switch; + +CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (b INT, c INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,6),(2,4), (8,9); + +let $q= +SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b); + +eval $q; +eval EXPLAIN EXTENDED $q; +set optimizer_switch= 'materialization=off'; +eval $q; +eval EXPLAIN EXTENDED $q; +set optimizer_switch= @optimizer_switch_save; + +DROP TABLE t1,t2; + +CREATE TABLE t1 (f1 varchar(10)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),('bar'); + +CREATE TABLE t2 (f2 varchar(10), key(f2)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('baz'),('qux'); + +CREATE TABLE t3 (f3 varchar(10)) ENGINE=MyISAM; +INSERT INTO t3 VALUES ('abc'),('def'); + +SELECT * FROM t1 + WHERE f1 = ALL( SELECT MAX(t2a.f2) + FROM t2 AS t2a INNER JOIN t2 t2b INNER JOIN t3 + ON (f3 = t2b.f2) ); + +DROP TABLE t1,t2,t3; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 12337ec2b1c..e0da946d190 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2493,6 +2493,27 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond"); DBUG_ASSERT(thd == join_arg->thd); + if (select_lex->min_max_opt_list.elements) + { + /* + MIN/MAX optimizations have been applied to Item_sum objects + of the subquery this subquery predicate in opt_sum_query(). + Injection of new condition invalidates this optimizations. + Thus those optimizations must be rolled back. + */ + List_iterator_fast it(select_lex->min_max_opt_list); + Item_sum *item; + while ((item= it++)) + { + item->clear(); + item->reset_forced_const(); + } + if (where_item) + where_item->update_used_tables(); + if (having_item) + having_item->update_used_tables(); + } + if (where_item) { List *and_args= NULL; diff --git a/sql/item_sum.h b/sql/item_sum.h index 86093f5d4f5..dcc3e494f82 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -454,6 +454,7 @@ public: used_tables_cache= 0; forced_const= TRUE; } + void reset_forced_const() { forced_const= FALSE; } virtual bool const_item() const { return forced_const; } virtual bool const_during_execution() const { return false; } virtual void print(String *str, enum_query_type query_type); diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index aa8b17a2c85..1a8c6be5f41 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -253,6 +253,8 @@ int opt_sum_query(THD *thd, int error= 0; DBUG_ENTER("opt_sum_query"); + thd->lex->current_select->min_max_opt_list.empty(); + if (conds) where_tables= conds->used_tables(); @@ -444,7 +446,14 @@ int opt_sum_query(THD *thd, item_sum->aggregator_clear(); } else + { item_sum->reset_and_add(); + /* + Save a reference to the item for possible rollback + of the min/max optimizations for this select + */ + thd->lex->current_select->min_max_opt_list.push_back(item_sum); + } item_sum->make_const(); recalc_const_item= 1; break; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index fa866bc7008..6611fd43876 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1875,6 +1875,7 @@ void st_select_lex::init_query() leaf_tables_prep.empty(); leaf_tables.empty(); item_list.empty(); + min_max_opt_list.empty(); join= 0; having= prep_having= where= prep_where= 0; olap= UNSPECIFIED_OLAP_TYPE; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b13befd8dbe..d283085886e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -766,6 +766,11 @@ public: */ List *ftfunc_list; List ftfunc_list_alloc; + /* + The list of items to which MIN/MAX optimizations of opt_sum_query() + have been applied. Used to rollback those optimizations if it's needed. + */ + List min_max_opt_list; JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */ List top_join_list; /* join list of the top level */ List *join_list; /* list for the currently parsed join */ From 2e1428c0b552f2c80aa4b27edaaab8bde8966b22 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 15 May 2017 13:33:59 +0200 Subject: [PATCH 100/148] MDEV-12799 Buffer overflow with a specially corrupted master.info one can get an invalid heartbeat_period that will trigger a heap overflow. --- sql/rpl_mi.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 3c5a99121fa..13284308f04 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -401,7 +401,7 @@ file '%s')", fname); mi->connect_retry= (uint) connect_retry; mi->ssl= (my_bool) ssl; mi->ssl_verify_server_cert= ssl_verify_server_cert; - mi->heartbeat_period= master_heartbeat_period; + mi->heartbeat_period= min(SLAVE_MAX_HEARTBEAT_PERIOD, master_heartbeat_period); } DBUG_PRINT("master_info",("log_file_name: %s position: %ld", mi->master_log_name, @@ -518,8 +518,8 @@ int flush_master_info(Master_info* mi, contents of file). But because of number of lines in the first line of file we don't care about this garbage. */ - char heartbeat_buf[sizeof(mi->heartbeat_period) * 4]; // buffer to suffice always - sprintf(heartbeat_buf, "%.3f", mi->heartbeat_period); + char heartbeat_buf[FLOATING_POINT_BUFFER]; + my_fcvt(mi->heartbeat_period, 3, heartbeat_buf, NULL); my_b_seek(file, 0L); my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n", From d672f88ef73e3fc566a382600968c3e51249de1a Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 8 Apr 2017 22:47:56 +1000 Subject: [PATCH 101/148] MDEV-12420: PCRE stack overflow It was possible to construct a PCRE expression that exceeded the stack. resulting in a crash: With fix: MariaDB [(none)]> SELECT 1 -> FROM dual -> WHERE ('Alpha,Bravo,Charlie,Delta,Echo,Foxtrot,StrataCentral,Golf,Hotel,India,Juliet,Kilo,Lima,Mike,StrataL3,November,Oscar,StrataL2,Sand,P3,P4SwitchTest,Arsys,Poppa,ExtensionMgr,Arp,Quebec,Romeo,StrataApiV2,PtReyes,Sierra,SandAcl,Arrow,Artools,BridgeTest,Tango,SandT,PAlaska,Namespace,Agent,Qos,PatchPanel,ProjectReport,Ark,Gimp,Agent,SliceAgent,Arnet,Bgp,Ale,Tommy,Central,AsicPktTestLib,Hsc,SandL3,Abuild,Pca9555,Standby,ControllerDut,CalSys,SandLib,Sb820,PointV2,BfnLib,Evpn,BfnSdk,Sflow,ManagementActive,AutoTest,GatedTest,Bgp,Sand,xinetd,BfnAgentLib,bf-utils,Hello,BfnState,Eos,Artest,Qos,Scd,ThermoMgr,Uniform,EosUtils,Eb,FanController,Central,BfnL3,BfnL2,tcp_wrappers,Victor,Environment,Route,Failover,Whiskey,Xray,Gimp,BfnFixed,Strata,SoCal,XApi,Msrp,XpProfile,tcpdump,PatchPanel,ArosTest,FhTest,Arbus,XpAcl,MacConc,XpApi,telnet,QosTest,Alpha2,BfnVlan,Stp,VxlanControllerTest,MplsAgent,Bravo2,Lanz,BfnMbb,Intf,XCtrl,Unicast,SandTunnel,L3Unicast,Ipsec,MplsTest,Rsvp,EthIntf,StageMgr,Sol,MplsUtils,Nat,Ira,P4NamespaceDut,Counters,Charlie2,Aqlc,Mlag,Power,OpenFlow,Lag,RestApi,BfdTest,strongs,Sfa,CEosUtils,Adt746,MaintenanceMode,MlagDut,EosImage,IpEth,MultiProtocol,Launcher,Max3179,Snmp,Acl,IpEthTest,PhyEee,bf-syslibs,tacc,XpL2,p4-ar-switch,p4-bf-switch,LdpTest,BfnPhy,Mirroring,Phy6,Ptp' -> -> REGEXP '^((?!\b(Strata|StrataApi|StrataApiV2)\b).)*$'); Empty set, 1 warning (0.00 sec) MariaDB [(none)]> show warnings; +---------+------+---------------------------------------------------------+ | Level | Code | Message | +---------+------+---------------------------------------------------------+ | Warning | 1139 | Got error 'pcre_exec: Internal error (-21)' from regexp | +---------+------+---------------------------------------------------------+ --- sql/item_cmpfunc.cc | 4 ++-- sql/item_cmpfunc.h | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 192e06566ff..5a3e028260f 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5237,7 +5237,7 @@ int Regexp_processor_pcre::pcre_exec_with_warn(const pcre *code, bool Regexp_processor_pcre::exec(const char *str, int length, int offset) { - m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, NULL, str, length, offset, 0, + m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, str, length, offset, 0, m_SubStrVec, m_subpatterns_needed * 3); return false; } @@ -5248,7 +5248,7 @@ bool Regexp_processor_pcre::exec(String *str, int offset, { if (!(str= convert_if_needed(str, &subject_converter))) return true; - m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, NULL, + m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, str->c_ptr_safe(), str->length(), offset, 0, m_SubStrVec, m_subpatterns_needed * 3); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b84cb26fb9c..bd552bfc952 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1550,6 +1550,7 @@ public: class Regexp_processor_pcre { pcre *m_pcre; + pcre_extra m_pcre_extra; bool m_conversion_is_needed; bool m_is_const; int m_library_flags; @@ -1574,7 +1575,10 @@ public: m_data_charset(&my_charset_utf8_general_ci), m_library_charset(&my_charset_utf8_general_ci), m_subpatterns_needed(0) - {} + { + m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION; + m_pcre_extra.match_limit_recursion= 100L; + } int default_regex_flags(); void init(CHARSET_INFO *data_charset, int extra_flags, uint nsubpatterns) { From fbc057ad3642884f5af1851bd46bcc2060e75404 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 9 Apr 2017 12:54:33 +1000 Subject: [PATCH 102/148] MDEV-12420: add full list of pcre error messages --- sql/item_cmpfunc.cc | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5a3e028260f..bfad63f21f8 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5193,15 +5193,77 @@ void Regexp_processor_pcre::pcre_exec_warn(int rc) const */ switch (rc) { + case PCRE_ERROR_NULL: + errmsg= "pcre_exec: null arguement passed"; + break; + case PCRE_ERROR_BADOPTION: + errmsg= "pcre_exec: bad option"; + break; + case PCRE_ERROR_BADMAGIC: + errmsg= "pcre_exec: bad magic - not a compiled regex"; + break; + case PCRE_ERROR_UNKNOWN_OPCODE: + errmsg= "pcre_exec: error in compiled regex"; + break; case PCRE_ERROR_NOMEMORY: errmsg= "pcre_exec: Out of memory"; break; + case PCRE_ERROR_NOSUBSTRING: + errmsg= "pcre_exec: no substring"; + break; + case PCRE_ERROR_MATCHLIMIT: + errmsg= "pcre_exec: match limit exceeded"; + break; + case PCRE_ERROR_CALLOUT: + errmsg= "pcre_exec: callout error"; + break; case PCRE_ERROR_BADUTF8: errmsg= "pcre_exec: Invalid utf8 byte sequence in the subject string"; break; + case PCRE_ERROR_BADUTF8_OFFSET: + errmsg= "pcre_exec: Started at invalid location within utf8 byte sequence"; + break; + case PCRE_ERROR_PARTIAL: + errmsg= "pcre_exec: partial match"; + break; + case PCRE_ERROR_INTERNAL: + errmsg= "pcre_exec: internal error"; + break; + case PCRE_ERROR_BADCOUNT: + errmsg= "pcre_exec: ovesize is negative"; + break; + case PCRE_ERROR_RECURSIONLIMIT: + my_snprintf(buf, sizeof(buf), "pcre_exec: recursion limit of %ld exceeded", + m_pcre_extra.match_limit_recursion); + errmsg= buf; + break; + case PCRE_ERROR_BADNEWLINE: + errmsg= "pcre_exec: bad newline options"; + break; + case PCRE_ERROR_BADOFFSET: + errmsg= "pcre_exec: start offset negative or greater than string length"; + break; + case PCRE_ERROR_SHORTUTF8: + errmsg= "pcre_exec: ended in middle of utf8 sequence"; + break; + case PCRE_ERROR_JIT_STACKLIMIT: + errmsg= "pcre_exec: insufficient stack memory for JIT compile"; + break; case PCRE_ERROR_RECURSELOOP: errmsg= "pcre_exec: Recursion loop detected"; break; + case PCRE_ERROR_BADMODE: + errmsg= "pcre_exec: compiled pattern passed to wrong bit library function"; + break; + case PCRE_ERROR_BADENDIANNESS: + errmsg= "pcre_exec: compiled pattern passed to wrong endianness processor"; + break; + case PCRE_ERROR_JIT_BADOPTION: + errmsg= "pcre_exec: bad jit option"; + break; + case PCRE_ERROR_BADLENGTH: + errmsg= "pcre_exec: negative length"; + break; default: /* As other error codes should normally not happen, From b30311e52a614a199e54767bb77d0419ad2d49c1 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 9 Apr 2017 13:30:59 +1000 Subject: [PATCH 103/148] MDEV-12420: pcre recursion overflow test case --- mysql-test/r/func_regexp_pcre.result | 5 +++++ mysql-test/t/func_regexp_pcre.test | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/mysql-test/r/func_regexp_pcre.result b/mysql-test/r/func_regexp_pcre.result index aa090c9faf6..af7230d2ad0 100644 --- a/mysql-test/r/func_regexp_pcre.result +++ b/mysql-test/r/func_regexp_pcre.result @@ -874,3 +874,8 @@ SET @regCheck= '\\xE0\\x01'; SELECT CAST(0xE001 AS BINARY) REGEXP @regCheck; CAST(0xE001 AS BINARY) REGEXP @regCheck 1 +# MDEV-12420: Testing recursion overflow +SELECT 1 FROM dual WHERE ('Alpha,Bravo,Charlie,Delta,Echo,Foxtrot,StrataCentral,Golf,Hotel,India,Juliet,Kilo,Lima,Mike,StrataL3,November,Oscar,StrataL2,Sand,P3,P4SwitchTest,Arsys,Poppa,ExtensionMgr,Arp,Quebec,Romeo,StrataApiV2,PtReyes,Sierra,SandAcl,Arrow,Artools,BridgeTest,Tango,SandT,PAlaska,Namespace,Agent,Qos,PatchPanel,ProjectReport,Ark,Gimp,Agent,SliceAgent,Arnet,Bgp,Ale,Tommy,Central,AsicPktTestLib,Hsc,SandL3,Abuild,Pca9555,Standby,ControllerDut,CalSys,SandLib,Sb820,PointV2,BfnLib,Evpn,BfnSdk,Sflow,ManagementActive,AutoTest,GatedTest,Bgp,Sand,xinetd,BfnAgentLib,bf-utils,Hello,BfnState,Eos,Artest,Qos,Scd,ThermoMgr,Uniform,EosUtils,Eb,FanController,Central,BfnL3,BfnL2,tcp_wrappers,Victor,Environment,Route,Failover,Whiskey,Xray,Gimp,BfnFixed,Strata,SoCal,XApi,Msrp,XpProfile,tcpdump,PatchPanel,ArosTest,FhTest,Arbus,XpAcl,MacConc,XpApi,telnet,QosTest,Alpha2,BfnVlan,Stp,VxlanControllerTest,MplsAgent,Bravo2,Lanz,BfnMbb,Intf,XCtrl,Unicast,SandTunnel,L3Unicast,Ipsec,MplsTest,Rsvp,EthIntf,StageMgr,Sol,MplsUtils,Nat,Ira,P4NamespaceDut,Counters,Charlie2,Aqlc,Mlag,Power,OpenFlow,Lag,RestApi,BfdTest,strongs,Sfa,CEosUtils,Adt746,MaintenanceMode,MlagDut,EosImage,IpEth,MultiProtocol,Launcher,Max3179,Snmp,Acl,IpEthTest,PhyEee,bf-syslibs,tacc,XpL2,p4-ar-switch,p4-bf-switch,LdpTest,BfnPhy,Mirroring,Phy6,Ptp' REGEXP '^((?!\b(Strata|StrataApi|StrataApiV2)\b).)*$'); +1 +Warnings: +Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp diff --git a/mysql-test/t/func_regexp_pcre.test b/mysql-test/t/func_regexp_pcre.test index c9b4c10007d..8e3adad0037 100644 --- a/mysql-test/t/func_regexp_pcre.test +++ b/mysql-test/t/func_regexp_pcre.test @@ -426,3 +426,7 @@ SELECT 0xE001 REGEXP @regCheck; SET NAMES latin1; SET @regCheck= '\\xE0\\x01'; SELECT CAST(0xE001 AS BINARY) REGEXP @regCheck; + +--echo # MDEV-12420: Testing recursion overflow +--replace_regex /[0-9]+ exceeded/NUM exceeded/ +SELECT 1 FROM dual WHERE ('Alpha,Bravo,Charlie,Delta,Echo,Foxtrot,StrataCentral,Golf,Hotel,India,Juliet,Kilo,Lima,Mike,StrataL3,November,Oscar,StrataL2,Sand,P3,P4SwitchTest,Arsys,Poppa,ExtensionMgr,Arp,Quebec,Romeo,StrataApiV2,PtReyes,Sierra,SandAcl,Arrow,Artools,BridgeTest,Tango,SandT,PAlaska,Namespace,Agent,Qos,PatchPanel,ProjectReport,Ark,Gimp,Agent,SliceAgent,Arnet,Bgp,Ale,Tommy,Central,AsicPktTestLib,Hsc,SandL3,Abuild,Pca9555,Standby,ControllerDut,CalSys,SandLib,Sb820,PointV2,BfnLib,Evpn,BfnSdk,Sflow,ManagementActive,AutoTest,GatedTest,Bgp,Sand,xinetd,BfnAgentLib,bf-utils,Hello,BfnState,Eos,Artest,Qos,Scd,ThermoMgr,Uniform,EosUtils,Eb,FanController,Central,BfnL3,BfnL2,tcp_wrappers,Victor,Environment,Route,Failover,Whiskey,Xray,Gimp,BfnFixed,Strata,SoCal,XApi,Msrp,XpProfile,tcpdump,PatchPanel,ArosTest,FhTest,Arbus,XpAcl,MacConc,XpApi,telnet,QosTest,Alpha2,BfnVlan,Stp,VxlanControllerTest,MplsAgent,Bravo2,Lanz,BfnMbb,Intf,XCtrl,Unicast,SandTunnel,L3Unicast,Ipsec,MplsTest,Rsvp,EthIntf,StageMgr,Sol,MplsUtils,Nat,Ira,P4NamespaceDut,Counters,Charlie2,Aqlc,Mlag,Power,OpenFlow,Lag,RestApi,BfdTest,strongs,Sfa,CEosUtils,Adt746,MaintenanceMode,MlagDut,EosImage,IpEth,MultiProtocol,Launcher,Max3179,Snmp,Acl,IpEthTest,PhyEee,bf-syslibs,tacc,XpL2,p4-ar-switch,p4-bf-switch,LdpTest,BfnPhy,Mirroring,Phy6,Ptp' REGEXP '^((?!\b(Strata|StrataApi|StrataApiV2)\b).)*$'); From 602b5e4c498ad2e2d045adfa4fd1478ac437582a Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 18 Apr 2017 17:20:34 +1000 Subject: [PATCH 104/148] WIP: global readonly variable pcre_frame_size --- include/my_sys.h | 3 +++ mysys/my_init.c | 2 ++ sql/item_cmpfunc.h | 8 +++++++- sql/mysqld.cc | 4 ++++ sql/sql_parse.cc | 8 ++++++++ sql/sql_parse.h | 1 + sql/sys_vars.cc | 8 ++++++++ 7 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/my_sys.h b/include/my_sys.h index 5b0a11408a4..395d0956430 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -227,6 +227,9 @@ extern void (*fatal_error_handler_hook)(uint my_err, const char *str, myf MyFlags); extern uint my_file_limit; extern ulonglong my_thread_stack_size; +#ifndef EMBEDDED_LIBRARY +extern ulonglong my_pcre_frame_size; +#endif extern int sf_leaking_memory; /* set to 1 to disable memleak detection */ extern void (*proc_info_hook)(void *, const PSI_stage_info *, PSI_stage_info *, diff --git a/mysys/my_init.c b/mysys/my_init.c index dee41e1202a..206f96827c3 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -45,6 +45,8 @@ my_bool my_init_done= 0; uint mysys_usage_id= 0; /* Incremented for each my_init() */ ulonglong my_thread_stack_size= (sizeof(void*) <= 4)? 65536: ((256-16)*1024); +/* http://pcre.org/original/doc/html/pcrestack.html - replaced by init_pcre value */ +ulonglong my_pcre_frame_size= 640 + 16; static ulong atoi_octal(const char *str) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index bd552bfc952..b5b94888330 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -25,6 +25,7 @@ #include "thr_malloc.h" /* sql_calloc */ #include "item_func.h" /* Item_int_func, Item_bool_func */ +long check_stack_available(long margin, uchar *dummy); #define PCRE_STATIC 1 /* Important on Windows */ #include "pcre.h" /* pcre header file */ @@ -1576,8 +1577,13 @@ public: m_library_charset(&my_charset_utf8_general_ci), m_subpatterns_needed(0) { +#ifndef EMBEDDED_LIBRARY + uchar dummy; m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION; - m_pcre_extra.match_limit_recursion= 100L; + m_pcre_extra.match_limit_recursion= check_stack_available(100, &dummy) / my_pcre_frame_size; +#else + m_pcre_extra.flags= 0L; +#endif } int default_regex_flags(); void init(CHARSET_INFO *data_charset, int extra_flags, uint nsubpatterns) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 79966f6f5e6..f6c6778e906 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -100,6 +100,7 @@ #include "sp_rcontext.h" #include "sp_cache.h" #include "sql_reload.h" // reload_acl_and_cache +#include "pcre.h" #ifdef HAVE_POLL_H #include @@ -3503,6 +3504,9 @@ static void init_pcre() pcre_free= pcre_stack_free= my_str_free_mysqld; #ifndef EMBEDDED_LIBRARY pcre_stack_guard= check_enough_stack_size_slow; + /* my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) + 16; + http://pcre.org/original/doc/html/pcrestack.html has reason for + 16 + my_pcre_frame_size= -pcre_match(NULL, NULL, NULL, 0, NULL, NULL, 0) + 16; */ #endif } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e059be4860b..edeb34418b2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6208,6 +6208,14 @@ bool check_stack_overrun(THD *thd, long margin, return 0; } +long check_stack_available(long margin, + uchar *buf __attribute__((unused))) +{ + long stack_top; + DBUG_ASSERT(current_thd); + return my_thread_stack_size - margin \ + - used_stack(current_thd->thread_stack,(char*) &stack_top); +} #define MY_YACC_INIT 1000 // Start with big alloc #define MY_YACC_MAX 32000 // Because of 'short' diff --git a/sql/sql_parse.h b/sql/sql_parse.h index fa414911093..b67692fec90 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -134,6 +134,7 @@ bool check_simple_select(); Item *normalize_cond(Item *cond); Item *negate_expression(THD *thd, Item *expr); bool check_stack_overrun(THD *thd, long margin, uchar *dummy); +long check_stack_available(long margin, uchar *dummy); /* Variables */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5ff79a2f235..e50217a4459 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2493,6 +2493,14 @@ static Sys_var_ulonglong Sys_thread_stack( VALID_RANGE(128*1024, ULONGLONG_MAX), DEFAULT(DEFAULT_THREAD_STACK), BLOCK_SIZE(1024)); +#ifndef EMBEDDED_LIBRARY +static Sys_var_ulonglong Sys_my_pcre_frame_size( + "pcre_frame_size", "Frame size for pcre_recursion", + GLOBAL_VAR(my_pcre_frame_size), NO_CMD_LINE, + VALID_RANGE(500,1024), DEFAULT(640 + 16), 1, NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0)); +#endif + static Sys_var_charptr Sys_tmpdir( "tmpdir", "Path for temporary files. Several paths may " "be specified, separated by a " From 52aa200919b1fd9357c05bcdfc66a42e51f242b3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 11 May 2017 19:48:42 +0200 Subject: [PATCH 105/148] MDEV-12420 max_recursive_iterations did not prevent a stack-overflow and segfault post-review fixes * move pcre-specific variable out of mysys * don't use current_thd * move a commonly used macro to my_sys.h * remove new sysvar --- include/my_sys.h | 9 ++++++--- mysys/lf_alloc-pin.c | 6 ------ mysys/my_init.c | 2 -- sql/item_cmpfunc.cc | 9 +++++++++ sql/item_cmpfunc.h | 11 +++-------- sql/mysqld.cc | 6 +++--- sql/mysqld.h | 2 ++ sql/sql_parse.cc | 16 +--------------- sql/sql_parse.h | 1 - sql/sys_vars.cc | 8 -------- 10 files changed, 24 insertions(+), 46 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 395d0956430..22ed7616f1c 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -227,9 +227,6 @@ extern void (*fatal_error_handler_hook)(uint my_err, const char *str, myf MyFlags); extern uint my_file_limit; extern ulonglong my_thread_stack_size; -#ifndef EMBEDDED_LIBRARY -extern ulonglong my_pcre_frame_size; -#endif extern int sf_leaking_memory; /* set to 1 to disable memleak detection */ extern void (*proc_info_hook)(void *, const PSI_stage_info *, PSI_stage_info *, @@ -909,6 +906,12 @@ extern ulonglong my_getcputime(void); #define hrtime_sec_part(X) ((ulong)((X).val % HRTIME_RESOLUTION)) #define my_time(X) hrtime_to_time(my_hrtime()) +#if STACK_DIRECTION < 0 +#define available_stack_size(CUR,END) (long) ((char*)(CUR) - (char*)(END)) +#else +#define available_stack_size(CUR,END) (long) ((char*)(END) - (char*)(CUR)) +#endif + #ifdef HAVE_SYS_MMAN_H #include diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 282433ea48d..a60a2ae657c 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -328,12 +328,6 @@ static int match_pins(LF_PINS *el, void *addr) return 0; } -#if STACK_DIRECTION < 0 -#define available_stack_size(CUR,END) (long) ((char*)(CUR) - (char*)(END)) -#else -#define available_stack_size(CUR,END) (long) ((char*)(END) - (char*)(CUR)) -#endif - #define next_node(P, X) (*((uchar * volatile *)(((uchar *)(X)) + (P)->free_ptr_offset))) #define anext_node(X) next_node(&allocator->pinbox, (X)) diff --git a/mysys/my_init.c b/mysys/my_init.c index 206f96827c3..dee41e1202a 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -45,8 +45,6 @@ my_bool my_init_done= 0; uint mysys_usage_id= 0; /* Incremented for each my_init() */ ulonglong my_thread_stack_size= (sizeof(void*) <= 4)? 65536: ((256-16)*1024); -/* http://pcre.org/original/doc/html/pcrestack.html - replaced by init_pcre value */ -ulonglong my_pcre_frame_size= 640 + 16; static ulong atoi_octal(const char *str) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index bfad63f21f8..038a0ebabc2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5104,6 +5104,15 @@ int Regexp_processor_pcre::default_regex_flags() return default_regex_flags_pcre(current_thd); } +void Regexp_processor_pcre::set_recursion_limit(THD *thd) +{ + long stack_used; + DBUG_ASSERT(thd == current_thd); + stack_used= available_stack_size(thd->thread_stack, &stack_used); + m_pcre_extra.match_limit_recursion= + (my_thread_stack_size - stack_used)/my_pcre_frame_size; +} + /** Convert string to lib_charset, if needed. diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b5b94888330..17ad1bd8c7d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -25,7 +25,6 @@ #include "thr_malloc.h" /* sql_calloc */ #include "item_func.h" /* Item_int_func, Item_bool_func */ -long check_stack_available(long margin, uchar *dummy); #define PCRE_STATIC 1 /* Important on Windows */ #include "pcre.h" /* pcre header file */ @@ -1577,15 +1576,11 @@ public: m_library_charset(&my_charset_utf8_general_ci), m_subpatterns_needed(0) { -#ifndef EMBEDDED_LIBRARY - uchar dummy; - m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION; - m_pcre_extra.match_limit_recursion= check_stack_available(100, &dummy) / my_pcre_frame_size; -#else - m_pcre_extra.flags= 0L; -#endif + m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION; + m_pcre_extra.match_limit_recursion= 100L; } int default_regex_flags(); + void set_recursion_limit(THD *); void init(CHARSET_INFO *data_charset, int extra_flags, uint nsubpatterns) { m_library_flags= default_regex_flags() | extra_flags | diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f6c6778e906..a8fef1bd8a3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3497,6 +3497,7 @@ static void init_libstrings() #endif } +ulonglong my_pcre_frame_size; static void init_pcre() { @@ -3504,9 +3505,8 @@ static void init_pcre() pcre_free= pcre_stack_free= my_str_free_mysqld; #ifndef EMBEDDED_LIBRARY pcre_stack_guard= check_enough_stack_size_slow; - /* my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) + 16; - http://pcre.org/original/doc/html/pcrestack.html has reason for + 16 - my_pcre_frame_size= -pcre_match(NULL, NULL, NULL, 0, NULL, NULL, 0) + 16; */ + /* See http://pcre.org/original/doc/html/pcrestack.html */ + my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) + 16; #endif } diff --git a/sql/mysqld.h b/sql/mysqld.h index 28ac871d858..e771a0c0da2 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -488,6 +488,8 @@ extern pthread_t signal_thread; extern struct st_VioSSLFd * ssl_acceptor_fd; #endif /* HAVE_OPENSSL */ +extern ulonglong my_pcre_frame_size; + /* The following variables were under INNODB_COMPABILITY_HOOKS */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index edeb34418b2..e57756217ca 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6163,12 +6163,6 @@ bool check_fk_parent_table_access(THD *thd, ****************************************************************************/ -#if STACK_DIRECTION < 0 -#define used_stack(A,B) (long) (A - B) -#else -#define used_stack(A,B) (long) (B - A) -#endif - #ifndef DBUG_OFF long max_stack_used; #endif @@ -6185,7 +6179,7 @@ bool check_stack_overrun(THD *thd, long margin, { long stack_used; DBUG_ASSERT(thd == current_thd); - if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= + if ((stack_used= available_stack_size(thd->thread_stack, &stack_used)) >= (long) (my_thread_stack_size - margin)) { thd->is_fatal_error= 1; @@ -6208,14 +6202,6 @@ bool check_stack_overrun(THD *thd, long margin, return 0; } -long check_stack_available(long margin, - uchar *buf __attribute__((unused))) -{ - long stack_top; - DBUG_ASSERT(current_thd); - return my_thread_stack_size - margin \ - - used_stack(current_thd->thread_stack,(char*) &stack_top); -} #define MY_YACC_INIT 1000 // Start with big alloc #define MY_YACC_MAX 32000 // Because of 'short' diff --git a/sql/sql_parse.h b/sql/sql_parse.h index b67692fec90..fa414911093 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -134,7 +134,6 @@ bool check_simple_select(); Item *normalize_cond(Item *cond); Item *negate_expression(THD *thd, Item *expr); bool check_stack_overrun(THD *thd, long margin, uchar *dummy); -long check_stack_available(long margin, uchar *dummy); /* Variables */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e50217a4459..5ff79a2f235 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2493,14 +2493,6 @@ static Sys_var_ulonglong Sys_thread_stack( VALID_RANGE(128*1024, ULONGLONG_MAX), DEFAULT(DEFAULT_THREAD_STACK), BLOCK_SIZE(1024)); -#ifndef EMBEDDED_LIBRARY -static Sys_var_ulonglong Sys_my_pcre_frame_size( - "pcre_frame_size", "Frame size for pcre_recursion", - GLOBAL_VAR(my_pcre_frame_size), NO_CMD_LINE, - VALID_RANGE(500,1024), DEFAULT(640 + 16), 1, NO_MUTEX_GUARD, - NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0)); -#endif - static Sys_var_charptr Sys_tmpdir( "tmpdir", "Path for temporary files. Several paths may " "be specified, separated by a " From f9264280d68dcbca2f9312c7d8620b2bcc9d0694 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 12 May 2017 14:27:49 +0200 Subject: [PATCH 106/148] MDEV-12761 Error return from external_lock make the server crash bunch of bugs when external_lock() fails on unlock: * mi_lock_database() used mi_mark_crashed() under share->intern_lock, but mi_mark_crashed() itself locks this mutex. * handler::close() required table to be unlocked, but failed external_lock didn't count as unlock * mysql_unlock_tables() ignored all unlock errors, but they still set the error status in stmt_da. --- mysql-test/r/myisam_debug.result | 12 ++++++++++++ mysql-test/t/myisam_debug.test | 13 +++++++++++++ sql/handler.cc | 2 +- sql/lock.cc | 3 +++ storage/myisam/mi_locking.c | 20 +++++++++----------- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/myisam_debug.result b/mysql-test/r/myisam_debug.result index 36a8fe6c724..77de991bafd 100644 --- a/mysql-test/r/myisam_debug.result +++ b/mysql-test/r/myisam_debug.result @@ -27,3 +27,15 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1,t2; +call mtr.add_suppression('Incorrect key file for table'); +create table t1 (a int, index(a)); +lock tables t1 write; +insert t1 values (1),(2),(1); +set @old_dbug=@@debug_dbug; +set debug_dbug='+d,mi_lock_database_failure'; +unlock tables; +Warnings: +Error 126 Incorrect key file for table './test/t1.MYI'; try to repair it +Error 1015 Can't lock file (errno: 22 "Invalid argument") +set debug_dbug=@old_dbug; +drop table t1; diff --git a/mysql-test/t/myisam_debug.test b/mysql-test/t/myisam_debug.test index 5b5d006bd22..57d423d88c9 100644 --- a/mysql-test/t/myisam_debug.test +++ b/mysql-test/t/myisam_debug.test @@ -59,3 +59,16 @@ KILL QUERY @thread_id; CHECK TABLE t1; DROP TABLE t1,t2; DISCONNECT insertConn; + +# +# MDEV-12761 Error return from external_lock make the server crash +# +call mtr.add_suppression('Incorrect key file for table'); +create table t1 (a int, index(a)); +lock tables t1 write; +insert t1 values (1),(2),(1); +set @old_dbug=@@debug_dbug; +set debug_dbug='+d,mi_lock_database_failure'; +unlock tables; +set debug_dbug=@old_dbug; +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index fc70ed5affc..e51f17f1712 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5944,7 +5944,7 @@ int handler::ha_external_lock(THD *thd, int lock_type) MYSQL_TABLE_LOCK_WAIT(m_psi, PSI_TABLE_EXTERNAL_LOCK, lock_type, { error= external_lock(thd, lock_type); }) - if (error == 0) + if (error == 0 || lock_type == F_UNLCK) { m_lock_type= lock_type; cached_table_flags= table_flags(); diff --git a/sql/lock.cc b/sql/lock.cc index 614341fcc43..29afcc8f578 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -380,12 +380,15 @@ static int lock_external(THD *thd, TABLE **tables, uint count) void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock) { DBUG_ENTER("mysql_unlock_tables"); + bool errors= thd->is_error(); if (sql_lock->table_count) unlock_external(thd, sql_lock->table, sql_lock->table_count); if (sql_lock->lock_count) thr_multi_unlock(sql_lock->locks, sql_lock->lock_count, 0); if (free_lock) my_free(sql_lock); + if (!errors) + thd->clear_error(); DBUG_VOID_RETURN; } diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 531b800c63e..1921926463e 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -29,7 +29,7 @@ static void mi_update_status_with_lock(MI_INFO *info); int mi_lock_database(MI_INFO *info, int lock_type) { - int error; + int error, mark_crashed= 0; uint count; MYISAM_SHARE *share=info->s; DBUG_ENTER("mi_lock_database"); @@ -52,6 +52,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) } error= 0; + DBUG_EXECUTE_IF ("mi_lock_database_failure", error= EINVAL;); mysql_mutex_lock(&share->intern_lock); if (share->kfile >= 0) /* May only be false on windows */ { @@ -75,17 +76,15 @@ int mi_lock_database(MI_INFO *info, int lock_type) &share->dirty_part_map, FLUSH_KEEP)) { - error=my_errno; + mark_crashed= error=my_errno; mi_print_error(info->s, HA_ERR_CRASHED); - mi_mark_crashed(info); /* Mark that table must be checked */ } if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) { if (end_io_cache(&info->rec_cache)) { - error=my_errno; + mark_crashed= error=my_errno; mi_print_error(info->s, HA_ERR_CRASHED); - mi_mark_crashed(info); } } if (!count) @@ -110,22 +109,19 @@ int mi_lock_database(MI_INFO *info, int lock_type) share->state.unique= info->last_unique= info->this_unique; share->state.update_count= info->last_loop= ++info->this_loop; if (mi_state_info_write(share->kfile, &share->state, 1)) - error=my_errno; + mark_crashed= error=my_errno; share->changed=0; if (myisam_flush) { if (mysql_file_sync(share->kfile, MYF(0))) - error= my_errno; + mark_crashed= error= my_errno; if (mysql_file_sync(info->dfile, MYF(0))) - error= my_errno; + mark_crashed= error= my_errno; } else share->not_flushed=1; if (error) - { mi_print_error(info->s, HA_ERR_CRASHED); - mi_mark_crashed(info); - } } if (info->lock_type != F_EXTRA_LCK) { @@ -260,6 +256,8 @@ int mi_lock_database(MI_INFO *info, int lock_type) } #endif mysql_mutex_unlock(&share->intern_lock); + if (mark_crashed) + mi_mark_crashed(info); DBUG_RETURN(error); } /* mi_lock_database */ From 71b45032421fe47fceabe419c63e79c44794428d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 12 May 2017 15:10:17 +0200 Subject: [PATCH 107/148] MDEV-9998 Fix issues caught by Clang's -Wpointer-bool-conversion warning remove useless checks and a couple of others --- libmysql/libmysql.c | 2 +- sql/log.cc | 2 +- sql/log_event_old.cc | 6 ++---- sql/slave.cc | 5 ++--- sql/sql_acl.cc | 6 ------ sql/sql_audit.cc | 3 +-- storage/connect/filamzip.cpp | 2 +- storage/connect/ha_connect.cc | 2 +- storage/connect/tabext.h | 2 +- storage/innobase/dict/dict0dict.cc | 5 ++--- storage/innobase/handler/ha_innodb.cc | 11 +++++------ storage/sphinx/ha_sphinx.cc | 2 +- storage/spider/spd_table.cc | 1 - storage/xtradb/handler/ha_innodb.cc | 11 +++++------ 14 files changed, 23 insertions(+), 37 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 3a08ea26b1d..3d787df804d 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1405,7 +1405,7 @@ void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net) DBUG_ASSERT(stmt != 0); stmt->last_errno= net->last_errno; - if (net->last_error && net->last_error[0]) + if (net->last_error[0]) strmov(stmt->last_error, net->last_error); strmov(stmt->sqlstate, net->sqlstate); diff --git a/sql/log.cc b/sql/log.cc index e99eefe4970..b80d65e20db 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1294,7 +1294,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */ user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE, - sctx->priv_user ? sctx->priv_user : "", "[", + sctx->priv_user, "[", sctx->user ? sctx->user : (thd->slave_thread ? "SQL_SLAVE" : ""), "] @ ", sctx->host ? sctx->host : "", " [", sctx->ip ? sctx->ip : "", "]", NullS) - diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 8bdb81f5283..73869e82f72 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1681,8 +1681,7 @@ int Old_rows_log_event::do_apply_event(rpl_group_info *rgi) default: rli->report(ERROR_LEVEL, thd->net.last_errno, NULL, "Error in %s event: row application failed. %s", - get_type_str(), - thd->net.last_error ? thd->net.last_error : ""); + get_type_str(), thd->net.last_error); thd->is_slave_error= 1; break; } @@ -1721,8 +1720,7 @@ int Old_rows_log_event::do_apply_event(rpl_group_info *rgi) "Error in %s event: error during transaction execution " "on table %s.%s. %s", get_type_str(), table->s->db.str, - table->s->table_name.str, - thd->net.last_error ? thd->net.last_error : ""); + table->s->table_name.str, thd->net.last_error); /* If one day we honour --skip-slave-errors in row-based replication, and diff --git a/sql/slave.cc b/sql/slave.cc index 8801e9e9ab5..3dd17fd7276 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -5647,8 +5647,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) TODO: handling `when' for SHOW SLAVE STATUS' snds behind */ - if ((memcmp(mi->master_log_name, hb.get_log_ident(), hb.get_ident_len()) - && mi->master_log_name != NULL) + if (memcmp(mi->master_log_name, hb.get_log_ident(), hb.get_ident_len()) || mi->master_log_pos > hb.log_pos) { /* missed events of heartbeat from the past */ @@ -6153,7 +6152,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir_ptr); /* we disallow empty users */ - if (mi->user == NULL || mi->user[0] == 0) + if (mi->user[0] == 0) { mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL, ER(ER_SLAVE_FATAL_ERROR), diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ac833e01ba7..c7e47c84db0 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -10639,12 +10639,6 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, /* global privileges */ grant->privilege= sctx->master_access; - if (!sctx->priv_user) - { - DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); - DBUG_VOID_RETURN; // it is slave - } - if (!thd->db || strcmp(db, thd->db)) { /* db privileges */ diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc index b659054a50b..60a75cb06e7 100644 --- a/sql/sql_audit.cc +++ b/sql/sql_audit.cc @@ -369,8 +369,7 @@ int initialize_audit_plugin(st_plugin_int *plugin) { st_mysql_audit *data= (st_mysql_audit*) plugin->plugin->info; - if (!data->class_mask || !data->event_notify || - !data->class_mask[0]) + if (!data->event_notify || !data->class_mask[0]) { sql_print_error("Plugin '%s' has invalid data.", plugin->name.str); diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 3d157da5e87..fa857837427 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -341,7 +341,7 @@ bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn, bool append) bool ZIPUTIL::addEntry(PGLOBAL g, char *entry) { //?? we dont need the stinking time - zip_fileinfo zi = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + zip_fileinfo zi = { {0, 0, 0, 0, 0, 0}, 0, 0, 0 }; getTime(zi.tmz_date); target = entry; diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index d1ab18f52d5..1f2bd0e5992 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1192,7 +1192,7 @@ char *ha_connect::GetRealString(const char *s) { char *sv; - if (IsPartitioned() && s && partname && *partname) { + if (IsPartitioned() && s && *partname) { sv= (char*)PlugSubAlloc(xp->g, NULL, 0); sprintf(sv, s, partname); PlugSubAlloc(xp->g, NULL, strlen(sv) + 1); diff --git a/storage/connect/tabext.h b/storage/connect/tabext.h index 2ef20c89f2c..5133bd9dd5f 100644 --- a/storage/connect/tabext.h +++ b/storage/connect/tabext.h @@ -7,7 +7,7 @@ /***********************************************************************/ #ifndef __TABEXT_H -#define __TABEXTF_H +#define __TABEXT_H #include "reldef.h" diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 6fd8afd2aee..b6ca02fa164 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -6251,6 +6251,7 @@ dict_set_corrupted_index_cache_only( dict_table_t* table) /*!< in/out: table */ { ut_ad(index != NULL); + ut_ad(table != NULL); ut_ad(mutex_own(&dict_sys->mutex)); ut_ad(!dict_table_is_comp(dict_sys->sys_tables)); ut_ad(!dict_table_is_comp(dict_sys->sys_indexes)); @@ -6260,9 +6261,7 @@ dict_set_corrupted_index_cache_only( if (dict_index_is_clust(index)) { dict_table_t* corrupt_table; - corrupt_table = (table != NULL) ? table : index->table; - ut_ad((index->table != NULL) || (table != NULL) - || index->table == table); + corrupt_table = table; if (corrupt_table) { corrupt_table->corrupted = TRUE; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 91a507ef1b9..1538471db4f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2000,12 +2000,11 @@ innobase_get_stmt( { const char* query = NULL; LEX_STRING *stmt = NULL; - if (thd) { - stmt = thd_query_string(thd); - if (stmt) { - *length = stmt->length; - query = stmt->str; - } + ut_ad(thd != NULL); + stmt = thd_query_string(thd); + if (stmt) { + *length = stmt->length; + query = stmt->str; } return (query); } diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index ff3b63465eb..3f035c7bc7d 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -911,7 +911,7 @@ bool sphinx_show_status ( THD * thd ) } // show last error or warning (either in addition to stats, or on their own) - if ( pTls && pTls->m_pHeadTable && pTls->m_pHeadTable->m_tStats.m_sLastMessage && pTls->m_pHeadTable->m_tStats.m_sLastMessage[0] ) + if ( pTls && pTls->m_pHeadTable && pTls->m_pHeadTable->m_tStats.m_sLastMessage[0] ) { const char * sMessageType = pTls->m_pHeadTable->m_tStats.m_bLastError ? "error" : "warning"; diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index ead335c07ea..66f558ecd91 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -517,7 +517,6 @@ int spider_free_share_alloc( ) { int roop_count; DBUG_ENTER("spider_free_share_alloc"); - if (share->dbton_bitmap) { for (roop_count = SPIDER_DBTON_SIZE - 1; roop_count >= 0; roop_count--) { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 9433ee4c7c5..12ae71508c7 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -2326,12 +2326,11 @@ innobase_get_stmt( { const char* query = NULL; LEX_STRING *stmt = NULL; - if (thd) { - stmt = thd_query_string(thd); - if (stmt) { - *length = stmt->length; - query = stmt->str; - } + ut_ad(thd != NULL); + stmt = thd_query_string(thd); + if (stmt) { + *length = stmt->length; + query = stmt->str; } return (query); } From a65623b3eb2695069791aa21d278b8bc751a560e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 12 May 2017 16:52:09 +0200 Subject: [PATCH 108/148] MDEV-11883 MariaDB crashes with out-of-memory when query information_schema CSV engine didn't expect CSM files to be read-only --- mysql-test/suite/csv/read_only.result | 30 +++++++++++++++++++++++++++ mysql-test/suite/csv/read_only.test | 19 +++++++++++++++++ storage/csv/ha_tina.cc | 15 ++++++++------ 3 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/csv/read_only.result create mode 100644 mysql-test/suite/csv/read_only.test diff --git a/mysql-test/suite/csv/read_only.result b/mysql-test/suite/csv/read_only.result new file mode 100644 index 00000000000..d6936681f65 --- /dev/null +++ b/mysql-test/suite/csv/read_only.result @@ -0,0 +1,30 @@ +create table t1 (a int not null) engine=csv; +insert t1 values (1),(2); +flush tables; +select * from information_schema.tables where table_schema='test'; +TABLE_CATALOG def +TABLE_SCHEMA test +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE NULL +VERSION NULL +ROW_FORMAT NULL +TABLE_ROWS NULL +AVG_ROW_LENGTH NULL +DATA_LENGTH NULL +MAX_DATA_LENGTH NULL +INDEX_LENGTH NULL +DATA_FREE NULL +AUTO_INCREMENT NULL +CREATE_TIME NULL +UPDATE_TIME NULL +CHECK_TIME NULL +TABLE_COLLATION NULL +CHECKSUM NULL +CREATE_OPTIONS NULL +TABLE_COMMENT File './test/t1.CSM' not found (Errcode: 13 "Permission denied") +Warnings: +Level Warning +Code 29 +Message File './test/t1.CSM' not found (Errcode: 13 "Permission denied") +drop table t1; diff --git a/mysql-test/suite/csv/read_only.test b/mysql-test/suite/csv/read_only.test new file mode 100644 index 00000000000..2af209182d0 --- /dev/null +++ b/mysql-test/suite/csv/read_only.test @@ -0,0 +1,19 @@ +# +# MDEV-11883 MariaDB crashes with out-of-memory when query information_schema +# +source include/have_csv.inc; + +let datadir=`select @@datadir`; + +create table t1 (a int not null) engine=csv; +insert t1 values (1),(2); +flush tables; + +chmod 0400 $datadir/test/t1.CSM; +chmod 0400 $datadir/test/t1.CSV; + +--replace_result $datadir ./ +query_vertical select * from information_schema.tables where table_schema='test'; + +drop table t1; + diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 92ac20a8f82..35596a59c86 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -289,7 +289,7 @@ static int read_meta_file(File meta_file, ha_rows *rows) mysql_file_seek(meta_file, 0, MY_SEEK_SET, MYF(0)); if (mysql_file_read(meta_file, (uchar*)meta_buffer, META_BUFFER_SIZE, 0) != META_BUFFER_SIZE) - DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + DBUG_RETURN(my_errno= HA_ERR_CRASHED_ON_USAGE); /* Parse out the meta data, we ignore version at the moment @@ -418,10 +418,13 @@ static int free_share(TINA_SHARE *share) int result_code= 0; if (!--share->use_count){ /* Write the meta file. Mark it as crashed if needed. */ - (void)write_meta_file(share->meta_file, share->rows_recorded, - share->crashed ? TRUE :FALSE); - if (mysql_file_close(share->meta_file, MYF(0))) - result_code= 1; + if (share->meta_file != -1) + { + (void)write_meta_file(share->meta_file, share->rows_recorded, + share->crashed ? TRUE :FALSE); + if (mysql_file_close(share->meta_file, MYF(0))) + result_code= 1; + } if (share->tina_write_opened) { if (mysql_file_close(share->tina_write_filedes, MYF(0))) @@ -930,7 +933,7 @@ int ha_tina::open(const char *name, int mode, uint open_options) if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR)) { free_share(share); - DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + DBUG_RETURN(my_errno ? my_errno : HA_ERR_CRASHED_ON_USAGE); } local_data_file_version= share->data_file_version; From a8773ef380609e238601dee94e026d99d4175696 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 13 May 2017 13:00:18 +0200 Subject: [PATCH 109/148] MDEV-12660 inconsistent mysql_stmt_close remove dead code: this "return rc" could've never happened, because reset_stmt_handle can only possibly fail if RESET_SERVER flag is used. But this "return rc" was confusing, it was under DBUG_ENTER (while not being DBUG_RETURN) and it was skipping required stmt cleanup at the end of the function. --- libmysql/libmysql.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 3d787df804d..c07fad38802 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -4713,8 +4713,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) { uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */ - if ((rc= reset_stmt_handle(stmt, RESET_ALL_BUFFERS | RESET_CLEAR_ERROR))) - return rc; + reset_stmt_handle(stmt, RESET_ALL_BUFFERS | RESET_CLEAR_ERROR); int4store(buff, stmt->stmt_id); if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))) From a3cf69e2e5ba8e3954b24bf3f8bcf8705c102f64 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 13 May 2017 13:52:58 +0200 Subject: [PATCH 110/148] MDEV-10936 CONNECT engine JDBC type can't find JdbcInterface Don't use instal_jar() from Use_Java.cmake - at least in CentOS 7 (cmake 2.8.12.2) it doesn't yet support the COMPONENT option. --- storage/connect/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index a602084b5bd..840ccdfb0a8 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -270,8 +270,8 @@ IF(CONNECT_WITH_JDBC) # Find required libraries and include directories SET (JAVA_SOURCES JdbcInterface.java) add_jar(JdbcInterface ${JAVA_SOURCES}) - install_jar(JdbcInterface DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/JavaWrappers.jar + ${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) add_definitions(-DJDBC_SUPPORT) ELSE() From 314f32c8c23a2be752691dfb77d929ac498a0478 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 16 May 2017 12:42:53 +0200 Subject: [PATCH 111/148] MDEV-5477 sphinxSE GROUP BY on multiple attributes Translate "multi:" to SPH_GROUPBY_MULTIPLE. SPH_GROUPBY_ATTRPAIR is still not supported. --- storage/sphinx/ha_sphinx.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 3f035c7bc7d..c196295f69e 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -216,7 +216,9 @@ enum ESphGroupBy SPH_GROUPBY_WEEK = 1, ///< group by week SPH_GROUPBY_MONTH = 2, ///< group by month SPH_GROUPBY_YEAR = 3, ///< group by year - SPH_GROUPBY_ATTR = 4 ///< group by attribute value + SPH_GROUPBY_ATTR = 4, ///< group by attribute value + SPH_GROUPBY_ATTRPAIR = 5, ///< group by sequential attrs pair (rendered redundant by 64bit attrs support; removed) + SPH_GROUPBY_MULTIPLE = 6 ///< group by on multiple attribute values }; /// known attribute types @@ -1555,6 +1557,7 @@ bool CSphSEQuery::ParseField ( char * sField ) { "month:", SPH_GROUPBY_MONTH }, { "year:", SPH_GROUPBY_YEAR }, { "attr:", SPH_GROUPBY_ATTR }, + { "multi:", SPH_GROUPBY_MULTIPLE } }; int i; From 24ff1793114fa9f15d493c26d879000307e6f00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 May 2017 13:53:15 +0300 Subject: [PATCH 112/148] 5.6.36 --- .../perfschema/r/start_server_1_digest.result | 7 +++ .../t/start_server_1_digest-master.opt | 1 + .../perfschema/t/start_server_1_digest.test | 15 ++++++ storage/perfschema/pfs.cc | 3 +- storage/perfschema/pfs_digest.cc | 5 +- storage/perfschema/unittest/pfs-t.cc | 46 ++++++++++++++----- .../perfschema/unittest/pfs_account-oom-t.cc | 4 +- .../perfschema/unittest/pfs_connect_attr-t.cc | 4 +- storage/perfschema/unittest/pfs_host-oom-t.cc | 4 +- .../perfschema/unittest/pfs_instr-oom-t.cc | 29 ++++++++++-- storage/perfschema/unittest/pfs_instr-t.cc | 9 ++-- .../unittest/pfs_instr_class-oom-t.cc | 4 +- .../perfschema/unittest/pfs_instr_class-t.cc | 4 +- storage/perfschema/unittest/pfs_misc-t.cc | 4 +- storage/perfschema/unittest/pfs_timer-t.cc | 4 +- storage/perfschema/unittest/pfs_user-oom-t.cc | 4 +- 16 files changed, 108 insertions(+), 39 deletions(-) create mode 100644 mysql-test/suite/perfschema/r/start_server_1_digest.result create mode 100644 mysql-test/suite/perfschema/t/start_server_1_digest-master.opt create mode 100644 mysql-test/suite/perfschema/t/start_server_1_digest.test diff --git a/mysql-test/suite/perfschema/r/start_server_1_digest.result b/mysql-test/suite/perfschema/r/start_server_1_digest.result new file mode 100644 index 00000000000..cf07022d344 --- /dev/null +++ b/mysql-test/suite/perfschema/r/start_server_1_digest.result @@ -0,0 +1,7 @@ +SELECT "Digest table has a size 1 and is full already." as use_case; +use_case +Digest table has a size 1 and is full already. +select SCHEMA_NAME, DIGEST, DIGEST_TEXT +from performance_schema.events_statements_summary_by_digest; +SCHEMA_NAME DIGEST DIGEST_TEXT +NULL NULL NULL diff --git a/mysql-test/suite/perfschema/t/start_server_1_digest-master.opt b/mysql-test/suite/perfschema/t/start_server_1_digest-master.opt new file mode 100644 index 00000000000..e59be3eb02f --- /dev/null +++ b/mysql-test/suite/perfschema/t/start_server_1_digest-master.opt @@ -0,0 +1 @@ +--performance-schema-digests-size=1 diff --git a/mysql-test/suite/perfschema/t/start_server_1_digest.test b/mysql-test/suite/perfschema/t/start_server_1_digest.test new file mode 100644 index 00000000000..998d9a5eebe --- /dev/null +++ b/mysql-test/suite/perfschema/t/start_server_1_digest.test @@ -0,0 +1,15 @@ +# ----------------------------------------------------------------------- +# Tests for the performance schema statement Digests. +# ----------------------------------------------------------------------- + +--source include/not_embedded.inc +--source include/have_perfschema.inc +--source include/no_protocol.inc + +SELECT "Digest table has a size 1 and is full already." as use_case; + +select SCHEMA_NAME, DIGEST, DIGEST_TEXT + from performance_schema.events_statements_summary_by_digest; + + + diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc index 3bbc0a4602e..18c58294b5c 100644 --- a/storage/perfschema/pfs.cc +++ b/storage/perfschema/pfs.cc @@ -3951,9 +3951,11 @@ static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker, switch (state->m_operation) { case PSI_FILE_STAT: + case PSI_FILE_RENAME: break; case PSI_FILE_STREAM_OPEN: case PSI_FILE_CREATE: + case PSI_FILE_OPEN: if (result != NULL) { PFS_file_class *klass= reinterpret_cast (state->m_class); @@ -3964,7 +3966,6 @@ static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker, state->m_file= reinterpret_cast (pfs_file); } break; - case PSI_FILE_OPEN: default: DBUG_ASSERT(false); break; diff --git a/storage/perfschema/pfs_digest.cc b/storage/perfschema/pfs_digest.cc index 5886c379b2f..3b5f1d35862 100644 --- a/storage/perfschema/pfs_digest.cc +++ b/storage/perfschema/pfs_digest.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -255,10 +255,11 @@ search: if (safe_index == 0) { /* Record [0] is reserved. */ - safe_index= 1; + continue; } /* Add a new record in digest stat array. */ + DBUG_ASSERT(safe_index < digest_max); pfs= &statements_digest_stat_array[safe_index]; if (pfs->m_lock.is_free()) diff --git a/storage/perfschema/unittest/pfs-t.cc b/storage/perfschema/unittest/pfs-t.cc index 8b24cee9eaf..7861c74a401 100644 --- a/storage/perfschema/unittest/pfs-t.cc +++ b/storage/perfschema/unittest/pfs-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -27,6 +27,8 @@ #include "stub_print_error.h" #include "stub_pfs_defaults.h" +void unload_performance_schema(); + /* test helpers, to simulate the setup */ void setup_thread(PSI_thread *t, bool enabled) @@ -126,7 +128,7 @@ void test_bootstrap() psi_2= boot->get_interface(PSI_VERSION_2); ok(psi_2 == NULL, "version 2"); - shutdown_performance_schema(); + unload_performance_schema(); } /* @@ -183,6 +185,28 @@ PSI * load_perfschema() return (PSI*) psi; } +void unload_performance_schema() +{ + cleanup_table_share(); + cleanup_instruments(); + cleanup_sync_class(); + cleanup_thread_class(); + cleanup_table_share(); + cleanup_file_class(); + cleanup_stage_class(); + cleanup_statement_class(); + cleanup_socket_class(); + cleanup_events_waits_history_long(); + cleanup_events_stages_history_long(); + cleanup_events_statements_history_long(); + cleanup_table_share_hash(); + cleanup_file_hash(); + cleanup_digest(); + PFS_atomic::cleanup(); + + shutdown_performance_schema(); +} + void test_bad_registration() { PSI *psi; @@ -581,8 +605,7 @@ void test_bad_registration() psi->register_socket("X", bad_socket_3, 1); ok(dummy_socket_key == 2, "assigned key"); - - shutdown_performance_schema(); + unload_performance_schema(); } void test_init_disabled() @@ -1016,7 +1039,7 @@ void test_init_disabled() socket_A1= psi->init_socket(99, NULL, NULL, 0); ok(socket_A1 == NULL, "broken socket key not instrumented"); - shutdown_performance_schema(); + unload_performance_schema(); } void test_locker_disabled() @@ -1321,8 +1344,9 @@ void test_locker_disabled() ok(socket_A1 != NULL, "instrumented"); /* Socket thread owner has not been set */ socket_locker= psi->start_socket_wait(&socket_state, socket_A1, PSI_SOCKET_SEND, 12, "foo.cc", 12); - ok(socket_locker == NULL, "no locker (no thread owner)"); - + ok(socket_locker != NULL, "locker (owner not used)"); + psi->end_socket_wait(socket_locker, 10); + /* Pretend the running thread is not instrumented */ /* ---------------------------------------------- */ @@ -1350,7 +1374,7 @@ void test_locker_disabled() socket_locker= psi->start_socket_wait(&socket_state, socket_A1, PSI_SOCKET_SEND, 12, "foo.cc", 12); ok(socket_locker == NULL, "no locker"); - shutdown_performance_schema(); + unload_performance_schema(); } void test_file_instrumentation_leak() @@ -1437,7 +1461,7 @@ void test_file_instrumentation_leak() file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_WRITE); ok(file_locker == NULL, "no locker, no leak"); - shutdown_performance_schema(); + unload_performance_schema(); } void test_enabled() @@ -1473,7 +1497,7 @@ void test_enabled() { & cond_key_B, "C-B", 0} }; - shutdown_performance_schema(); + unload_performance_schema(); #endif } @@ -1642,6 +1666,6 @@ int main(int, char **) plan(216); MY_INIT("pfs-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_account-oom-t.cc b/storage/perfschema/unittest/pfs_account-oom-t.cc index ef8a7c195e0..fccb9ef2e43 100644 --- a/storage/perfschema/unittest/pfs_account-oom-t.cc +++ b/storage/perfschema/unittest/pfs_account-oom-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2011, 2017, 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 @@ -111,6 +111,6 @@ int main(int, char **) plan(6); MY_INIT("pfs_account-oom-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_connect_attr-t.cc b/storage/perfschema/unittest/pfs_connect_attr-t.cc index 7bee1d063a1..ecf790eeede 100644 --- a/storage/perfschema/unittest/pfs_connect_attr-t.cc +++ b/storage/perfschema/unittest/pfs_connect_attr-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -341,5 +341,5 @@ int main(int, char **) diag("skipping the cp1251 tests : missing character set"); plan(59 + (cs_cp1251 ? 10 : 0)); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_host-oom-t.cc b/storage/perfschema/unittest/pfs_host-oom-t.cc index 6627dd48df2..95a375c4d10 100644 --- a/storage/perfschema/unittest/pfs_host-oom-t.cc +++ b/storage/perfschema/unittest/pfs_host-oom-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2011, 2017, 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 @@ -111,6 +111,6 @@ int main(int, char **) plan(6); MY_INIT("pfs_host-oom-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_instr-oom-t.cc b/storage/perfschema/unittest/pfs_instr-oom-t.cc index 161060aa6bf..f58d9026c7d 100644 --- a/storage/perfschema/unittest/pfs_instr-oom-t.cc +++ b/storage/perfschema/unittest/pfs_instr-oom-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -355,6 +355,11 @@ void test_oom() rc= init_instruments(& param); ok(rc == 1, "oom (per thread wait)"); + cleanup_sync_class(); + cleanup_thread_class(); + cleanup_file_class(); + cleanup_instruments(); + param.m_enabled= true; param.m_mutex_class_sizing= 0; param.m_rwlock_class_sizing= 0; @@ -432,6 +437,8 @@ void test_oom() init_event_name_sizing(& param); rc= init_instruments(& param); ok(rc == 1, "oom (thread stages history sizing)"); + + cleanup_thread_class(); cleanup_instruments(); param.m_enabled= true; @@ -467,6 +474,9 @@ void test_oom() init_event_name_sizing(& param); rc= init_instruments(& param); ok(rc == 1, "oom (per thread stages)"); + + cleanup_stage_class(); + cleanup_thread_class(); cleanup_instruments(); param.m_enabled= true; @@ -502,6 +512,8 @@ void test_oom() init_event_name_sizing(& param); rc= init_instruments(& param); ok(rc == 1, "oom (thread statements history sizing)"); + + cleanup_thread_class(); cleanup_instruments(); param.m_enabled= true; @@ -537,6 +549,9 @@ void test_oom() init_event_name_sizing(& param); rc= init_instruments(& param); ok(rc == 1, "oom (per thread statements)"); + + cleanup_statement_class(); + cleanup_thread_class(); cleanup_instruments(); param.m_enabled= true; @@ -572,6 +587,8 @@ void test_oom() init_event_name_sizing(& param); rc= init_instruments(& param); ok(rc == 1, "oom (global waits)"); + + cleanup_sync_class(); cleanup_instruments(); param.m_enabled= true; @@ -609,8 +626,10 @@ void test_oom() ok(rc == 0, "init stage class"); rc= init_instruments(& param); ok(rc == 1, "oom (global stages)"); - cleanup_instruments(); + + cleanup_sync_class(); cleanup_stage_class(); + cleanup_instruments(); param.m_enabled= true; param.m_mutex_class_sizing= 10; @@ -647,8 +666,10 @@ void test_oom() ok(rc == 0, "init statement class"); rc= init_instruments(& param); ok(rc == 1, "oom (global statements)"); - cleanup_instruments(); + + cleanup_sync_class(); cleanup_statement_class(); + cleanup_instruments(); } void do_all_tests() @@ -665,6 +686,6 @@ int main(int, char **) plan(20); MY_INIT("pfs_instr-oom-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_instr-t.cc b/storage/perfschema/unittest/pfs_instr-t.cc index 3cc4c48388d..f457bf1f811 100644 --- a/storage/perfschema/unittest/pfs_instr-t.cc +++ b/storage/perfschema/unittest/pfs_instr-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -23,10 +23,11 @@ #include +PFS_global_param param; + void test_no_instruments() { int rc; - PFS_global_param param; memset(& param, 0xFF, sizeof(param)); param.m_enabled= true; @@ -86,7 +87,6 @@ void test_no_instances() PFS_file *file; PFS_socket *socket; PFS_table *table; - PFS_global_param param; memset(& param, 0xFF, sizeof(param)); param.m_enabled= true; @@ -227,7 +227,6 @@ void test_with_instances() PFS_socket *socket_2; PFS_table *table_1; PFS_table *table_2; - PFS_global_param param; memset(& param, 0xFF, sizeof(param)); param.m_enabled= true; @@ -417,6 +416,6 @@ int main(int, char **) plan(103); MY_INIT("pfs_instr-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc index e98250d8567..9b01044e31f 100644 --- a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc +++ b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -67,6 +67,6 @@ int main(int, char **) plan(9); MY_INIT("pfs_instr_info-oom-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_instr_class-t.cc b/storage/perfschema/unittest/pfs_instr_class-t.cc index ee483312e3c..b58ae2e371d 100644 --- a/storage/perfschema/unittest/pfs_instr_class-t.cc +++ b/storage/perfschema/unittest/pfs_instr_class-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -673,6 +673,6 @@ int main(int, char **) plan(181); MY_INIT("pfs_instr_info-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_misc-t.cc b/storage/perfschema/unittest/pfs_misc-t.cc index a0fff2f593c..d960b5fe0a0 100644 --- a/storage/perfschema/unittest/pfs_misc-t.cc +++ b/storage/perfschema/unittest/pfs_misc-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2015, 2017, 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 @@ -66,6 +66,6 @@ int main(int, char **) plan(2); MY_INIT("pfs_misc-t"); do_all_tests(); - return exit_status(); + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_timer-t.cc b/storage/perfschema/unittest/pfs_timer-t.cc index 9c9ae0f75f1..7ea1326365e 100644 --- a/storage/perfschema/unittest/pfs_timer-t.cc +++ b/storage/perfschema/unittest/pfs_timer-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2017, 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 @@ -117,6 +117,6 @@ int main(int, char **) plan(5); MY_INIT("pfs_timer-t"); do_all_tests(); - return 0; + return (exit_status()); } diff --git a/storage/perfschema/unittest/pfs_user-oom-t.cc b/storage/perfschema/unittest/pfs_user-oom-t.cc index 0e4c5eb3411..87558e9e813 100644 --- a/storage/perfschema/unittest/pfs_user-oom-t.cc +++ b/storage/perfschema/unittest/pfs_user-oom-t.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2011, 2017, 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 @@ -110,6 +110,6 @@ int main(int, char **) plan(6); MY_INIT("pfs_user-oom-t"); do_all_tests(); - return 0; + return (exit_status()); } From 8e1056bce073530e815939ed596581980952d729 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 16 May 2017 13:14:03 +0200 Subject: [PATCH 113/148] MDEV-12216 main.mysqld--help 'unix' test is failing when profiling support is not present --- mysql-test/t/mysqld--help.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index cee9337ccc3..96774d829ec 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -3,6 +3,7 @@ # --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/have_profiling.inc --source include/platform.inc # From 360a4a037271d65ab6471f7ab3f9b6a893d90a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 May 2017 14:16:11 +0300 Subject: [PATCH 114/148] 5.6.36-82.0 --- storage/xtradb/btr/btr0sea.cc | 2 +- storage/xtradb/buf/buf0buf.cc | 2 +- storage/xtradb/buf/buf0dblwr.cc | 4 +- storage/xtradb/buf/buf0dump.cc | 4 +- storage/xtradb/buf/buf0flu.cc | 38 ++- storage/xtradb/dict/dict0boot.cc | 7 +- storage/xtradb/dict/dict0dict.cc | 21 +- storage/xtradb/dict/dict0stats.cc | 15 +- storage/xtradb/dict/dict0stats_bg.cc | 4 +- storage/xtradb/fil/fil0fil.cc | 24 +- storage/xtradb/fts/fts0que.cc | 20 ++ storage/xtradb/handler/ha_innodb.cc | 181 +++++++----- storage/xtradb/handler/ha_innodb.h | 6 +- storage/xtradb/handler/handler0alter.cc | 6 +- storage/xtradb/include/buf0dblwr.h | 4 +- storage/xtradb/include/dict0dict.h | 11 +- storage/xtradb/include/dict0dict.ic | 9 +- storage/xtradb/include/fil0fil.h | 14 +- storage/xtradb/include/ha0ha.h | 6 +- storage/xtradb/include/log0online.h | 2 +- storage/xtradb/include/os0file.h | 335 ++++++++++++++++++---- storage/xtradb/include/os0file.ic | 215 ++++++++++++-- storage/xtradb/include/row0mysql.h | 18 +- storage/xtradb/include/srv0srv.h | 17 +- storage/xtradb/include/srv0start.h | 4 +- storage/xtradb/include/trx0xa.h | 15 +- storage/xtradb/include/univ.i | 12 +- storage/xtradb/log/log0log.cc | 19 +- storage/xtradb/log/log0online.cc | 62 ++-- storage/xtradb/log/log0recv.cc | 4 +- storage/xtradb/os/os0file.cc | 240 ++++++++++------ storage/xtradb/pars/pars0opt.cc | 6 +- storage/xtradb/pars/pars0pars.cc | 3 +- storage/xtradb/row/row0log.cc | 17 +- storage/xtradb/row/row0merge.cc | 35 ++- storage/xtradb/row/row0sel.cc | 361 ++++++++++++++++++++---- storage/xtradb/srv/srv0srv.cc | 41 ++- storage/xtradb/srv/srv0start.cc | 66 +++-- storage/xtradb/trx/trx0purge.cc | 5 +- storage/xtradb/trx/trx0rec.cc | 3 +- storage/xtradb/trx/trx0roll.cc | 4 +- storage/xtradb/trx/trx0sys.cc | 18 +- 42 files changed, 1420 insertions(+), 460 deletions(-) diff --git a/storage/xtradb/btr/btr0sea.cc b/storage/xtradb/btr/btr0sea.cc index 78cb9dfd6e0..2ed383b0dcb 100644 --- a/storage/xtradb/btr/btr0sea.cc +++ b/storage/xtradb/btr/btr0sea.cc @@ -199,7 +199,7 @@ btr_search_sys_create( &btr_search_latch_arr[i], SYNC_SEARCH_SYS); btr_search_sys->hash_tables[i] - = ha_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0); + = ib_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0); #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG btr_search_sys->hash_tables[i]->adaptive = TRUE; diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 978d94f07ec..b946b1dd4e4 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -1413,7 +1413,7 @@ buf_pool_init_instance( ut_a(srv_n_page_hash_locks != 0); ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS); - buf_pool->page_hash = ha_create(2 * buf_pool->curr_size, + buf_pool->page_hash = ib_create(2 * buf_pool->curr_size, srv_n_page_hash_locks, MEM_HEAP_FOR_PAGE_HASH, SYNC_BUF_PAGE_HASH); diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc index 3c12d6da73f..46296814bb6 100644 --- a/storage/xtradb/buf/buf0dblwr.cc +++ b/storage/xtradb/buf/buf0dblwr.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -355,7 +355,7 @@ recovery, this function loads the pages from double write buffer into memory. */ void buf_dblwr_init_or_load_pages( /*=========================*/ - os_file_t file, + pfs_os_file_t file, char* path, bool load_corrupt_pages) { diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc index 88ff4399115..8ecdedc613b 100644 --- a/storage/xtradb/buf/buf0dump.cc +++ b/storage/xtradb/buf/buf0dump.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2017, 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 @@ -597,6 +597,7 @@ DECLARE_THREAD(buf_dump_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_ad(!srv_read_only_mode); srv_buf_dump_thread_active = TRUE; @@ -632,6 +633,7 @@ DECLARE_THREAD(buf_dump_thread)( srv_buf_dump_thread_active = FALSE; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index 5dd2efcf0c3..36e24fb3a1b 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -356,6 +356,7 @@ buf_flush_insert_into_flush_list( buf_block_t* block, /*!< in/out: block which is modified */ lsn_t lsn) /*!< in: oldest modification */ { + ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE); ut_ad(log_flush_order_mutex_own()); ut_ad(mutex_own(&block->mutex)); @@ -414,6 +415,7 @@ buf_flush_insert_sorted_into_flush_list( buf_page_t* prev_b; buf_page_t* b; + ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE); ut_ad(log_flush_order_mutex_own()); ut_ad(mutex_own(&block->mutex)); ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); @@ -724,6 +726,7 @@ buf_flush_write_complete( buf_page_set_io_fix(bpage, BUF_IO_NONE); buf_pool->n_flush[flush_type]--; + ut_ad(buf_pool->n_flush[flush_type] != ULINT_MAX); /* fprintf(stderr, "n pending flush %lu\n", buf_pool->n_flush[flush_type]); */ @@ -1061,6 +1064,7 @@ buf_flush_page( } ++buf_pool->n_flush[flush_type]; + ut_ad(buf_pool->n_flush[flush_type] != 0); mutex_exit(&buf_pool->flush_state_mutex); @@ -2206,13 +2210,14 @@ Clears up tail of the LRU lists: * Flush dirty pages at the tail of LRU to the disk The depth to which we scan each buffer pool is controlled by dynamic config parameter innodb_LRU_scan_depth. -@return number of pages flushed */ +@return number of flushed and evicted pages */ UNIV_INTERN ulint buf_flush_LRU_tail(void) /*====================*/ { ulint total_flushed = 0; + ulint total_evicted = 0; ulint start_time = ut_time_ms(); ulint scan_depth[MAX_BUFFER_POOLS]; ulint requested_pages[MAX_BUFFER_POOLS]; @@ -2278,6 +2283,7 @@ buf_flush_LRU_tail(void) limited_scan[i] = (previous_evicted[i] > n.evicted); previous_evicted[i] = n.evicted; + total_evicted += n.evicted; requested_pages[i] += lru_chunk_size; @@ -2310,7 +2316,7 @@ buf_flush_LRU_tail(void) MONITOR_LRU_BATCH_PAGES, total_flushed); } - return(total_flushed); + return(total_flushed + total_evicted); } /*********************************************************************//** @@ -2604,6 +2610,23 @@ buf_get_total_free_list_length(void) return result; } +/** Returns the aggregate LRU list length over all buffer pool instances. +@return total LRU list length. */ +MY_ATTRIBUTE((warn_unused_result)) +static +ulint +buf_get_total_LRU_list_length(void) +{ + ulint result = 0; + + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + + result += UT_LIST_GET_LEN(buf_pool_from_array(i)->LRU); + } + + return result; +} + /*********************************************************************//** Adjust the desired page cleaner thread sleep time for LRU flushes. */ MY_ATTRIBUTE((nonnull)) @@ -2616,8 +2639,9 @@ page_cleaner_adapt_lru_sleep_time( ulint lru_n_flushed) /*!< in: number of flushed in previous batch */ { - ulint free_len = buf_get_total_free_list_length(); - ulint max_free_len = srv_LRU_scan_depth * srv_buf_pool_instances; + ulint free_len = buf_get_total_free_list_length(); + ulint max_free_len = ut_min(buf_get_total_LRU_list_length(), + srv_LRU_scan_depth * srv_buf_pool_instances); if (free_len < max_free_len / 100 && lru_n_flushed) { @@ -2629,7 +2653,7 @@ page_cleaner_adapt_lru_sleep_time( /* Free lists filled more than 20% or no pages flushed in previous batch, sleep a bit more */ - *lru_sleep_time += 50; + *lru_sleep_time += 1; if (*lru_sleep_time > srv_cleaner_max_lru_time) *lru_sleep_time = srv_cleaner_max_lru_time; } else if (free_len < max_free_len / 20 && *lru_sleep_time >= 50) { @@ -2676,6 +2700,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ulint next_loop_time = ut_time_ms() + 1000; ulint n_flushed = 0; ulint last_activity = srv_get_activity_count(); @@ -2812,6 +2837,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( thread_exit: buf_page_cleaner_is_active = FALSE; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); diff --git a/storage/xtradb/dict/dict0boot.cc b/storage/xtradb/dict/dict0boot.cc index c0bb0298bea..4c8420252c2 100644 --- a/storage/xtradb/dict/dict0boot.cc +++ b/storage/xtradb/dict/dict0boot.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -464,7 +464,10 @@ dict_boot(void) dberr_t err = DB_SUCCESS; - if (srv_read_only_mode && !ibuf_is_empty()) { + /** If innodb_force_recovery is set to 6 then allow + the server to start even though ibuf is not empty. */ + if (srv_force_recovery != SRV_FORCE_NO_LOG_REDO + && srv_read_only_mode && !ibuf_is_empty()) { ib_logf(IB_LOG_LEVEL_ERROR, "Change buffer must be empty when --innodb-read-only " diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index bd62744a49c..eec681c4005 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -835,16 +835,24 @@ dict_index_get_nth_col_or_prefix_pos( /*=================================*/ const dict_index_t* index, /*!< in: index */ ulint n, /*!< in: column number */ - ibool inc_prefix) /*!< in: TRUE=consider + ibool inc_prefix, /*!< in: TRUE=consider column prefixes too */ + ulint* prefix_col_pos) /*!< out: col num if prefix */ { const dict_field_t* field; const dict_col_t* col; ulint pos; ulint n_fields; + ulint prefixed_pos_dummy; ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + ut_ad((inc_prefix && !prefix_col_pos) || (!inc_prefix)); + + if (!prefix_col_pos) { + prefix_col_pos = &prefixed_pos_dummy; + } + *prefix_col_pos = ULINT_UNDEFINED; col = dict_table_get_nth_col(index->table, n); @@ -858,10 +866,11 @@ dict_index_get_nth_col_or_prefix_pos( for (pos = 0; pos < n_fields; pos++) { field = dict_index_get_nth_field(index, pos); - if (col == field->col - && (inc_prefix || field->prefix_len == 0)) { - - return(pos); + if (col == field->col) { + *prefix_col_pos = pos; + if (inc_prefix || field->prefix_len == 0) { + return(pos); + } } } @@ -1005,7 +1014,7 @@ dict_table_get_nth_col_pos( ulint n) /*!< in: column number */ { return(dict_index_get_nth_col_pos(dict_table_get_first_index(table), - n)); + n, NULL)); } /********************************************************************//** diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc index b0ba98308be..55a26268579 100644 --- a/storage/xtradb/dict/dict0stats.cc +++ b/storage/xtradb/dict/dict0stats.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2017, 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 @@ -690,6 +690,9 @@ dict_stats_copy( && (src_idx = dict_table_get_next_index(src_idx)))) { if (dict_stats_should_ignore_index(dst_idx)) { + if (!(dst_idx->type & DICT_FTS)) { + dict_stats_empty_index(dst_idx); + } continue; } @@ -1096,10 +1099,10 @@ dict_stats_analyze_index_level( leaf-level delete marks because delete marks on non-leaf level do not make sense. */ - if (level == 0 && srv_stats_include_delete_marked? 0: + if (level == 0 && (srv_stats_include_delete_marked ? 0: rec_get_deleted_flag( rec, - page_is_comp(btr_pcur_get_page(&pcur)))) { + page_is_comp(btr_pcur_get_page(&pcur))))) { if (rec_is_last_on_page && !prev_rec_is_copied @@ -3229,12 +3232,6 @@ dict_stats_update( dict_table_stats_lock(table, RW_X_LATCH); - /* Initialize all stats to dummy values before - copying because dict_stats_table_clone_create() does - skip corrupted indexes so our dummy object 't' may - have less indexes than the real object 'table'. */ - dict_stats_empty_table(table); - dict_stats_copy(table, t); dict_stats_assert_initialized(table); diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc index 6f01c379776..975c8a50803 100644 --- a/storage/xtradb/dict/dict0stats_bg.cc +++ b/storage/xtradb/dict/dict0stats_bg.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, 2017, 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 @@ -334,6 +334,7 @@ DECLARE_THREAD(dict_stats_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_a(!srv_read_only_mode); srv_dict_stats_thread_active = TRUE; @@ -359,6 +360,7 @@ DECLARE_THREAD(dict_stats_thread)( srv_dict_stats_thread_active = FALSE; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit instead of return(). */ os_thread_exit(NULL); diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 57e415ae939..d701bddebfc 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -146,7 +146,7 @@ struct fil_node_t { belongs */ char* name; /*!< path to the file */ ibool open; /*!< TRUE if file open */ - os_file_t handle; /*!< OS handle to the file, if file open */ + pfs_os_file_t handle; /*!< OS handle to the file, if file open */ os_event_t sync_event;/*!< Condition event to group and serialize calls to fsync */ ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw @@ -317,7 +317,8 @@ initialized. */ static fil_system_t* fil_system = NULL; /** Determine if (i) is a user tablespace id or not. */ -# define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open) +# define fil_is_user_tablespace_id(i) (i != 0 \ + && !srv_is_undo_tablespace(i)) /** Determine if user has explicitly disabled fsync(). */ #ifndef __WIN__ @@ -2084,7 +2085,7 @@ UNIV_INTERN const char* fil_read_first_page( /*================*/ - os_file_t data_file, /*!< in: open data file */ + pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ @@ -3407,7 +3408,7 @@ fil_open_linked_file( /*===============*/ const char* tablename, /*!< in: database/tablename */ char** remote_filepath,/*!< out: remote filepath */ - os_file_t* remote_file) /*!< out: remote file handle */ + pfs_os_file_t* remote_file) /*!< out: remote file handle */ { ibool success; @@ -3467,7 +3468,8 @@ fil_create_new_single_table_tablespace( tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE */ { - os_file_t file; + pfs_os_file_t file; + ibool ret; dberr_t err; byte* buf2; @@ -5206,8 +5208,8 @@ retry: os_offset_t end_offset = (size_after_extend - file_start_page_no) * page_size; - success = (posix_fallocate(node->handle, start_offset, - end_offset) == 0); + success = (os_file_allocate(node->handle, start_offset, + end_offset) == 0); if (!success) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -5960,7 +5962,7 @@ fil_flush( { fil_space_t* space; fil_node_t* node; - os_file_t file; + pfs_os_file_t file; mutex_enter(&fil_system->mutex); @@ -6319,7 +6321,7 @@ fil_buf_block_init( } struct fil_iterator_t { - os_file_t file; /*!< File handle */ + pfs_os_file_t file; /*!< File handle */ const char* filepath; /*!< File path name */ os_offset_t start; /*!< From where to start */ os_offset_t end; /*!< Where to stop */ @@ -6454,7 +6456,7 @@ fil_tablespace_iterate( PageCallback& callback) { dberr_t err; - os_file_t file; + pfs_os_file_t file; char* filepath; ut_a(n_io_buffers > 0); diff --git a/storage/xtradb/fts/fts0que.cc b/storage/xtradb/fts/fts0que.cc index 2c44a21a8f2..d926d9b0675 100644 --- a/storage/xtradb/fts/fts0que.cc +++ b/storage/xtradb/fts/fts0que.cc @@ -953,6 +953,18 @@ fts_query_free_doc_ids( query->total_size -= SIZEOF_RBT_CREATE; } +/** +Free the query intersection +@param[in] query query instance */ +static +void +fts_query_free_intersection( + fts_query_t* query) +{ + fts_query_free_doc_ids(query, query->intersection); + query->intersection = NULL; +} + /*******************************************************************//** Add the word to the documents "list" of matching words from the query. We make a copy of the word from the query heap. */ @@ -1311,6 +1323,7 @@ fts_query_intersect( /* error is passed by 'query->error' */ if (query->error != DB_SUCCESS) { ut_ad(query->error == DB_FTS_EXCEED_RESULT_CACHE_LIMIT); + fts_query_free_intersection(query); return(query->error); } @@ -1339,6 +1352,8 @@ fts_query_intersect( ut_a(!query->multi_exist || (query->multi_exist && rbt_size(query->doc_ids) <= n_doc_ids)); + } else if (query->intersection != NULL) { + fts_query_free_intersection(query); } } @@ -1557,6 +1572,11 @@ fts_merge_doc_ids( query, ranking->doc_id, ranking->rank); if (query->error != DB_SUCCESS) { + if (query->intersection != NULL) + { + ut_a(query->oper == FTS_EXIST); + fts_query_free_intersection(query); + } DBUG_RETURN(query->error); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 05a77436a12..d1f6c3b499a 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -701,6 +701,32 @@ innobase_is_fake_change( THD* thd); /*!< in: MySQL thread handle of the user for whom the transaction is being committed */ +/** Empty free list algorithm. +Checks if buffer pool is big enough to enable backoff algorithm. +InnoDB empty free list algorithm backoff requires free pages +from LRU for the best performance. +buf_LRU_buf_pool_running_out cancels query if 1/4 of +buffer pool belongs to LRU or freelist. +At the same time buf_flush_LRU_list_batch +keeps up to BUF_LRU_MIN_LEN in LRU. +In order to avoid deadlock baclkoff requires buffer pool +to be at least 4*BUF_LRU_MIN_LEN, +but flush peformance is bad because of trashing +and additional BUF_LRU_MIN_LEN pages are requested. +@param[in] algorithm desired algorithm from srv_empty_free_list_t +@return true if it's possible to enable backoff. */ +static inline +bool +innodb_empty_free_list_algorithm_allowed( + srv_empty_free_list_t algorithm) +{ + long long buf_pool_pages = srv_buf_pool_size / srv_page_size + / srv_buf_pool_instances; + + return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) + || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF); +} + /** Get the list of foreign keys referencing a specified table table. @param thd The thread handle @@ -970,6 +996,10 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_x_lock_spin_rounds, SHOW_LONGLONG}, {"x_lock_spin_waits", (char*) &export_vars.innodb_x_lock_spin_waits, SHOW_LONGLONG}, + {"secondary_index_triggered_cluster_reads", + (char*) &export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG}, + {"secondary_index_triggered_cluster_reads_avoided", + (char*) &export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG}, {NullS, NullS, SHOW_LONG} }; @@ -1384,28 +1414,6 @@ innobase_drop_zip_dict( ulint* name_len); /*!< in/out: zip dictionary name length */ -/*************************************************************//** -Checks if buffer pool is big enough to enable backoff algorithm. -InnoDB empty free list algorithm backoff requires free pages -from LRU for the best performance. -buf_LRU_buf_pool_running_out cancels query if 1/4 of -buffer pool belongs to LRU or freelist. -At the same time buf_flush_LRU_list_batch -keeps up to BUF_LRU_MIN_LEN in LRU. -In order to avoid deadlock baclkoff requires buffer pool -to be at least 4*BUF_LRU_MIN_LEN, -but flush peformance is bad because of trashing -and additional BUF_LRU_MIN_LEN pages are requested. -@return true if it's possible to enable backoff. */ -static -bool -innodb_empty_free_list_algorithm_backoff_allowed( - srv_empty_free_list_t - algorithm, /*!< in: desired algorithm - from srv_empty_free_list_t */ - long long buf_pool_pages); /*!< in: total number - of pages inside buffer pool */ - /*************************************************************//** Removes old archived transaction log files. @return true on error */ @@ -3446,7 +3454,8 @@ 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_ONLINE_BACKUPS | HTON_SUPPORTS_FOREIGN_KEYS; + HTON_SUPPORTS_ONLINE_BACKUPS | HTON_SUPPORTS_FOREIGN_KEYS | + HTON_SUPPORTS_COMPRESSED_COLUMNS; innobase_hton->release_temporary_latches = innobase_release_temporary_latches; @@ -3915,10 +3924,9 @@ innobase_change_buffering_inited_ok: innobase_commit_concurrency_init_default(); /* Do not enable backoff algorithm for small buffer pool. */ - if (!innodb_empty_free_list_algorithm_backoff_allowed( + if (!innodb_empty_free_list_algorithm_allowed( static_cast( - srv_empty_free_list_algorithm), - innobase_buffer_pool_size / srv_page_size)) { + srv_empty_free_list_algorithm))) { sql_print_information( "InnoDB: innodb_empty_free_list_algorithm " "has been changed to legacy " @@ -4160,6 +4168,10 @@ innobase_create_zip_dict( if (UNIV_UNLIKELY(high_level_read_only)) { DBUG_RETURN(HA_CREATE_ZIP_DICT_READ_ONLY); } + + if (UNIV_UNLIKELY(THDVAR(NULL, fake_changes))) { + DBUG_RETURN(HA_CREATE_ZIP_DICT_FAKE_CHANGES); + } if (UNIV_UNLIKELY(*name_len > ZIP_DICT_MAX_NAME_LENGTH)) { *name_len = ZIP_DICT_MAX_NAME_LENGTH; @@ -4178,6 +4190,15 @@ innobase_create_zip_dict( case DB_DUPLICATE_KEY: result = HA_CREATE_ZIP_DICT_ALREADY_EXISTS; break; + case DB_OUT_OF_MEMORY: + result = HA_CREATE_ZIP_DICT_OUT_OF_MEMORY; + break; + case DB_OUT_OF_FILE_SPACE: + result = HA_CREATE_ZIP_DICT_OUT_OF_FILE_SPACE; + break; + case DB_TOO_MANY_CONCURRENT_TRXS: + result = HA_CREATE_ZIP_DICT_TOO_MANY_CONCURRENT_TRXS; + break; default: ut_ad(0); result = HA_CREATE_ZIP_DICT_UNKNOWN_ERROR; @@ -4204,6 +4225,10 @@ innobase_drop_zip_dict( DBUG_RETURN(HA_DROP_ZIP_DICT_READ_ONLY); } + if (UNIV_UNLIKELY(THDVAR(NULL, fake_changes))) { + DBUG_RETURN(HA_DROP_ZIP_DICT_FAKE_CHANGES); + } + switch (dict_drop_zip_dict(name, *name_len)) { case DB_SUCCESS: result = HA_DROP_ZIP_DICT_OK; @@ -4214,6 +4239,15 @@ innobase_drop_zip_dict( case DB_ROW_IS_REFERENCED: result = HA_DROP_ZIP_DICT_IS_REFERENCED; break; + case DB_OUT_OF_MEMORY: + result = HA_DROP_ZIP_DICT_OUT_OF_MEMORY; + break; + case DB_OUT_OF_FILE_SPACE: + result = HA_DROP_ZIP_DICT_OUT_OF_FILE_SPACE; + break; + case DB_TOO_MANY_CONCURRENT_TRXS: + result = HA_DROP_ZIP_DICT_TOO_MANY_CONCURRENT_TRXS; + break; default: ut_ad(0); result = HA_DROP_ZIP_DICT_UNKNOWN_ERROR; @@ -6032,6 +6066,8 @@ table_opened: prebuilt->default_rec = table->s->default_values; ut_ad(prebuilt->default_rec); + prebuilt->mysql_handler = this; + /* Looks like MySQL-3.23 sometimes has primary key number != 0 */ primary_key = table->s->primary_key; key_used_on_scan = primary_key; @@ -7181,9 +7217,31 @@ build_template_field( ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED); if (dict_index_is_clust(index)) { + templ->rec_field_is_prefix = false; templ->rec_field_no = templ->clust_rec_field_no; + templ->rec_prefix_field_no = ULINT_UNDEFINED; } else { - templ->rec_field_no = dict_index_get_nth_col_pos(index, i); + /* If we're in a secondary index, keep track of the original + index position even if this is just a prefix index; we will use + this later to avoid a cluster index lookup in some cases.*/ + + templ->rec_field_no = dict_index_get_nth_col_pos(index, i, + &templ->rec_prefix_field_no); + templ->rec_field_is_prefix + = (templ->rec_field_no == ULINT_UNDEFINED) + && (templ->rec_prefix_field_no != ULINT_UNDEFINED); +#ifdef UNIV_DEBUG + if (templ->rec_prefix_field_no != ULINT_UNDEFINED) + { + const dict_field_t* field = dict_index_get_nth_field( + index, + templ->rec_prefix_field_no); + ut_ad(templ->rec_field_is_prefix + == (field->prefix_len != 0)); + } else { + ut_ad(!templ->rec_field_is_prefix); + } +#endif } if (field->real_maybe_null()) { @@ -7373,7 +7431,8 @@ ha_innobase::build_template( } else { templ->icp_rec_field_no = dict_index_get_nth_col_pos( - prebuilt->index, i); + prebuilt->index, i, + NULL); } if (dict_index_is_clust(prebuilt->index)) { @@ -7403,7 +7462,7 @@ ha_innobase::build_template( templ->icp_rec_field_no = dict_index_get_nth_col_or_prefix_pos( - prebuilt->index, i, TRUE); + prebuilt->index, i, TRUE, NULL); ut_ad(templ->icp_rec_field_no != ULINT_UNDEFINED); @@ -11288,7 +11347,8 @@ ha_innobase::delete_table( extension, in contrast to ::create */ normalize_table_name(norm_name, name); - if (srv_read_only_mode) { + if (srv_read_only_mode + || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) { DBUG_RETURN(HA_ERR_TABLE_READONLY); } else if (row_is_magic_monitor_table(norm_name) && check_global_access(thd, PROCESS_ACL)) { @@ -15301,16 +15361,21 @@ and SYS_ZIP_DICT_COLS for all columns marked with COLUMN_FORMAT_TYPE_COMPRESSED flag and updates zip_dict_name / zip_dict_data for those which have associated compression dictionaries. + +@param part_name Full table name (including partition part). + Must be non-NULL only if called from ha_partition. */ UNIV_INTERN void -ha_innobase::update_field_defs_with_zip_dict_info() +ha_innobase::update_field_defs_with_zip_dict_info(const char *part_name) { DBUG_ENTER("update_field_defs_with_zip_dict_info"); ut_ad(!mutex_own(&dict_sys->mutex)); char norm_name[FN_REFLEN]; - normalize_table_name(norm_name, table_share->normalized_path.str); + normalize_table_name(norm_name, + part_name != 0 ? part_name : + table_share->normalized_path.str); dict_table_t* ib_table = dict_table_open_on_name( norm_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); @@ -16687,15 +16752,17 @@ innodb_buffer_pool_evict_uncompressed(void) ut_ad(block->page.in_LRU_list); mutex_enter(&block->mutex); - if (!buf_LRU_free_page(&block->page, false)) { - mutex_exit(&block->mutex); - all_evicted = false; - } else { - mutex_exit(&block->mutex); - mutex_enter(&buf_pool->LRU_list_mutex); - } + all_evicted = buf_LRU_free_page(&block->page, false); + mutex_exit(&block->mutex); - block = prev_block; + if (all_evicted) { + + mutex_enter(&buf_pool->LRU_list_mutex); + block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); + } else { + + block = prev_block; + } } mutex_exit(&buf_pool->LRU_list_mutex); @@ -17497,32 +17564,6 @@ innodb_status_output_update( os_event_set(lock_sys->timeout_event); } -/*************************************************************//** -Empty free list algorithm. -Checks if buffer pool is big enough to enable backoff algorithm. -InnoDB empty free list algorithm backoff requires free pages -from LRU for the best performance. -buf_LRU_buf_pool_running_out cancels query if 1/4 of -buffer pool belongs to LRU or freelist. -At the same time buf_flush_LRU_list_batch -keeps up to BUF_LRU_MIN_LEN in LRU. -In order to avoid deadlock baclkoff requires buffer pool -to be at least 4*BUF_LRU_MIN_LEN, -but flush peformance is bad because of trashing -and additional BUF_LRU_MIN_LEN pages are requested. -@return true if it's possible to enable backoff. */ -static -bool -innodb_empty_free_list_algorithm_backoff_allowed( - srv_empty_free_list_t algorithm, /*!< in: desired algorithm - from srv_empty_free_list_t */ - long long buf_pool_pages) /*!< in: total number - of pages inside buffer pool */ -{ - return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) - || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF); -} - /*************************************************************//** Empty free list algorithm. This function is registered as a callback with MySQL. @@ -17564,13 +17605,11 @@ innodb_srv_empty_free_list_algorithm_validate( return(1); algorithm = static_cast(algo); - if (!innodb_empty_free_list_algorithm_backoff_allowed( - algorithm, - innobase_buffer_pool_size / srv_page_size)) { + if (!innodb_empty_free_list_algorithm_allowed(algorithm)) { sql_print_warning( "InnoDB: innodb_empty_free_list_algorithm " "= 'backoff' requires at least" - " 20MB buffer pool.\n"); + " 20MB buffer pool instances.\n"); return(1); } diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 39de6b179ab..99953a22121 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -295,8 +295,12 @@ class ha_innobase: public handler COLUMN_FORMAT_TYPE_COMPRESSED flag and updates zip_dict_name / zip_dict_data for those which have associated compression dictionaries. + + @param part_name Full table name (including partition part). + Must be non-NULL only if called from ha_partition. */ - virtual void update_field_defs_with_zip_dict_info(); + virtual void update_field_defs_with_zip_dict_info( + const char* part_name); private: /** Builds a 'template' to the prebuilt struct. diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 098d93d4529..d6576fe27d5 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1148,7 +1148,8 @@ innobase_rec_to_mysql( field->reset(); - ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE); + ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE, + NULL); if (ipos == ULINT_UNDEFINED || rec_offs_nth_extern(offsets, ipos)) { @@ -1196,7 +1197,8 @@ innobase_fields_to_mysql( field->reset(); - ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE); + ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE, + NULL); if (ipos == ULINT_UNDEFINED || dfield_is_ext(&fields[ipos]) diff --git a/storage/xtradb/include/buf0dblwr.h b/storage/xtradb/include/buf0dblwr.h index a62a6400d97..18e124b7437 100644 --- a/storage/xtradb/include/buf0dblwr.h +++ b/storage/xtradb/include/buf0dblwr.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -55,7 +55,7 @@ recovery, this function loads the pages from double write buffer into memory. */ void buf_dblwr_init_or_load_pages( /*=========================*/ - os_file_t file, + pfs_os_file_t file, char* path, bool load_corrupt_pages); diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h index 99d745eb49f..7ca2f45cb80 100644 --- a/storage/xtradb/include/dict0dict.h +++ b/storage/xtradb/include/dict0dict.h @@ -1142,8 +1142,9 @@ ulint dict_index_get_nth_col_pos( /*=======================*/ const dict_index_t* index, /*!< in: index */ - ulint n) /*!< in: column number */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + ulint n, /*!< in: column number */ + ulint* prefix_col_pos) /*!< out: col num if prefix */ + MY_ATTRIBUTE((nonnull(1), warn_unused_result)); /********************************************************************//** Looks for column n in an index. @return position in internal representation of the index; @@ -1154,9 +1155,11 @@ dict_index_get_nth_col_or_prefix_pos( /*=================================*/ const dict_index_t* index, /*!< in: index */ ulint n, /*!< in: column number */ - ibool inc_prefix) /*!< in: TRUE=consider + ibool inc_prefix, /*!< in: TRUE=consider column prefixes too */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + ulint* prefix_col_pos) /*!< out: col num if prefix */ + + MY_ATTRIBUTE((nonnull(1), warn_unused_result)); /********************************************************************//** Returns TRUE if the index contains a column or a prefix of that column. @return TRUE if contains the column or its prefix */ diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic index 58a9ef4d65d..32bc4f376d9 100644 --- a/storage/xtradb/include/dict0dict.ic +++ b/storage/xtradb/include/dict0dict.ic @@ -1049,7 +1049,8 @@ dict_index_get_sys_col_pos( } return(dict_index_get_nth_col_pos( - index, dict_table_get_sys_col_no(index->table, type))); + index, dict_table_get_sys_col_no(index->table, type), + NULL)); } /*********************************************************************//** @@ -1101,9 +1102,11 @@ ulint dict_index_get_nth_col_pos( /*=======================*/ const dict_index_t* index, /*!< in: index */ - ulint n) /*!< in: column number */ + ulint n, /*!< in: column number */ + ulint* prefix_col_pos) /*!< out: col num if prefix */ { - return(dict_index_get_nth_col_or_prefix_pos(index, n, FALSE)); + return(dict_index_get_nth_col_or_prefix_pos(index, n, FALSE, + prefix_col_pos)); } #ifndef UNIV_HOTBACKUP diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 14dfa296435..78222b3122a 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -182,7 +182,7 @@ struct fsp_open_info { ibool success; /*!< Has the tablespace been opened? */ const char* check_msg; /*!< fil_check_first_page() message */ ibool valid; /*!< Is the tablespace valid? */ - os_file_t file; /*!< File handle */ + pfs_os_file_t file; /*!< File handle */ char* filepath; /*!< File path to open */ lsn_t lsn; /*!< Flushed LSN from header page */ ulint id; /*!< Space ID */ @@ -390,7 +390,7 @@ UNIV_INTERN const char* fil_read_first_page( /*================*/ - os_file_t data_file, /*!< in: open data file */ + pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ @@ -906,12 +906,12 @@ struct PageCallback { Called for every page in the tablespace. If the page was not updated then its state must be set to BUF_PAGE_NOT_USED. For compressed tables the page descriptor memory will be at offset: - block->frame + UNIV_PAGE_SIZE; + block->frame + UNIV_PAGE_SIZE; @param offset - physical offset within the file @param block - block read from file, note it is not from the buffer pool @retval DB_SUCCESS or error code. */ virtual dberr_t operator()( - os_offset_t offset, + os_offset_t offset, buf_block_t* block) UNIV_NOTHROW = 0; /** @@ -919,7 +919,7 @@ struct PageCallback { to open it for the file that is being iterated over. @param filename - then physical name of the tablespace file. @param file - OS file handle */ - void set_file(const char* filename, os_file_t file) UNIV_NOTHROW + void set_file(const char* filename, pfs_os_file_t file) UNIV_NOTHROW { m_file = file; m_filepath = filename; @@ -955,7 +955,7 @@ struct PageCallback { ulint m_page_size; /** File handle to the tablespace */ - os_file_t m_file; + pfs_os_file_t m_file; /** Physical file path. */ const char* m_filepath; diff --git a/storage/xtradb/include/ha0ha.h b/storage/xtradb/include/ha0ha.h index 7351b407e8c..58eb581e76a 100644 --- a/storage/xtradb/include/ha0ha.h +++ b/storage/xtradb/include/ha0ha.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -107,7 +107,7 @@ chosen to be a slightly bigger prime number. @param level in: level of the mutexes in the latching order @param n_m in: number of mutexes to protect the hash table; must be a power of 2, or 0 */ -# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type) +# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type) #else /* UNIV_SYNC_DEBUG */ /** Creates a hash table. @return own: created table @@ -116,7 +116,7 @@ chosen to be a slightly bigger prime number. @param level in: level of the mutexes in the latching order @param n_m in: number of mutexes to protect the hash table; must be a power of 2, or 0 */ -# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type) +# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type) #endif /* UNIV_SYNC_DEBUG */ /*************************************************************//** diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h index 722336dd6b4..5c3e7d07fd9 100644 --- a/storage/xtradb/include/log0online.h +++ b/storage/xtradb/include/log0online.h @@ -130,7 +130,7 @@ log_online_bitmap_iterator_next( /** Struct for single bitmap file information */ struct log_online_bitmap_file_struct { char name[FN_REFLEN]; /*!< Name with full path */ - os_file_t file; /*!< Handle to opened file */ + pfs_os_file_t file; /*!< Handle to opened file */ ib_uint64_t size; /*!< Size of the file */ os_offset_t offset; /*!< Offset of the next read, or count of already-read bytes diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h index cf8935ff7d2..4dab704ad50 100644 --- a/storage/xtradb/include/os0file.h +++ b/storage/xtradb/include/os0file.h @@ -1,6 +1,6 @@ /*********************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted @@ -78,7 +78,6 @@ typedef ib_uint64_t os_offset_t; #define SRV_PATH_SEPARATOR '\\' /** File handle */ # define os_file_t HANDLE -# define os_file_invalid INVALID_HANDLE_VALUE /** Convert a C file descriptor to a native file handle @param fd file descriptor @return native file handle */ @@ -87,13 +86,22 @@ typedef ib_uint64_t os_offset_t; #define SRV_PATH_SEPARATOR '/' /** File handle */ typedef int os_file_t; -# define os_file_invalid (-1) /** Convert a C file descriptor to a native file handle @param fd file descriptor @return native file handle */ # define OS_FILE_FROM_FD(fd) fd #endif +/*Common file descriptor for file IO instrumentation with PFS +on windows and other platforms */ +struct pfs_os_file_t +{ + os_file_t m_file; +#ifdef UNIV_PFS_IO + struct PSI_file *m_psi; +#endif +}; + /** Umask for creating files */ extern ulint os_innodb_umask; @@ -129,6 +137,21 @@ enum os_file_create_t { ON_ERROR_NO_EXIT is set */ }; +/** Options for os_file_advise_func @{ */ +enum os_file_advise_t { + OS_FILE_ADVISE_NORMAL = 1, /*!< no advice on access pattern + (default) */ + OS_FILE_ADVISE_RANDOM = 2, /*!< access in random order */ + OS_FILE_ADVISE_SEQUENTIAL = 4, /*!< access the specified data + sequentially (with lower offsets read + before higher ones) */ + OS_FILE_ADVISE_WILLNEED = 8, /*!< specified data will be accessed + in the near future */ + OS_FILE_ADVISE_DONTNEED = 16, /*!< specified data will not be + accessed in the near future */ + OS_FILE_ADVISE_NOREUSE = 32 /*!< access only once */ +}; + #define OS_FILE_READ_ONLY 333 #define OS_FILE_READ_WRITE 444 #define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */ @@ -230,6 +253,8 @@ extern mysql_pfs_key_t innodb_file_bmp_key; various file I/O operations with performance schema. 1) register_pfs_file_open_begin() and register_pfs_file_open_end() are used to register file creation, opening, closing and renaming. +2) register_pfs_file_rename_begin() and register_pfs_file_rename_end() +are used to register file renaming 2) register_pfs_file_io_begin() and register_pfs_file_io_end() are used to register actual file read, write and flush 3) register_pfs_file_close_begin() and register_pfs_file_close_end() @@ -239,17 +264,30 @@ are used to register file deletion operations*/ do { \ locker = PSI_FILE_CALL(get_thread_file_name_locker)( \ state, key, op, name, &locker); \ - if (UNIV_LIKELY(locker != NULL)) { \ + if (locker != NULL) { \ PSI_FILE_CALL(start_file_open_wait)( \ locker, src_file, src_line); \ } \ } while (0) -# define register_pfs_file_open_end(locker, file) \ +# define register_pfs_file_open_end(locker, file, result) \ do { \ - if (UNIV_LIKELY(locker != NULL)) { \ - PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(\ - locker, file); \ + if (locker != NULL) { \ + file.m_psi = PSI_FILE_CALL( \ + end_file_open_wait)( \ + locker, result); \ + } \ +} while (0) + +# define register_pfs_file_rename_begin(state, locker, key, op, name, \ + src_file, src_line) \ + register_pfs_file_open_begin(state, locker, key, op, name, \ + src_file, src_line) \ + +# define register_pfs_file_rename_end(locker, result) \ +do { \ + if (locker != NULL) { \ + PSI_FILE_CALL(end_file_open_wait)(locker, result); \ } \ } while (0) @@ -275,9 +313,9 @@ do { \ # define register_pfs_file_io_begin(state, locker, file, count, op, \ src_file, src_line) \ do { \ - locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( \ - state, file, op); \ - if (UNIV_LIKELY(locker != NULL)) { \ + locker = PSI_FILE_CALL(get_thread_file_stream_locker)( \ + state, file.m_psi, op); \ + if (locker != NULL) { \ PSI_FILE_CALL(start_file_wait)( \ locker, count, src_file, src_line); \ } \ @@ -285,7 +323,7 @@ do { \ # define register_pfs_file_io_end(locker, count) \ do { \ - if (UNIV_LIKELY(locker != NULL)) { \ + if (locker != NULL) { \ PSI_FILE_CALL(end_file_wait)(locker, count); \ } \ } while (0) @@ -299,11 +337,16 @@ os_file_create os_file_create_simple os_file_create_simple_no_error_handling os_file_close +os_file_close_no_error_handling os_file_rename os_aio os_file_read os_file_read_no_error_handling +os_file_read_no_error_handling_int_fd os_file_write +os_file_write_int_fd +os_file_set_eof_at +os_file_allocate The wrapper functions have the prefix of "innodb_". */ @@ -321,20 +364,23 @@ The wrapper functions have the prefix of "innodb_". */ pfs_os_file_create_simple_no_error_handling_func( \ key, name, create_mode, access, success, __FILE__, __LINE__) -# define os_file_close(file) \ +# define os_file_close_pfs(file) \ pfs_os_file_close_func(file, __FILE__, __LINE__) +# define os_file_close_no_error_handling_pfs(file) \ + pfs_os_file_close_no_error_handling_func(file, __FILE__, __LINE__) + # define os_aio(type, mode, name, file, buf, offset, \ n, message1, message2, space_id, trx) \ pfs_os_aio_func(type, mode, name, file, buf, offset, \ n, message1, message2, space_id, trx, \ __FILE__, __LINE__) -# define os_file_read(file, buf, offset, n) \ +# define os_file_read_pfs(file, buf, offset, n) \ pfs_os_file_read_func(file, buf, offset, n, NULL, \ __FILE__, __LINE__) -# define os_file_read_trx(file, buf, offset, n, trx) \ +# define os_file_read_trx_pfs(file, buf, offset, n, trx) \ pfs_os_file_read_func(file, buf, offset, n, trx, \ __FILE__, __LINE__) @@ -342,11 +388,20 @@ The wrapper functions have the prefix of "innodb_". */ pfs_os_file_read_no_error_handling_func(file, buf, offset, n, \ __FILE__, __LINE__) -# define os_file_write(name, file, buf, offset, n) \ +# define os_file_read_no_error_handling_int_fd( \ + file, buf, offset, n) \ + pfs_os_file_read_no_error_handling_int_fd_func( \ + file, buf, offset, n, __FILE__, __LINE__) + +# define os_file_write_pfs(name, file, buf, offset, n) \ pfs_os_file_write_func(name, file, buf, offset, \ n, __FILE__, __LINE__) -# define os_file_flush(file) \ +# define os_file_write_int_fd(name, file, buf, offset, n) \ + pfs_os_file_write_int_fd_func(name, file, buf, offset, \ + n, __FILE__, __LINE__) + +# define os_file_flush_pfs(file) \ pfs_os_file_flush_func(file, __FILE__, __LINE__) # define os_file_rename(key, oldpath, newpath) \ @@ -357,6 +412,15 @@ The wrapper functions have the prefix of "innodb_". */ # define os_file_delete_if_exists(key, name) \ pfs_os_file_delete_if_exists_func(key, name, __FILE__, __LINE__) + +# define os_file_set_eof_at_pfs(file, new_len) \ + pfs_os_file_set_eof_at_func(file, new_len, __FILE__, __LINE__) + +# ifdef HAVE_POSIX_FALLOCATE +# define os_file_allocate_pfs(file, offset, len) \ + pfs_os_file_allocate_func(file, offset, len, __FILE__, __LINE__) +# endif + #else /* UNIV_PFS_IO */ /* If UNIV_PFS_IO is not defined, these I/O APIs point @@ -372,26 +436,36 @@ to original un-instrumented file I/O APIs */ os_file_create_simple_no_error_handling_func( \ name, create_mode, access, success) -# define os_file_close(file) os_file_close_func(file) +# define os_file_close_pfs(file) \ + os_file_close_func(file) + +# define os_file_close_no_error_handling_pfs(file) \ + os_file_close_no_error_handling_func(file) # define os_aio(type, mode, name, file, buf, offset, n, message1, \ message2, space_id, trx) \ os_aio_func(type, mode, name, file, buf, offset, n, \ message1, message2, space_id, trx) -# define os_file_read(file, buf, offset, n) \ +# define os_file_read_pfs(file, buf, offset, n) \ os_file_read_func(file, buf, offset, n, NULL) -# define os_file_read_trx(file, buf, offset, n, trx) \ +# define os_file_read_trx_pfs(file, buf, offset, n, trx) \ os_file_read_func(file, buf, offset, n, trx) # define os_file_read_no_error_handling(file, buf, offset, n) \ os_file_read_no_error_handling_func(file, buf, offset, n) +# define os_file_read_no_error_handling_int_fd( \ + file, buf, offset, n) \ + os_file_read_no_error_handling_func(file, buf, offset, n) -# define os_file_write(name, file, buf, offset, n) \ +# define os_file_write_int_fd(name, file, buf, offset, n) \ + os_file_write_func(name, file, buf, offset, n) +# define os_file_write_pfs(name, file, buf, offset, n) \ os_file_write_func(name, file, buf, offset, n) -# define os_file_flush(file) os_file_flush_func(file) + +# define os_file_flush_pfs(file) os_file_flush_func(file) # define os_file_rename(key, oldpath, newpath) \ os_file_rename_func(oldpath, newpath) @@ -401,8 +475,78 @@ to original un-instrumented file I/O APIs */ # define os_file_delete_if_exists(key, name) \ os_file_delete_if_exists_func(name) +# define os_file_set_eof_at_pfs(file, new_len) \ + os_file_set_eof_at_func(file, new_len) + +# ifdef HAVE_POSIX_FALLOCATE +# define os_file_allocate_pfs(file, offset, len) \ + os_file_allocate_func(file, offset, len) +# endif + #endif /* UNIV_PFS_IO */ +#ifdef UNIV_PFS_IO + #define os_file_close(file) os_file_close_pfs(file) +#else + #define os_file_close(file) os_file_close_pfs((file).m_file) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_close_no_error_handling(file) \ + os_file_close_no_error_handling_pfs(file) +#else + #define os_file_close_no_error_handling(file) \ + os_file_close_no_error_handling_pfs((file).m_file) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_read(file, buf, offset, n) \ + os_file_read_pfs(file, buf, offset, n) +#else + #define os_file_read(file, buf, offset, n) \ + os_file_read_pfs(file.m_file, buf, offset, n) +#endif + +#ifdef UNIV_PFS_IO + # define os_file_read_trx(file, buf, offset, n, trx) \ + os_file_read_trx_pfs(file, buf, offset, n, trx) +#else + # define os_file_read_trx(file, buf, offset, n, trx) \ + os_file_read_trx_pfs(file.m_file, buf, offset, n, trx) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_flush(file) os_file_flush_pfs(file) +#else + #define os_file_flush(file) os_file_flush_pfs(file.m_file) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_write(name, file, buf, offset, n) \ + os_file_write_pfs(name, file, buf, offset, n) +#else + #define os_file_write(name, file, buf, offset, n) \ + os_file_write_pfs(name, file.m_file, buf, offset, n) +#endif + +#ifdef UNIV_PFS_IO + #define os_file_set_eof_at(file, new_len) \ + os_file_set_eof_at_pfs(file, new_len) +#else + #define os_file_set_eof_at(file, new_len) \ + os_file_set_eof_at_pfs(file.m_file, new_len) +#endif + +#ifdef HAVE_POSIX_FALLOCATE +#ifdef UNIV_PFS_IO + #define os_file_allocate(file, offset, len) \ + os_file_allocate_pfs(file, offset, len) +#else + #define os_file_allocate(file, offset, len) \ + os_file_allocate_pfs(file.m_file, offset, len) +#endif +#endif + /* File types for directory entry data type */ enum os_file_type_t { @@ -536,7 +680,7 @@ A simple function to open or create a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_simple_no_error_handling_func( /*=========================================*/ const char* name, /*!< in: name of the file or path as a @@ -569,7 +713,7 @@ Opens an existing file or creates a new. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_func( /*================*/ const char* name, /*!< in: name of the file or path as a @@ -628,6 +772,42 @@ ibool os_file_close_func( /*===============*/ os_file_t file); /*!< in, own: handle to a file */ +/***********************************************************************//** +NOTE! Use the corresponding macro os_file_close(), not directly this +function! +Closes a file handle. In case of error, error number can be retrieved with +os_file_get_last_error. +@return TRUE if success */ +UNIV_INTERN +bool +os_file_close_no_error_handling_func( +/*===============*/ + os_file_t file); /*!< in, own: handle to a file */ + +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_set_eof_at(), not +directly this function! +Truncates a file at the specified position. +@return TRUE if success */ +UNIV_INTERN +bool +os_file_set_eof_at_func( + os_file_t file, /*!< in: handle to a file */ + ib_uint64_t new_len);/*!< in: new file length */ + +#ifdef HAVE_POSIX_FALLOCATE +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_allocate(), not +directly this function! +Ensures that disk space is allocated for the file. +@return TRUE if success */ +UNIV_INTERN +bool +os_file_allocate_func( + os_file_t file, /*!< in, own: handle to a file */ + os_offset_t offset, /*!< in: file region offset */ + os_offset_t len); /*!< in: file region length */ +#endif #ifdef UNIV_PFS_IO /****************************************************************//** @@ -638,7 +818,7 @@ os_file_create_simple() which opens or creates a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_func( /*===========================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -661,7 +841,7 @@ monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_no_error_handling_func( /*=============================================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -685,7 +865,7 @@ Add instrumentation to monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_func( /*====================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -714,7 +894,20 @@ UNIV_INLINE ibool pfs_os_file_close_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line);/*!< in: line where the func invoked */ +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_close_no_error_handling(), +not directly this function! +A performance schema instrumented wrapper function for +os_file_close_no_error_handling(). +@return TRUE if success */ +UNIV_INLINE +bool +pfs_os_file_close_no_error_handling_func( +/*===================*/ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line);/*!< in: line where the func invoked */ /*******************************************************************//** @@ -727,7 +920,7 @@ UNIV_INLINE ibool pfs_os_file_read_func( /*==================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -746,7 +939,7 @@ UNIV_INLINE ibool pfs_os_file_read_no_error_handling_func( /*====================================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -767,7 +960,7 @@ pfs_os_aio_func( ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ @@ -796,7 +989,7 @@ pfs_os_file_write_func( /*===================*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ const void* buf, /*!< in: buffer from which to write */ os_offset_t offset, /*!< in: file offset where to write */ ulint n, /*!< in: number of bytes to write */ @@ -813,7 +1006,7 @@ UNIV_INLINE ibool pfs_os_file_flush_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line);/*!< in: line where the func invoked */ @@ -865,16 +1058,66 @@ pfs_os_file_delete_if_exists_func( string */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line);/*!< in: line where the func invoked */ + +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_set_eof_at(), not +directly this function! +This is the performance schema instrumented wrapper function for +os_file_set_eof_at() +@return TRUE if success */ +UNIV_INLINE +bool +pfs_os_file_set_eof_at_func( + pfs_os_file_t file, /*!< in: handle to a file */ + ib_uint64_t new_len,/*!< in: new file length */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line);/*!< in: line where the func invoked */ + +#ifdef HAVE_POSIX_FALLOCATE +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_allocate(), not +directly this function! +Ensures that disk space is allocated for the file. +@return TRUE if success */ +UNIV_INLINE +bool +pfs_os_file_allocate_func( + pfs_os_file_t file, /*!< in, own: handle to a file */ + os_offset_t offset, /*!< in: file region offset */ + os_offset_t len, /*!< in: file region length */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line);/*!< in: line where the func invoked */ +#endif + #endif /* UNIV_PFS_IO */ /***********************************************************************//** -Closes a file handle. -@return TRUE if success */ +Checks if the file is marked as invalid. +@return TRUE if invalid */ UNIV_INTERN -ibool -os_file_close_no_error_handling( -/*============================*/ - os_file_t file); /*!< in, own: handle to a file */ +bool +os_file_is_invalid( + pfs_os_file_t file); /*!< in, own: handle to a file */ + +/***********************************************************************//** +Marks the file as invalid. */ +UNIV_INTERN +void +os_file_mark_invalid( + pfs_os_file_t* file); /*!< out: pointer to a handle to a file */ + +/***********************************************************************//** +Announces an intention to access file data in a specific pattern in the +future. +@return TRUE if success */ +UNIV_INTERN +bool +os_file_advise( + pfs_os_file_t file, /*!< in, own: handle to a file */ + os_offset_t offset, /*!< in: file region offset */ + os_offset_t len, /*!< in: file region length */ + ulint advice);/*!< in: advice for access pattern */ + /***********************************************************************//** Gets a file size. @return file size, or (os_offset_t) -1 on failure */ @@ -882,7 +1125,7 @@ UNIV_INTERN os_offset_t os_file_get_size( /*=============*/ - os_file_t file) /*!< in: handle to a file */ + pfs_os_file_t file) /*!< in: handle to a file */ MY_ATTRIBUTE((warn_unused_result)); /***********************************************************************//** Write the specified number of zeros to a newly created file. @@ -893,7 +1136,7 @@ os_file_set_size( /*=============*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ os_offset_t size) /*!< in: file size */ MY_ATTRIBUTE((nonnull, warn_unused_result)); /***********************************************************************//** @@ -905,14 +1148,6 @@ os_file_set_eof( /*============*/ FILE* file); /*!< in: file to be truncated */ /***********************************************************************//** -Truncates a file at the specified position. -@return TRUE if success */ -UNIV_INTERN -ibool -os_file_set_eof_at( - os_file_t file, /*!< in: handle to a file */ - ib_uint64_t new_len);/*!< in: new file length */ -/***********************************************************************//** NOTE! Use the corresponding macro os_file_flush(), not directly this function! Flushes the write buffers of a given file to the disk. @return TRUE if success */ @@ -1140,7 +1375,7 @@ os_aio_func( caution! */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ diff --git a/storage/xtradb/include/os0file.ic b/storage/xtradb/include/os0file.ic index 25a1397147e..c82a2559fed 100644 --- a/storage/xtradb/include/os0file.ic +++ b/storage/xtradb/include/os0file.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2010, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2010, 2017, 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 @@ -34,7 +34,7 @@ os_file_create_simple() which opens or creates a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_func( /*===========================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -47,7 +47,7 @@ pfs_os_file_create_simple_func( const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { - os_file_t file; + pfs_os_file_t file; struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; @@ -58,11 +58,13 @@ pfs_os_file_create_simple_func( : PSI_FILE_OPEN), name, src_file, src_line); - file = os_file_create_simple_func(name, create_mode, + file.m_file = os_file_create_simple_func(name, create_mode, access_type, success); + file.m_psi = NULL; - /* Regsiter the returning "file" value with the system */ - register_pfs_file_open_end(locker, file); + /* Regsiter psi value for the file */ + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); return(file); } @@ -76,7 +78,7 @@ monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_simple_no_error_handling_func( /*=============================================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -91,7 +93,7 @@ pfs_os_file_create_simple_no_error_handling_func( const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { - os_file_t file; + pfs_os_file_t file; struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; @@ -104,8 +106,10 @@ pfs_os_file_create_simple_no_error_handling_func( file = os_file_create_simple_no_error_handling_func( name, create_mode, access_type, success); + file.m_psi = NULL; - register_pfs_file_open_end(locker, file); + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); return(file); } @@ -118,7 +122,7 @@ Add instrumentation to monitor file creation/open. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INLINE -os_file_t +pfs_os_file_t pfs_os_file_create_func( /*====================*/ mysql_pfs_key_t key, /*!< in: Performance Schema Key */ @@ -137,7 +141,7 @@ pfs_os_file_create_func( const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { - os_file_t file; + pfs_os_file_t file; struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; @@ -149,8 +153,10 @@ pfs_os_file_create_func( name, src_file, src_line); file = os_file_create_func(name, create_mode, purpose, type, success); + file.m_psi = NULL; - register_pfs_file_open_end(locker, file); + register_pfs_file_open_end(locker, file, + (*success == TRUE ? success : 0)); return(file); } @@ -164,7 +170,7 @@ UNIV_INLINE ibool pfs_os_file_close_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { @@ -176,7 +182,35 @@ pfs_os_file_close_func( register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE, src_file, src_line); - result = os_file_close_func(file); + result = os_file_close_func(file.m_file); + + register_pfs_file_io_end(locker, 0); + + return(result); +} +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_close_no_error_handling(), +not directly this function! +A performance schema instrumented wrapper function for +os_file_close_no_error_handling(). +@return TRUE if success */ +UNIV_INLINE +bool +pfs_os_file_close_no_error_handling_func( +/*===================*/ + pfs_os_file_t file, /*!< in, own: handle to a file */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line)/*!< in: line where the func invoked */ +{ + bool result; + struct PSI_file_locker* locker = NULL; + PSI_file_locker_state state; + + /* register the file close */ + register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE, + src_file, src_line); + + result = os_file_close_no_error_handling_func(file.m_file); register_pfs_file_io_end(locker, 0); @@ -197,7 +231,7 @@ pfs_os_aio_func( ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ @@ -244,7 +278,7 @@ UNIV_INLINE ibool pfs_os_file_read_func( /*==================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -259,7 +293,7 @@ pfs_os_file_read_func( register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ, src_file, src_line); - result = os_file_read_func(file, buf, offset, n, trx); + result = os_file_read_func(file.m_file, buf, offset, n, trx); register_pfs_file_io_end(locker, n); @@ -278,7 +312,7 @@ UNIV_INLINE ibool pfs_os_file_read_no_error_handling_func( /*====================================*/ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ os_offset_t offset, /*!< in: file offset where to read */ ulint n, /*!< in: number of bytes to read */ @@ -292,13 +326,50 @@ pfs_os_file_read_no_error_handling_func( register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ, src_file, src_line); - result = os_file_read_no_error_handling_func(file, buf, offset, n); + result = os_file_read_no_error_handling_func(file.m_file, buf, offset, n); register_pfs_file_io_end(locker, n); return(result); } +/** NOTE! Please use the corresponding macro +os_file_read_no_error_handling_int_fd(), not directly this function! +This is the performance schema instrumented wrapper function for +os_file_read_no_error_handling_int_fd_func() which requests a +synchronous read operation. +@return TRUE if request was successful, FALSE if fail */ +UNIV_INLINE +ibool +pfs_os_file_read_no_error_handling_int_fd_func( + int file, /*!< in: handle to a file */ + void* buf, /*!< in: buffer where to read */ + os_offset_t offset, /*!< in: file offset where to read */ + ulint n, /*!< in: number of bytes to read */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line)/*!< in: line where the func invoked */ +{ + + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &state, file, PSI_FILE_READ); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, n, + __FILE__, __LINE__); + } + ibool result = os_file_read_no_error_handling_func( + OS_FILE_FROM_FD(file), buf, offset, n); + + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, n); + } + + return(result); +} + /*******************************************************************//** NOTE! Please use the corresponding macro os_file_write(), not directly this function! @@ -311,7 +382,7 @@ pfs_os_file_write_func( /*===================*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ const void* buf, /*!< in: buffer from which to write */ os_offset_t offset, /*!< in: file offset where to write */ ulint n, /*!< in: number of bytes to write */ @@ -325,13 +396,50 @@ pfs_os_file_write_func( register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_WRITE, src_file, src_line); - result = os_file_write_func(name, file, buf, offset, n); + result = os_file_write_func(name, file.m_file, buf, offset, n); register_pfs_file_io_end(locker, n); return(result); } +/** NOTE! Please use the corresponding macro os_file_write(), not +directly this function! +This is the performance schema instrumented wrapper function for +os_file_write() which requests a synchronous write operation. +@return TRUE if request was successful, FALSE if fail */ +UNIV_INLINE +ibool +pfs_os_file_write_int_fd_func( + const char* name, /*!< in: name of the file or path as a + null-terminated string */ + int file, /*!< in: handle to a file */ + const void* buf, /*!< in: buffer from which to write */ + os_offset_t offset, /*!< in: file offset where to write */ + ulint n, /*!< in: number of bytes to write */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line)/*!< in: line where the func invoked */ +{ + PSI_file_locker_state state; + struct PSI_file_locker* locker = NULL; + + locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &state, file, PSI_FILE_WRITE); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, n, + __FILE__, __LINE__); + } + ibool result = os_file_write_func( + name, OS_FILE_FROM_FD(file), buf, offset, n); + + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, n); + } + + return(result); +} + /***********************************************************************//** NOTE! Please use the corresponding macro os_file_flush(), not directly this function! @@ -342,7 +450,7 @@ UNIV_INLINE ibool pfs_os_file_flush_func( /*===================*/ - os_file_t file, /*!< in, own: handle to a file */ + pfs_os_file_t file, /*!< in, own: handle to a file */ const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { @@ -352,7 +460,7 @@ pfs_os_file_flush_func( register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_SYNC, src_file, src_line); - result = os_file_flush_func(file); + result = os_file_flush_func(file.m_file); register_pfs_file_io_end(locker, 0); @@ -380,12 +488,12 @@ pfs_os_file_rename_func( struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; - register_pfs_file_open_begin(&state, locker, key, PSI_FILE_RENAME, newpath, + register_pfs_file_rename_begin(&state, locker, key, PSI_FILE_RENAME, newpath, src_file, src_line); result = os_file_rename_func(oldpath, newpath); - register_pfs_file_open_end(locker, 0); + register_pfs_file_rename_end(locker, 0); return(result); } @@ -449,4 +557,61 @@ pfs_os_file_delete_if_exists_func( return(result); } + +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_set_eof_at(), not +directly this function! +This is the performance schema instrumented wrapper function for +os_file_set_eof_at() +@return TRUE if success */ +UNIV_INLINE +bool +pfs_os_file_set_eof_at_func( + pfs_os_file_t file, /*!< in: handle to a file */ + ib_uint64_t new_len,/*!< in: new file length */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line)/*!< in: line where the func invoked */ +{ + bool result; + struct PSI_file_locker* locker = NULL; + PSI_file_locker_state state; + + register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CHSIZE, + src_file, src_line); + result = os_file_set_eof_at_func(file.m_file, new_len); + + register_pfs_file_io_end(locker, 0); + + return(result); +} + +#ifdef HAVE_POSIX_FALLOCATE +/***********************************************************************//** +NOTE! Please use the corresponding macro os_file_allocate(), not +directly this function! +Ensures that disk space is allocated for the file. +@return TRUE if success */ +UNIV_INLINE +bool +pfs_os_file_allocate_func( + pfs_os_file_t file, /*!< in, own: handle to a file */ + os_offset_t offset, /*!< in: file region offset */ + os_offset_t len, /*!< in: file region length */ + const char* src_file,/*!< in: file name where func invoked */ + ulint src_line)/*!< in: line where the func invoked */ +{ + bool result; + struct PSI_file_locker* locker = NULL; + PSI_file_locker_state state; + + register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CHSIZE, + src_file, src_line); + result = os_file_allocate_func(file.m_file, offset, len); + + register_pfs_file_io_end(locker, 0); + + return(result); +} +#endif + #endif /* UNIV_PFS_IO */ diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index 27d3adfc7f0..eb604d05557 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -681,6 +681,12 @@ struct mysql_row_templ_t { Innobase record in the current index; not defined if template_type is ROW_MYSQL_WHOLE_ROW */ + bool rec_field_is_prefix; /* is this field in a prefix index? */ + ulint rec_prefix_field_no; /* record field, even if just a + prefix; same as rec_field_no when not a + prefix, otherwise rec_field_no is + ULINT_UNDEFINED but this is the true + field number*/ ulint clust_rec_field_no; /*!< field number of the column in an Innobase record in the clustered index; not defined if template_type is @@ -729,6 +735,8 @@ struct mysql_row_templ_t { #define ROW_PREBUILT_ALLOCATED 78540783 #define ROW_PREBUILT_FREED 26423527 +class ha_innobase; + /** A struct for (sometimes lazily) prebuilt structures in an Innobase table handle used within MySQL; these are used to save CPU time. */ @@ -784,7 +792,9 @@ struct row_prebuilt_t { columns through a secondary index and at least one column is not in the secondary index, then this is - set to TRUE */ + set to TRUE; note that sometimes this + is set but we later optimize out the + clustered index lookup */ unsigned templ_contains_blob:1;/*!< TRUE if the template contains a column with DATA_BLOB == get_innobase_type_from_mysql_type(); @@ -958,6 +968,12 @@ struct row_prebuilt_t { to InnoDB format.*/ uint srch_key_val_len; /*!< Size of search key */ + /** MySQL handler object. */ + ha_innobase* mysql_handler; + + /** True if exceeded the end_range while filling the prefetch cache. */ + bool end_range; + }; /** Callback for row_mysql_sys_index_iterate() */ diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 882ceae2417..0fb563f539c 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. @@ -588,6 +588,11 @@ extern my_bool srv_print_all_deadlocks; extern my_bool srv_cmp_per_index_enabled; +/** Number of times secondary index lookup triggered cluster lookup */ +extern ulint srv_sec_rec_cluster_reads; +/** Number of times prefix optimization avoided triggering cluster lookup */ +extern ulint srv_sec_rec_cluster_reads_avoided; + /** Status variables to be passed to MySQL */ extern struct export_var_t export_vars; @@ -973,6 +978,13 @@ void srv_purge_wakeup(void); /*==================*/ +/** Check whether given space id is undo tablespace id +@param[in] space_id space id to check +@return true if it is undo tablespace else false. */ +bool +srv_is_undo_tablespace( + ulint space_id); + /** Status variables to be passed to MySQL */ struct export_var_t{ ulint innodb_adaptive_hash_hash_searches; @@ -1085,6 +1097,9 @@ struct export_var_t{ #endif /* UNIV_DEBUG */ ulint innodb_column_compressed; /*!< srv_column_compressed */ ulint innodb_column_decompressed; /*!< srv_column_decompressed */ + + ulint innodb_sec_rec_cluster_reads; /*!< srv_sec_rec_cluster_reads */ + ulint innodb_sec_rec_cluster_reads_avoided; /*!< srv_sec_rec_cluster_reads_avoided */ }; /** Thread slot in the thread table. */ diff --git a/storage/xtradb/include/srv0start.h b/storage/xtradb/include/srv0start.h index 963b767f0fb..a60776a4665 100644 --- a/storage/xtradb/include/srv0start.h +++ b/storage/xtradb/include/srv0start.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, 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 @@ -139,6 +139,8 @@ extern ibool srv_startup_is_before_trx_rollback_phase; /** TRUE if a raw partition is in use */ extern ibool srv_start_raw_disk_in_use; +/** Undo tablespaces starts with space_id. */ +extern ulint srv_undo_space_id_start; /** Shutdown state */ enum srv_shutdown_state { diff --git a/storage/xtradb/include/trx0xa.h b/storage/xtradb/include/trx0xa.h index 7caddfb7ba4..255431293f5 100644 --- a/storage/xtradb/include/trx0xa.h +++ b/storage/xtradb/include/trx0xa.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,6 +24,8 @@ this program; if not, write to the Free Software Foundation, Inc., #ifndef XA_H #define XA_H +#include "xa.h" + /* * Transaction branch identification: XID and NULLXID: */ @@ -35,17 +37,6 @@ this program; if not, write to the Free Software Foundation, Inc., #define MAXGTRIDSIZE 64 /*!< maximum size in bytes of gtrid */ #define MAXBQUALSIZE 64 /*!< maximum size in bytes of bqual */ -/** X/Open XA distributed transaction identifier */ -struct xid_t { - long formatID; /*!< format identifier; -1 - means that the XID is null */ - long gtrid_length; /*!< value from 1 through 64 */ - long bqual_length; /*!< value from 1 through 64 */ - char data[XIDDATASIZE]; /*!< distributed transaction - identifier */ -}; -/** X/Open XA distributed transaction identifier */ -typedef struct xid_t XID; #endif /** X/Open XA distributed transaction status codes */ /* @{ */ diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 7da293542f5..b4ad030a565 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 80.0 +#define PERCONA_INNODB_VERSION 82.0 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ @@ -145,14 +145,8 @@ HAVE_PSI_INTERFACE is defined. */ #if defined HAVE_PSI_INTERFACE && !defined UNIV_HOTBACKUP # define UNIV_PFS_MUTEX # define UNIV_PFS_RWLOCK -/* For I/O instrumentation, performance schema rely -on a native descriptor to identify the file, this -descriptor could conflict with our OS level descriptor. -Disable IO instrumentation on Windows until this is -resolved */ -# ifndef __WIN__ -# define UNIV_PFS_IO -# endif + +# define UNIV_PFS_IO # define UNIV_PFS_THREAD /* There are mutexes/rwlocks that we want to exclude from diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc index 7784e8538b7..f73d5b458d1 100644 --- a/storage/xtradb/log/log0log.cc +++ b/storage/xtradb/log/log0log.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -2627,7 +2627,7 @@ log_group_archive( /*==============*/ log_group_t* group) /*!< in: log group */ { - os_file_t file_handle; + pfs_os_file_t file_handle; lsn_t start_lsn; lsn_t end_lsn; char name[OS_FILE_MAX_PATH]; @@ -3607,9 +3607,15 @@ loop: lsn = log_sys->lsn; - if (lsn != log_sys->last_checkpoint_lsn - || (srv_track_changed_pages - && (tracked_lsn != log_sys->last_checkpoint_lsn)) + const bool is_last = + ((srv_force_recovery == SRV_FORCE_NO_LOG_REDO + && lsn == log_sys->last_checkpoint_lsn + + LOG_BLOCK_HDR_SIZE) + || lsn == log_sys->last_checkpoint_lsn) + && (!srv_track_changed_pages + || tracked_lsn == log_sys->last_checkpoint_lsn); + + if (!is_last #ifdef UNIV_LOG_ARCHIVE || (srv_log_archive_on && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE) @@ -3675,7 +3681,8 @@ loop: ut_a(freed); ut_a(lsn == log_sys->lsn); - ut_ad(lsn == log_sys->last_checkpoint_lsn); + ut_ad(srv_force_recovery >= SRV_FORCE_NO_LOG_REDO + || lsn == log_sys->last_checkpoint_lsn); if (lsn < srv_start_lsn) { ib_logf(IB_LOG_LEVEL_ERROR, diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 8d1952fdd04..99762c00a08 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -336,7 +336,7 @@ log_online_read_last_tracked_lsn(void) lsn_t result; os_offset_t read_offset = log_bmp_sys->out.offset; - while (!checksum_ok && read_offset > 0 && !is_last_page) + while ((!checksum_ok || !is_last_page) && read_offset > 0) { read_offset -= MODIFIED_PAGE_BLOCK_SIZE; log_bmp_sys->out.offset = read_offset; @@ -564,9 +564,9 @@ log_online_rotate_bitmap_file( lsn_t next_file_start_lsn) /*!out.file != os_file_invalid) { + if (!os_file_is_invalid(log_bmp_sys->out.file)) { os_file_close(log_bmp_sys->out.file); - log_bmp_sys->out.file = os_file_invalid; + os_file_mark_invalid(&log_bmp_sys->out.file); } log_bmp_sys->out_seq_num++; log_online_make_bitmap_name(next_file_start_lsn); @@ -736,7 +736,11 @@ log_online_read_init(void) } last_tracked_lsn = log_online_read_last_tracked_lsn(); + /* Do not rotate if we truncated the file to zero length - we + can just start writing there */ + const bool need_rotate = (last_tracked_lsn != 0); if (!last_tracked_lsn) { + last_tracked_lsn = last_file_start_lsn; } @@ -748,7 +752,10 @@ log_online_read_init(void) } else { file_start_lsn = tracking_start_lsn; } - if (!log_online_rotate_bitmap_file(file_start_lsn)) { + + if (need_rotate + && !log_online_rotate_bitmap_file(file_start_lsn)) { + exit(1); } @@ -788,9 +795,9 @@ log_online_read_shutdown(void) ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list; - if (log_bmp_sys->out.file != os_file_invalid) { + if (!os_file_is_invalid(log_bmp_sys->out.file)) { os_file_close(log_bmp_sys->out.file); - log_bmp_sys->out.file = os_file_invalid; + os_file_mark_invalid(&log_bmp_sys->out.file); } rbt_free(log_bmp_sys->modified_pages); @@ -1129,6 +1136,18 @@ log_online_write_bitmap_page( } }); + /* A crash injection site that ensures last checkpoint LSN > last + tracked LSN, so that LSN tracking for this interval is tested. */ + DBUG_EXECUTE_IF("crash_before_bitmap_write", + { + ulint space_id + = mach_read_from_4(block + + MODIFIED_PAGE_SPACE_ID); + if (space_id > 0) + DBUG_SUICIDE(); + }); + + ibool success = os_file_write(log_bmp_sys->out.name, log_bmp_sys->out.file, block, log_bmp_sys->out.offset, @@ -1152,10 +1171,8 @@ log_online_write_bitmap_page( return FALSE; } -#ifdef UNIV_LINUX - posix_fadvise(log_bmp_sys->out.file, log_bmp_sys->out.offset, - MODIFIED_PAGE_BLOCK_SIZE, POSIX_FADV_DONTNEED); -#endif + os_file_advise(log_bmp_sys->out.file, log_bmp_sys->out.offset, + MODIFIED_PAGE_BLOCK_SIZE, OS_FILE_ADVISE_DONTNEED); log_bmp_sys->out.offset += MODIFIED_PAGE_BLOCK_SIZE; return TRUE; @@ -1277,10 +1294,6 @@ log_online_follow_redo_log(void) group = UT_LIST_GET_NEXT(log_groups, group); } - /* A crash injection site that ensures last checkpoint LSN > last - tracked LSN, so that LSN tracking for this interval is tested. */ - DBUG_EXECUTE_IF("crash_before_bitmap_write", DBUG_SUICIDE();); - result = log_online_write_bitmap(); log_bmp_sys->start_lsn = log_bmp_sys->end_lsn; log_set_tracked_lsn(log_bmp_sys->start_lsn); @@ -1550,10 +1563,8 @@ log_online_open_bitmap_file_read_only( bitmap_file->size = os_file_get_size(bitmap_file->file); bitmap_file->offset = 0; -#ifdef UNIV_LINUX - posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_SEQUENTIAL); - posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_NOREUSE); -#endif + os_file_advise(bitmap_file->file, 0, 0, OS_FILE_ADVISE_SEQUENTIAL); + os_file_advise(bitmap_file->file, 0, 0, OS_FILE_ADVISE_NOREUSE); return TRUE; } @@ -1639,7 +1650,7 @@ log_online_bitmap_iterator_init( /* Empty range */ i->in_files.count = 0; i->in_files.files = NULL; - i->in.file = os_file_invalid; + os_file_mark_invalid(&i->in.file); i->page = NULL; i->failed = FALSE; return TRUE; @@ -1657,7 +1668,7 @@ log_online_bitmap_iterator_init( if (i->in_files.count == 0) { /* Empty range */ - i->in.file = os_file_invalid; + os_file_mark_invalid(&i->in.file); i->page = NULL; i->failed = FALSE; return TRUE; @@ -1696,10 +1707,10 @@ log_online_bitmap_iterator_release( { ut_a(i); - if (i->in.file != os_file_invalid) { + if (!os_file_is_invalid(i->in.file)) { os_file_close(i->in.file); - i->in.file = os_file_invalid; + os_file_mark_invalid(&i->in.file); } if (i->in_files.files) { @@ -1753,8 +1764,9 @@ log_online_bitmap_iterator_next( /* Advance file */ i->in_i++; - success = os_file_close_no_error_handling(i->in.file); - i->in.file = os_file_invalid; + success = os_file_close_no_error_handling( + i->in.file); + os_file_mark_invalid(&i->in.file); if (UNIV_UNLIKELY(!success)) { os_file_get_last_error(TRUE); @@ -1863,7 +1875,7 @@ log_online_purge_changed_page_bitmaps( /* If we have to delete the current output file, close it first. */ os_file_close(log_bmp_sys->out.file); - log_bmp_sys->out.file = os_file_invalid; + os_file_mark_invalid(&log_bmp_sys->out.file); } for (i = 0; i < bitmap_files.count; i++) { diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc index b80f1f8597e..b2e55faffca 100644 --- a/storage/xtradb/log/log0recv.cc +++ b/storage/xtradb/log/log0recv.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -324,6 +324,7 @@ DECLARE_THREAD(recv_writer_thread)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_ad(!srv_read_only_mode); #ifdef UNIV_PFS_THREAD @@ -356,6 +357,7 @@ DECLARE_THREAD(recv_writer_thread)( recv_writer_thread_active = false; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index dac67055114..9b2a2746976 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -1,6 +1,6 @@ /*********************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted @@ -82,9 +82,11 @@ my_umask */ #ifndef __WIN__ /** Umask for creating files */ UNIV_INTERN ulint os_innodb_umask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; +# define os_file_invalid (-1) #else /** Umask for creating files */ UNIV_INTERN ulint os_innodb_umask = 0; +# define os_file_invalid INVALID_HANDLE_VALUE #endif /* __WIN__ */ #ifndef UNIV_HOTBACKUP @@ -173,7 +175,7 @@ struct os_aio_slot_t{ byte* buf; /*!< buffer used in i/o */ ulint type; /*!< OS_FILE_READ or OS_FILE_WRITE */ os_offset_t offset; /*!< file offset in bytes */ - os_file_t file; /*!< file where to read or write */ + pfs_os_file_t file; /*!< file where to read or write */ const char* name; /*!< file name or path */ ibool io_already_done;/*!< used only in simulated aio: TRUE if the physical i/o already @@ -1347,7 +1349,7 @@ A simple function to open or create a file. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_simple_no_error_handling_func( /*=========================================*/ const char* name, /*!< in: name of the file or path as a @@ -1361,7 +1363,7 @@ os_file_create_simple_no_error_handling_func( if it would be enabled otherwise) */ ibool* success)/*!< out: TRUE if succeed, FALSE if error */ { - os_file_t file; + pfs_os_file_t file; *success = FALSE; #ifdef __WIN__ @@ -1369,7 +1371,6 @@ os_file_create_simple_no_error_handling_func( DWORD create_flag; DWORD attributes = 0; DWORD share_mode = FILE_SHARE_READ; - ut_a(name); ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); @@ -1386,8 +1387,8 @@ os_file_create_simple_no_error_handling_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown file create mode (%lu) for file '%s'", create_mode, name); - - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); } if (access_type == OS_FILE_READ_ONLY) { @@ -1411,11 +1412,11 @@ os_file_create_simple_no_error_handling_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown file access type (%lu) for file '%s'", access_type, name); - - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); } - file = CreateFile((LPCTSTR) name, + file.m_file = CreateFile((LPCTSTR) name, access, share_mode, NULL, // Security attributes @@ -1423,11 +1424,10 @@ os_file_create_simple_no_error_handling_func( attributes, NULL); // No template file - *success = (file != INVALID_HANDLE_VALUE); + *success = (file.m_file != INVALID_HANDLE_VALUE); #else /* __WIN__ */ int create_flag; const char* mode_str = NULL; - ut_a(name); ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); @@ -1470,19 +1470,19 @@ os_file_create_simple_no_error_handling_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown file create mode (%lu) for file '%s'", create_mode, name); - - return((os_file_t) -1); + file.m_file = -1; + return(file); } - file = ::open(name, create_flag, os_innodb_umask); + file.m_file = ::open(name, create_flag, os_innodb_umask); - *success = file == -1 ? FALSE : TRUE; + *success = file.m_file == -1 ? FALSE : TRUE; /* This function is always called for data files, we should disable OS caching (O_DIRECT) here as we do in os_file_create_func(), so we open the same file in the same mode, see man page of open(2). */ if (*success) { - os_file_set_nocache_if_needed(file, name, mode_str, + os_file_set_nocache_if_needed(file.m_file, name, mode_str, OS_DATA_FILE, access_type); } @@ -1491,11 +1491,11 @@ os_file_create_simple_no_error_handling_func( && *success && (access_type == OS_FILE_READ_WRITE || access_type == OS_FILE_READ_WRITE_CACHED) - && os_file_lock(file, name)) { + && os_file_lock(file.m_file, name)) { *success = FALSE; - close(file); - file = -1; + close(file.m_file); + file.m_file = -1; } #endif /* USE_FILE_LOCK */ @@ -1606,7 +1606,7 @@ Opens an existing file or creates a new. @return own: handle to the file, not defined if error, error number can be retrieved with os_file_get_last_error */ UNIV_INTERN -os_file_t +pfs_os_file_t os_file_create_func( /*================*/ const char* name, /*!< in: name of the file or path as a @@ -1622,24 +1622,25 @@ os_file_create_func( ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */ ibool* success)/*!< out: TRUE if succeed, FALSE if error */ { - os_file_t file; + pfs_os_file_t file; ibool retry; ibool on_error_no_exit; ibool on_error_silent; - #ifdef __WIN__ DBUG_EXECUTE_IF( "ib_create_table_fail_disk_full", *success = FALSE; SetLastError(ERROR_DISK_FULL); - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); ); #else /* __WIN__ */ DBUG_EXECUTE_IF( "ib_create_table_fail_disk_full", *success = FALSE; errno = ENOSPC; - return((os_file_t) -1); + file.m_file = -1; + return(file); ); #endif /* __WIN__ */ @@ -1690,7 +1691,8 @@ os_file_create_func( "Unknown file create mode (%lu) for file '%s'", create_mode, name); - return((os_file_t) -1); + file.m_file = (os_file_t)-1; + return(file); } DWORD attributes = 0; @@ -1715,8 +1717,8 @@ os_file_create_func( ib_logf(IB_LOG_LEVEL_ERROR, "Unknown purpose flag (%lu) while opening file '%s'", purpose, name); - - return((os_file_t)(-1)); + file.m_file = (os_file_t)-1; + return(file); } #ifdef UNIV_NON_BUFFERED_IO @@ -1743,11 +1745,11 @@ os_file_create_func( do { /* Use default security attributes and no template file. */ - file = CreateFile( + file.m_file = CreateFile( (LPCTSTR) name, access, share_mode, NULL, create_flag, attributes, NULL); - if (file == INVALID_HANDLE_VALUE) { + if (file.m_file == INVALID_HANDLE_VALUE) { const char* operation; operation = (create_mode == OS_FILE_CREATE @@ -1772,7 +1774,6 @@ os_file_create_func( #else /* __WIN__ */ int create_flag; const char* mode_str = NULL; - on_error_no_exit = create_mode & OS_FILE_ON_ERROR_NO_EXIT ? TRUE : FALSE; on_error_silent = create_mode & OS_FILE_ON_ERROR_SILENT @@ -1810,7 +1811,8 @@ os_file_create_func( "Unknown file create mode (%lu) for file '%s'", create_mode, name); - return((os_file_t) -1); + file.m_file = -1; + return(file); } ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE); @@ -1830,9 +1832,9 @@ os_file_create_func( #endif /* O_SYNC */ do { - file = ::open(name, create_flag, os_innodb_umask); + file.m_file = ::open(name, create_flag, os_innodb_umask); - if (file == -1) { + if (file.m_file == -1) { const char* operation; operation = (create_mode == OS_FILE_CREATE @@ -1856,14 +1858,15 @@ os_file_create_func( if (*success) { - os_file_set_nocache_if_needed(file, name, mode_str, type, 0); + os_file_set_nocache_if_needed(file.m_file, name, mode_str, + type, 0); } #ifdef USE_FILE_LOCK if (!srv_read_only_mode && *success && create_mode != OS_FILE_OPEN_RAW - && os_file_lock(file, name)) { + && os_file_lock(file.m_file, name)) { if (create_mode == OS_FILE_OPEN_RETRY) { @@ -1875,7 +1878,7 @@ os_file_create_func( for (int i = 0; i < 100; i++) { os_thread_sleep(1000000); - if (!os_file_lock(file, name)) { + if (!os_file_lock(file.m_file, name)) { *success = TRUE; return(file); } @@ -1886,17 +1889,18 @@ os_file_create_func( } *success = FALSE; - close(file); - file = -1; + close(file.m_file); + file.m_file = -1; } #endif /* USE_FILE_LOCK */ if (srv_use_atomic_writes && type == OS_DATA_FILE - && file != -1 && !os_file_set_atomic_writes(name, file)) { + && file.m_file != -1 + && !os_file_set_atomic_writes(name, file.m_file)) { *success = FALSE; - close(file); - file = -1; + close(file.m_file); + file.m_file = -1; } #endif /* __WIN__ */ @@ -2127,8 +2131,8 @@ os_file_close_func( Closes a file handle. @return TRUE if success */ UNIV_INTERN -ibool -os_file_close_no_error_handling( +bool +os_file_close_no_error_handling_func( /*============================*/ os_file_t file) /*!< in, own: handle to a file */ { @@ -2140,10 +2144,10 @@ os_file_close_no_error_handling( ret = CloseHandle(file); if (ret) { - return(TRUE); + return(true); } - return(FALSE); + return(false); #else int ret; @@ -2151,10 +2155,83 @@ os_file_close_no_error_handling( if (ret == -1) { - return(FALSE); + return(false); } - return(TRUE); + return(true); +#endif /* __WIN__ */ +} + +#ifdef HAVE_POSIX_FALLOCATE +/***********************************************************************//** +Ensures that disk space is allocated for the file. +@return TRUE if success */ +UNIV_INTERN +bool +os_file_allocate_func( + os_file_t file, /*!< in, own: handle to a file */ + os_offset_t offset, /*!< in: file region offset */ + os_offset_t len) /*!< in: file region length */ +{ + return(posix_fallocate(file, offset, len) == 0); +} +#endif + +/***********************************************************************//** +Checks if the file is marked as invalid. +@return TRUE if invalid */ +UNIV_INTERN +bool +os_file_is_invalid( + pfs_os_file_t file) /*!< in, own: handle to a file */ +{ + return(file.m_file == os_file_invalid); +} + +/***********************************************************************//** +Marks the file as invalid. */ +UNIV_INTERN +void +os_file_mark_invalid( + pfs_os_file_t* file) /*!< out: pointer to a handle to a file */ +{ + file->m_file = os_file_invalid; +} + +/***********************************************************************//** +Announces an intention to access file data in a specific pattern in the +future. +@return TRUE if success */ +UNIV_INTERN +bool +os_file_advise( + pfs_os_file_t file, /*!< in, own: handle to a file */ + os_offset_t offset, /*!< in: file region offset */ + os_offset_t len, /*!< in: file region length */ + ulint advice)/*!< in: advice for access pattern */ +{ +#ifdef __WIN__ + return(true); +#else +#ifdef UNIV_LINUX + int native_advice = 0; + if ((advice & OS_FILE_ADVISE_NORMAL) != 0) + native_advice |= POSIX_FADV_NORMAL; + if ((advice & OS_FILE_ADVISE_RANDOM) != 0) + native_advice |= POSIX_FADV_RANDOM; + if ((advice & OS_FILE_ADVISE_SEQUENTIAL) != 0) + native_advice |= POSIX_FADV_SEQUENTIAL; + if ((advice & OS_FILE_ADVISE_WILLNEED) != 0) + native_advice |= POSIX_FADV_WILLNEED; + if ((advice & OS_FILE_ADVISE_DONTNEED) != 0) + native_advice |= POSIX_FADV_DONTNEED; + if ((advice & OS_FILE_ADVISE_NOREUSE) != 0) + native_advice |= POSIX_FADV_NOREUSE; + + return(posix_fadvise(file.m_file, offset, len, native_advice) == 0); +#else + return(true); +#endif #endif /* __WIN__ */ } @@ -2165,14 +2242,14 @@ UNIV_INTERN os_offset_t os_file_get_size( /*=============*/ - os_file_t file) /*!< in: handle to a file */ + pfs_os_file_t file) /*!< in: handle to a file */ { #ifdef __WIN__ os_offset_t offset; DWORD high; DWORD low; - low = GetFileSize(file, &high); + low = GetFileSize(file.m_file, &high); if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) { return((os_offset_t) -1); @@ -2182,7 +2259,8 @@ os_file_get_size( return(offset); #else - return((os_offset_t) lseek(file, 0, SEEK_END)); + return((os_offset_t) lseek(file.m_file, 0, SEEK_END)); + #endif /* __WIN__ */ } @@ -2195,7 +2273,7 @@ os_file_set_size( /*=============*/ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ os_offset_t size) /*!< in: file size */ { os_offset_t current_size; @@ -2209,7 +2287,7 @@ os_file_set_size( #ifdef HAVE_POSIX_FALLOCATE if (srv_use_posix_fallocate) { - if (posix_fallocate(file, current_size, size) == -1) { + if (posix_fallocate(file.m_file, current_size, size) == -1) { ib_logf(IB_LOG_LEVEL_ERROR, "preallocating file " "space for file \'%s\' failed. Current size " @@ -2304,8 +2382,8 @@ os_file_set_eof( Truncates a file at the specified position. @return TRUE if success */ UNIV_INTERN -ibool -os_file_set_eof_at( +bool +os_file_set_eof_at_func( os_file_t file, /*!< in: handle to a file */ ib_uint64_t new_len)/*!< in: new file length */ { @@ -4400,7 +4478,7 @@ os_aio_array_reserve_slot( the aio operation */ void* message2,/*!< in: message to be passed along with the aio operation */ - os_file_t file, /*!< in: file handle */ + pfs_os_file_t file, /*!< in: file handle */ const char* name, /*!< in: name of the file or path as a null-terminated string */ void* buf, /*!< in: buffer where to read or from which @@ -4522,10 +4600,10 @@ found: iocb = &slot->control; if (type == OS_FILE_READ) { - io_prep_pread(iocb, file, buf, len, aio_offset); + io_prep_pread(iocb, file.m_file, buf, len, aio_offset); } else { ut_a(type == OS_FILE_WRITE); - io_prep_pwrite(iocb, file, buf, len, aio_offset); + io_prep_pwrite(iocb, file.m_file, buf, len, aio_offset); } iocb->data = (void*) slot; @@ -4763,7 +4841,7 @@ os_aio_func( caution! */ const char* name, /*!< in: name of the file or path as a null-terminated string */ - os_file_t file, /*!< in: handle to a file */ + pfs_os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read or from which to write */ os_offset_t offset, /*!< in: file offset where to read or write */ @@ -4790,8 +4868,7 @@ os_aio_func( ulint dummy_type; #endif /* WIN_ASYNC_IO */ ulint wake_later; - - ut_ad(file); + ut_ad(file.m_file); ut_ad(buf); ut_ad(n > 0); ut_ad(n % OS_MIN_LOG_BLOCK_SIZE == 0); @@ -4823,13 +4900,12 @@ os_aio_func( and os_file_write_func() */ if (type == OS_FILE_READ) { - return(os_file_read_func(file, buf, offset, n, trx)); + return(os_file_read_func(file.m_file, buf, offset, n, + trx)); } - ut_ad(!srv_read_only_mode); ut_a(type == OS_FILE_WRITE); - - return(os_file_write_func(name, file, buf, offset, n)); + return(os_file_write_func(name, file.m_file, buf, offset, n)); } try_again: @@ -4886,9 +4962,8 @@ try_again: os_n_file_reads++; os_bytes_read_since_printout += n; #ifdef WIN_ASYNC_IO - ret = ReadFile(file, buf, (DWORD) n, &len, + ret = ReadFile(file.m_file, buf, (DWORD) n, &len, &(slot->control)); - #elif defined(LINUX_NATIVE_AIO) if (!os_aio_linux_dispatch(array, slot)) { goto err_exit; @@ -4906,9 +4981,8 @@ try_again: if (srv_use_native_aio) { os_n_file_writes++; #ifdef WIN_ASYNC_IO - ret = WriteFile(file, buf, (DWORD) n, &len, + ret = WriteFile(file.m_file, buf, (DWORD) n, &len, &(slot->control)); - #elif defined(LINUX_NATIVE_AIO) if (!os_aio_linux_dispatch(array, slot)) { goto err_exit; @@ -5063,8 +5137,7 @@ os_aio_windows_handle( srv_set_io_thread_op_info( orig_seg, "get windows aio return value"); } - - ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE); + ret = GetOverlappedResult(slot->file.m_file, &(slot->control), &len, TRUE); *message1 = slot->message1; *message2 = slot->message2; @@ -5094,7 +5167,8 @@ os_aio_windows_handle( and os_file_write APIs, need to register with performance schema explicitly here. */ struct PSI_file_locker* locker = NULL; - register_pfs_file_io_begin(locker, slot->file, slot->len, + PSI_file_locker_state state; + register_pfs_file_io_begin(&state, locker, slot->file, slot->len, (slot->type == OS_FILE_WRITE) ? PSI_FILE_WRITE : PSI_FILE_READ, @@ -5105,16 +5179,14 @@ os_aio_windows_handle( switch (slot->type) { case OS_FILE_WRITE: - ret = WriteFile(slot->file, slot->buf, + ret = WriteFile(slot->file.m_file, slot->buf, (DWORD) slot->len, &len, &(slot->control)); - break; case OS_FILE_READ: - ret = ReadFile(slot->file, slot->buf, + ret = ReadFile(slot->file.m_file, slot->buf, (DWORD) slot->len, &len, &(slot->control)); - break; default: ut_error; @@ -5130,8 +5202,7 @@ os_aio_windows_handle( file where we also use async i/o: in Windows we must use the same wait mechanism as for async i/o */ - - ret = GetOverlappedResult(slot->file, + ret = GetOverlappedResult(slot->file.m_file, &(slot->control), &len, TRUE); } @@ -5385,12 +5456,14 @@ found: iocb = &(slot->control); if (slot->type == OS_FILE_READ) { - io_prep_pread(&slot->control, slot->file, slot->buf, - slot->len, (off_t) slot->offset); + io_prep_pread(&slot->control, slot->file.m_file, + slot->buf, slot->len, + (off_t) slot->offset); } else { ut_a(slot->type == OS_FILE_WRITE); - io_prep_pwrite(&slot->control, slot->file, slot->buf, - slot->len, (off_t) slot->offset); + io_prep_pwrite(&slot->control, slot->file.m_file, + slot->buf, slot->len, + (off_t) slot->offset); } /* Resubmit an I/O request */ submit_ret = io_submit(array->aio_ctx[segment], 1, &iocb); @@ -5617,12 +5690,11 @@ consecutive_loop: os_aio_slot_t* slot; slot = os_aio_array_get_nth_slot(array, i + segment * n); - if (slot->reserved && slot != aio_slot && slot->offset == aio_slot->offset + aio_slot->len && slot->type == aio_slot->type - && slot->file == aio_slot->file) { + && slot->file.m_file == aio_slot->file.m_file) { /* Found a consecutive i/o request */ diff --git a/storage/xtradb/pars/pars0opt.cc b/storage/xtradb/pars/pars0opt.cc index cbed2b39eeb..5a7e1861d74 100644 --- a/storage/xtradb/pars/pars0opt.cc +++ b/storage/xtradb/pars/pars0opt.cc @@ -948,12 +948,14 @@ opt_find_all_cols( /* Fill in the field_no fields in sym_node */ sym_node->field_nos[SYM_CLUST_FIELD_NO] = dict_index_get_nth_col_pos( - dict_table_get_first_index(index->table), sym_node->col_no); + dict_table_get_first_index(index->table), sym_node->col_no, + NULL); if (!dict_index_is_clust(index)) { ut_a(plan); - col_pos = dict_index_get_nth_col_pos(index, sym_node->col_no); + col_pos = dict_index_get_nth_col_pos(index, sym_node->col_no, + NULL); if (col_pos == ULINT_UNDEFINED) { diff --git a/storage/xtradb/pars/pars0pars.cc b/storage/xtradb/pars/pars0pars.cc index b116357c5b9..ea65d16e9dc 100644 --- a/storage/xtradb/pars/pars0pars.cc +++ b/storage/xtradb/pars/pars0pars.cc @@ -1232,7 +1232,8 @@ pars_process_assign_list( col_sym = assign_node->col; upd_field_set_field_no(upd_field, dict_index_get_nth_col_pos( - clust_index, col_sym->col_no), + clust_index, col_sym->col_no, + NULL), clust_index, NULL); upd_field->exp = assign_node->val; diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 54183759e8d..4596e2fb951 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/row/row0log.cc @@ -363,9 +363,9 @@ row_log_online_op( goto err_exit; } - ret = os_file_write( + ret = os_file_write_int_fd( "(modification log)", - OS_FILE_FROM_FD(log->fd), + log->fd, log->tail.block, byte_offset, srv_sort_buf_size); log->tail.blocks++; if (!ret) { @@ -479,9 +479,9 @@ row_log_table_close_func( goto err_exit; } - ret = os_file_write( + ret = os_file_write_int_fd( "(modification log)", - OS_FILE_FROM_FD(log->fd), + log->fd, log->tail.block, byte_offset, srv_sort_buf_size); log->tail.blocks++; if (!ret) { @@ -2609,11 +2609,10 @@ all_done: goto func_exit; } - success = os_file_read_no_error_handling( - OS_FILE_FROM_FD(index->online_log->fd), + success = os_file_read_no_error_handling_int_fd( + index->online_log->fd, index->online_log->head.block, ofs, srv_sort_buf_size); - if (!success) { fprintf(stderr, "InnoDB: unable to read temporary file" " for table %s\n", index->table_name); @@ -3436,8 +3435,8 @@ all_done: goto func_exit; } - success = os_file_read_no_error_handling( - OS_FILE_FROM_FD(index->online_log->fd), + success = os_file_read_no_error_handling_int_fd( + index->online_log->fd, index->online_log->head.block, ofs, srv_sort_buf_size); diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index 5139adf4746..691b6b1e8de 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -876,8 +876,9 @@ row_merge_read( } #endif /* UNIV_DEBUG */ - success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, + success = os_file_read_no_error_handling_int_fd(fd, buf, ofs, srv_sort_buf_size); + #ifdef POSIX_FADV_DONTNEED /* Each block is read exactly once. Free up the file cache. */ posix_fadvise(fd, ofs, srv_sort_buf_size, POSIX_FADV_DONTNEED); @@ -911,7 +912,7 @@ row_merge_write( DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE);); - ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, ofs, buf_len); + ret = os_file_write_int_fd("(merge)", fd, buf, ofs, buf_len); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -3134,14 +3135,21 @@ row_merge_file_create_low( performance schema */ struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; - register_pfs_file_open_begin(&state, locker, innodb_file_temp_key, - PSI_FILE_OPEN, - "Innodb Merge Temp File", - __FILE__, __LINE__); + locker = PSI_FILE_CALL(get_thread_file_name_locker)( + &state, innodb_file_temp_key, PSI_FILE_OPEN, + "Innodb Merge Temp File", &locker); + if (locker != NULL) { + PSI_FILE_CALL(start_file_open_wait)(locker, + __FILE__, + __LINE__); + } #endif fd = innobase_mysql_tmpfile(path); #ifdef UNIV_PFS_IO - register_pfs_file_open_end(locker, fd); + if (locker != NULL) { + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)( + locker, fd); + } #endif if (fd < 0) { @@ -3188,15 +3196,20 @@ row_merge_file_destroy_low( #ifdef UNIV_PFS_IO struct PSI_file_locker* locker = NULL; PSI_file_locker_state state; - register_pfs_file_io_begin(&state, locker, - fd, 0, PSI_FILE_CLOSE, - __FILE__, __LINE__); + locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &state, fd, PSI_FILE_CLOSE); + if (locker != NULL) { + PSI_FILE_CALL(start_file_wait)( + locker, 0, __FILE__, __LINE__); + } #endif if (fd >= 0) { close(fd); } #ifdef UNIV_PFS_IO - register_pfs_file_io_end(locker, 0); + if (locker != NULL) { + PSI_FILE_CALL(end_file_wait)(locker, 0); + } #endif } /*********************************************************************//** diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index d2821abdc2e..9f66d12283a 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -62,6 +62,9 @@ Created 12/19/1997 Heikki Tuuri #include "my_sys.h" /* DEBUG_SYNC_C */ #include "my_compare.h" /* enum icp_result */ +#include "thr_lock.h" +#include "handler.h" +#include "ha_innodb.h" /* Maximum number of rows to prefetch; MySQL interface has another parameter */ #define SEL_MAX_N_PREFETCH 16 @@ -2733,7 +2736,8 @@ row_sel_field_store_in_mysql_format_func( || !(templ->mysql_col_len % templ->mbmaxlen)); ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len || (field_no == templ->icp_rec_field_no - && field->prefix_len > 0)); + && field->prefix_len > 0) + || templ->rec_field_is_prefix); ut_ad(!(field->prefix_len % templ->mbmaxlen)); if (templ->mbminlen == 1 && templ->mbmaxlen != 1) { @@ -2768,34 +2772,43 @@ row_sel_field_store_in_mysql_format_func( #ifdef UNIV_DEBUG /** Convert a field from Innobase format to MySQL format. */ -# define row_sel_store_mysql_field(m,p,r,i,o,f,t) \ - row_sel_store_mysql_field_func(m,p,r,i,o,f,t) +# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \ + row_sel_store_mysql_field_func(m,p,r,i,o,f,t,c) #else /* UNIV_DEBUG */ /** Convert a field from Innobase format to MySQL format. */ -# define row_sel_store_mysql_field(m,p,r,i,o,f,t) \ - row_sel_store_mysql_field_func(m,p,r,o,f,t) +# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \ + row_sel_store_mysql_field_func(m,p,r,o,f,t,c) #endif /* UNIV_DEBUG */ -/**************************************************************//** -Convert a field in the Innobase format to a field in the MySQL format. */ +/** Convert a field in the Innobase format to a field in the MySQL format. +@param[out] mysql_rec record in the MySQL format +@param[in,out] prebuilt prebuilt struct +@param[in] rec InnoDB record; must be protected + by a page latch +@param[in] index index of rec +@param[in] offsets array returned by rec_get_offsets() +@param[in] field_no templ->rec_field_no or + templ->clust_rec_field_no + or templ->icp_rec_field_no + or sec field no if clust_templ_for_sec + is TRUE +@param[in] templ row template +@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index + but prebuilt template is in clustered + index format and used only for end + range comparison. */ static MY_ATTRIBUTE((warn_unused_result)) ibool row_sel_store_mysql_field_func( -/*===========================*/ - byte* mysql_rec, /*!< out: record in the - MySQL format */ - row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */ - const rec_t* rec, /*!< in: InnoDB record; - must be protected by - a page latch */ + byte* mysql_rec, + row_prebuilt_t* prebuilt, + const rec_t* rec, #ifdef UNIV_DEBUG - const dict_index_t* index, /*!< in: index of rec */ + const dict_index_t* index, #endif - const ulint* offsets, /*!< in: array returned by - rec_get_offsets() */ - ulint field_no, /*!< in: templ->rec_field_no or - templ->clust_rec_field_no or - templ->icp_rec_field_no */ - const mysql_row_templ_t*templ) /*!< in: row template */ + const ulint* offsets, + ulint field_no, + const mysql_row_templ_t*templ, + bool clust_templ_for_sec) { const byte* data; ulint len; @@ -2804,10 +2817,12 @@ row_sel_store_mysql_field_func( ut_ad(templ); ut_ad(templ >= prebuilt->mysql_template); ut_ad(templ < &prebuilt->mysql_template[prebuilt->n_template]); - ut_ad(field_no == templ->clust_rec_field_no + ut_ad(clust_templ_for_sec + || field_no == templ->clust_rec_field_no || field_no == templ->rec_field_no || field_no == templ->icp_rec_field_no); - ut_ad(rec_offs_validate(rec, index, offsets)); + ut_ad(rec_offs_validate(rec, + clust_templ_for_sec == true ? prebuilt->index : index, offsets)); if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) { @@ -2924,30 +2939,37 @@ row_sel_store_mysql_field_func( return(TRUE); } -/**************************************************************//** -Convert a row in the Innobase format to a row in the MySQL format. +/** Convert a row in the Innobase format to a row in the MySQL format. Note that the template in prebuilt may advise us to copy only a few columns to mysql_rec, other columns are left blank. All columns may not be needed in the query. +@param[out] mysql_rec row in the MySQL format +@param[in] prebuilt prebuilt structure +@param[in] rec Innobase record in the index + which was described in prebuilt's + template, or in the clustered index; + must be protected by a page latch +@param[in] rec_clust TRUE if the rec in the clustered index +@param[in] index index of rec +@param[in] offsets array returned by rec_get_offsets(rec) +@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index + but the prebuilt->template is in + clustered index format and it is + used only for end range comparison @return TRUE on success, FALSE if not all columns could be retrieved */ static MY_ATTRIBUTE((warn_unused_result)) ibool row_sel_store_mysql_rec( -/*====================*/ - byte* mysql_rec, /*!< out: row in the MySQL format */ - row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ - const rec_t* rec, /*!< in: Innobase record in the index - which was described in prebuilt's - template, or in the clustered index; - must be protected by a page latch */ - ibool rec_clust, /*!< in: TRUE if rec is in the - clustered index instead of - prebuilt->index */ - const dict_index_t* index, /*!< in: index of rec */ - const ulint* offsets) /*!< in: array returned by - rec_get_offsets(rec) */ + byte* mysql_rec, + row_prebuilt_t* prebuilt, + const rec_t* rec, + ibool rec_clust, + const dict_index_t* index, + const ulint* offsets, + bool clust_templ_for_sec) { - ulint i; + ulint i; + std::vector template_col; ut_ad(rec_clust || index == prebuilt->index); ut_ad(!rec_clust || dict_index_is_clust(index)); @@ -2960,20 +2982,48 @@ row_sel_store_mysql_rec( if (UNIV_LIKELY_NULL(prebuilt->compress_heap)) mem_heap_empty(prebuilt->compress_heap); + if (clust_templ_for_sec) { + /* Store all clustered index field of + secondary index record. */ + for (i = 0; i < dict_index_get_n_fields( + prebuilt->index); i++) { + ulint sec_field = dict_index_get_nth_field_pos( + index, prebuilt->index, i); + template_col.push_back(sec_field); + } + } + for (i = 0; i < prebuilt->n_template; i++) { const mysql_row_templ_t*templ = &prebuilt->mysql_template[i]; - const ulint field_no + ulint field_no = rec_clust ? templ->clust_rec_field_no : templ->rec_field_no; /* We should never deliver column prefixes to MySQL, - except for evaluating innobase_index_cond(). */ + except for evaluating innobase_index_cond() and if the prefix + index is longer than the actual row data. */ + ut_ad(dict_index_get_nth_field(index, field_no)->prefix_len - == 0); + == 0 || templ->rec_field_is_prefix); + + if (clust_templ_for_sec) { + std::vector::iterator it; + it = std::find(template_col.begin(), + template_col.end(), field_no); + + if (it == template_col.end()) { + continue; + } + + ut_ad(templ->rec_field_no == templ->clust_rec_field_no); + + field_no = it - template_col.begin(); + } if (!row_sel_store_mysql_field(mysql_rec, prebuilt, rec, index, offsets, - field_no, templ)) { + field_no, templ, + clust_templ_for_sec)) { return(FALSE); } } @@ -3063,6 +3113,8 @@ row_sel_get_clust_rec_for_mysql( dberr_t err; trx_t* trx; + os_atomic_increment_ulint(&srv_sec_rec_cluster_reads, 1); + *out_rec = NULL; trx = thr_get_trx(thr); @@ -3613,7 +3665,7 @@ row_search_idx_cond_check( if (!row_sel_store_mysql_field(mysql_rec, prebuilt, rec, prebuilt->index, offsets, templ->icp_rec_field_no, - templ)) { + templ, false)) { return(ICP_NO_MATCH); } } @@ -3634,7 +3686,7 @@ row_search_idx_cond_check( || dict_index_is_clust(prebuilt->index)) { if (!row_sel_store_mysql_rec( mysql_rec, prebuilt, rec, FALSE, - prebuilt->index, offsets)) { + prebuilt->index, offsets, false)) { ut_ad(dict_index_is_clust(prebuilt->index)); return(ICP_NO_MATCH); } @@ -3653,6 +3705,50 @@ row_search_idx_cond_check( return(result); } +/** Check the pushed down end range condition to avoid extra traversal +if records are not within view and also to avoid prefetching in the +cache buffer. +@param[in] mysql_rec record in MySQL format +@param[in,out] handler the MySQL handler performing the scan +@retval true if the row in mysql_rec is out of range +@retval false if the row in mysql_rec is in range */ +static +bool +row_search_end_range_check( + const byte* mysql_rec, + ha_innobase* handler) +{ + if (handler->end_range && + handler->compare_key_in_buffer(mysql_rec) > 0) { + return(true); + } + + return(false); +} + +/** Return the record field length in characters. +@param[in] col table column of the field +@param[in] field_no field number +@param[in] rec physical record +@param[in] offsets field offsets in the physical record + +@return field length in characters */ +static +size_t +rec_field_len_in_chars(const dict_col_t &col, + const ulint field_no, + const rec_t *rec, + const ulint *offsets) +{ + const ulint cset = dtype_get_charset_coll(col.prtype); + const CHARSET_INFO* cs = all_charsets[cset]; + ulint rec_field_len; + const char* rec_field = reinterpret_cast( + rec_get_nth_field( + rec, offsets, field_no, &rec_field_len)); + return(cs->cset->numchars(cs, rec_field, rec_field + rec_field_len)); +} + /********************************************************************//** Searches for rows in the database. This is used in the interface to MySQL. This function opens a cursor, and also implements fetch next @@ -3690,7 +3786,9 @@ row_search_for_mysql( trx_t* trx = prebuilt->trx; dict_index_t* clust_index; que_thr_t* thr; - const rec_t* rec; + const rec_t* prev_rec = NULL; + const rec_t* rec = NULL; + byte* end_range_cache = NULL; const rec_t* result_rec = NULL; const rec_t* clust_rec; dberr_t err = DB_SUCCESS; @@ -3715,6 +3813,8 @@ row_search_for_mysql( ulint* offsets = offsets_; ibool table_lock_waited = FALSE; byte* next_buf = 0; + ulint end_loop = 0; + bool use_clustered_index = false; rec_offs_init(offsets_); @@ -3838,6 +3938,10 @@ row_search_for_mysql( err = DB_SUCCESS; goto func_exit; + } else if (prebuilt->end_range == true) { + prebuilt->end_range = false; + err = DB_RECORD_NOT_FOUND; + goto func_exit; } if (prebuilt->fetch_cache_first > 0 @@ -3970,7 +4074,8 @@ row_search_for_mysql( if (!row_sel_store_mysql_rec( buf, prebuilt, - rec, FALSE, index, offsets)) { + rec, FALSE, index, + offsets, false)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such @@ -4224,11 +4329,62 @@ rec_loop: and neither can a record lock be placed on it: we skip such a record. */ + prev_rec = NULL; goto next_rec; } if (page_rec_is_supremum(rec)) { + /** Compare the last record of the page with end range + passed to InnoDB when there is no ICP and number of loops + in row_search_for_mysql for rows found but not + reporting due to search views etc. */ + if (prev_rec != NULL + && prebuilt->mysql_handler->end_range != NULL + && prebuilt->idx_cond == NULL + && end_loop >= 100) { + + dict_index_t* key_index = prebuilt->index; + bool clust_templ_for_sec = false; + + if (end_range_cache == NULL) { + end_range_cache = static_cast( + ut_malloc(prebuilt->mysql_row_len)); + } + + if (index != clust_index + && prebuilt->need_to_access_clustered) { + /** Secondary index record but the template + based on PK. */ + key_index = clust_index; + clust_templ_for_sec = true; + } + + /** Create offsets based on prebuilt index. */ + offsets = rec_get_offsets(prev_rec, prebuilt->index, + offsets, ULINT_UNDEFINED, &heap); + + if (row_sel_store_mysql_rec( + end_range_cache, prebuilt, prev_rec, + clust_templ_for_sec, key_index, offsets, + clust_templ_for_sec)) { + + if (row_search_end_range_check( + end_range_cache, + prebuilt->mysql_handler)) { + + /** In case of prebuilt->fetch, + set the error in prebuilt->end_range. */ + if (prebuilt->n_fetch_cached > 0) { + prebuilt->end_range = true; + } + + err = DB_RECORD_NOT_FOUND; + goto normal_return; + } + } + } + if (set_also_gap_locks && !(srv_locks_unsafe_for_binlog || trx->isolation_level <= TRX_ISO_READ_COMMITTED) @@ -4260,6 +4416,7 @@ rec_loop: /* A page supremum record cannot be in the result set: skip it now that we have placed a possible lock on it */ + prev_rec = NULL; goto next_rec; } @@ -4334,6 +4491,7 @@ wrong_offs: btr_pcur_move_to_last_on_page(pcur, &mtr); + prev_rec = NULL; goto next_rec; } } @@ -4362,10 +4520,13 @@ wrong_offs: fputs(". We try to skip the record.\n", stderr); + prev_rec = NULL; goto next_rec; } } + prev_rec = rec; + /* Note that we cannot trust the up_match value in the cursor at this place because we can arrive here after moving the cursor! Thus we have to recompare rec and search_tuple to determine if they @@ -4590,6 +4751,7 @@ no_gap_lock: did_semi_consistent_read = TRUE; rec = old_vers; + prev_rec = rec; break; default: @@ -4636,6 +4798,7 @@ no_gap_lock: } rec = old_vers; + prev_rec = rec; } } else { /* We are looking into a non-clustered index, @@ -4729,10 +4892,97 @@ locks_ok: } /* Get the clustered index record if needed, if we did not do the - search using the clustered index. */ + search using the clustered index... */ - if (index != clust_index && prebuilt->need_to_access_clustered) { + use_clustered_index = + (index != clust_index && prebuilt->need_to_access_clustered); + if (use_clustered_index && prebuilt->n_template <= index->n_fields) { + /* ...but, perhaps avoid the clustered index lookup if + all of the following are true: + 1) all columns are in the secondary index + 2) all values for columns that are prefix-only + indexes are shorter than the prefix size + This optimization can avoid many IOs for certain schemas. + */ + bool row_contains_all_values = true; + unsigned int i; + for (i = 0; i < prebuilt->n_template; i++) { + /* Condition (1) from above: is the field in the + index (prefix or not)? */ + const mysql_row_templ_t* templ = + prebuilt->mysql_template + i; + ulint secondary_index_field_no = + templ->rec_prefix_field_no; + if (secondary_index_field_no == ULINT_UNDEFINED) { + row_contains_all_values = false; + break; + } + /* Condition (2) from above: if this is a + prefix, is this row's value size shorter + than the prefix? */ + if (templ->rec_field_is_prefix) { + ulint record_size = rec_offs_nth_size( + offsets, + secondary_index_field_no); + const dict_field_t *field = + dict_index_get_nth_field( + index, + secondary_index_field_no); + ut_a(field->prefix_len > 0); + if (record_size + < field->prefix_len / templ->mbmaxlen) { + + /* Record in bytes shorter than the + index prefix length in characters */ + continue; + + } else if (record_size * templ->mbminlen + >= field->prefix_len) { + + /* The shortest represantable string by + the byte length of the record is longer + than the maximum possible index + prefix. */ + row_contains_all_values = false; + break; + } else { + + /* The record could or could not fit + into the index prefix, calculate length + to find out */ + + if (rec_field_len_in_chars( + *field->col, + secondary_index_field_no, + rec, offsets) + >= (field->prefix_len + / templ->mbmaxlen)) { + + row_contains_all_values = false; + break; + } + } + } + } + /* If (1) and (2) were true for all columns above, use + rec_prefix_field_no instead of rec_field_no, and skip + the clustered lookup below. */ + if (row_contains_all_values) { + for (i = 0; i < prebuilt->n_template; i++) { + mysql_row_templ_t* templ = + prebuilt->mysql_template + i; + templ->rec_field_no = + templ->rec_prefix_field_no; + ut_a(templ->rec_field_no != ULINT_UNDEFINED); + } + use_clustered_index = false; + os_atomic_increment_ulint( + &srv_sec_rec_cluster_reads_avoided, 1); + } + } + + if (use_clustered_index) { requires_clust_rec: ut_ad(index != clust_index); /* We use a 'goto' to the preceding label if a consistent @@ -4813,7 +5063,7 @@ requires_clust_rec: appropriate version of the clustered index record. */ if (!row_sel_store_mysql_rec( buf, prebuilt, result_rec, - TRUE, clust_index, offsets)) { + TRUE, clust_index, offsets, false)) { goto next_rec; } } @@ -4881,7 +5131,7 @@ requires_clust_rec: next_buf, prebuilt, result_rec, result_rec != rec, result_rec != rec ? clust_index : index, - offsets)) { + offsets, false)) { if (next_buf == buf) { ut_a(prebuilt->n_fetch_cached == 0); @@ -4936,7 +5186,7 @@ requires_clust_rec: buf, prebuilt, result_rec, result_rec != rec, result_rec != rec ? clust_index : index, - offsets)) { + offsets, false)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such records do @@ -4988,6 +5238,8 @@ idx_cond_failed: goto normal_return; next_rec: + end_loop++; + /* Reset the old and new "did semi-consistent read" flags. */ if (UNIV_UNLIKELY(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT)) { @@ -5174,6 +5426,11 @@ normal_return: func_exit: trx->op_info = ""; + + if (end_range_cache != NULL) { + ut_free(end_range_cache); + } + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 24c5a9bd5d9..2153440886c 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -155,7 +155,8 @@ UNIV_INTERN unsigned long long srv_online_max_size; OS (provided we compiled Innobase with it in), otherwise we will use simulated aio we build below with threads. Currently we support native aio on windows and linux */ -UNIV_INTERN my_bool srv_use_native_aio = TRUE; +/* make srv_use_native_aio to be visible for other plugins */ +my_bool srv_use_native_aio = TRUE; UNIV_INTERN my_bool srv_numa_interleave = FALSE; #ifdef __WIN__ @@ -574,6 +575,12 @@ static ulint srv_main_shutdown_loops = 0; /** Log writes involving flush. */ static ulint srv_log_writes_and_flush = 0; +/** Number of times secondary index lookup triggered cluster lookup */ +ulint srv_sec_rec_cluster_reads = 0; + +/** Number of times prefix optimization avoided triggering cluster lookup */ +ulint srv_sec_rec_cluster_reads_avoided = 0; + /* This is only ever touched by the master thread. It records the time when the last flush of log file has happened. The master thread ensures that we flush the log files at least once per @@ -1895,6 +1902,12 @@ srv_export_innodb_status(void) } #endif /* UNIV_DEBUG */ + os_rmb; + export_vars.innodb_sec_rec_cluster_reads = + srv_sec_rec_cluster_reads; + export_vars.innodb_sec_rec_cluster_reads_avoided = + srv_sec_rec_cluster_reads_avoided; + mutex_exit(&srv_innodb_monitor_mutex); } @@ -2956,6 +2969,8 @@ DECLARE_THREAD(srv_master_thread)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); + srv_slot_t* slot; ulint old_activity_count = srv_get_activity_count(); ulint old_ibuf_merge_activity_count @@ -3029,6 +3044,7 @@ suspend_thread: os_event_wait(slot->event); if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + my_thread_end(); os_thread_exit(NULL); } @@ -3115,6 +3131,8 @@ DECLARE_THREAD(srv_worker_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); + srv_slot_t* slot; ulint tid_i = os_atomic_increment_ulint(&purge_tid_i, 1); @@ -3181,6 +3199,7 @@ DECLARE_THREAD(srv_worker_thread)( os_thread_pf(os_thread_get_curr_id())); #endif /* UNIV_DEBUG_THREAD_CREATION */ + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); @@ -3383,6 +3402,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); + srv_slot_t* slot; ulint n_total_purged = ULINT_UNDEFINED; @@ -3495,6 +3516,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( srv_release_threads(SRV_WORKER, srv_n_purge_threads - 1); } + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); @@ -3563,3 +3585,18 @@ srv_purge_wakeup(void) } } +/** Check whether given space id is undo tablespace id +@param[in] space_id space id to check +@return true if it is undo tablespace else false. */ +bool +srv_is_undo_tablespace( + ulint space_id) +{ + if (srv_undo_space_id_start == 0) { + return (false); + } + + return(space_id >= srv_undo_space_id_start + && space_id < (srv_undo_space_id_start + + srv_undo_tablespaces_open)); +} diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index c53faba88ba..ac634df06dd 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. @@ -110,6 +110,9 @@ UNIV_INTERN ibool srv_have_fullfsync = FALSE; /** TRUE if a raw partition is in use */ UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE; +/** UNDO tablespaces starts with space id. */ +ulint srv_undo_space_id_start; + /** TRUE if the server is being started, before rolling back any incomplete transactions */ UNIV_INTERN ibool srv_startup_is_before_trx_rollback_phase = FALSE; @@ -125,7 +128,7 @@ SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */ UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE; /** Files comprising the system tablespace */ -static os_file_t files[1000]; +static pfs_os_file_t files[1000]; /** io_handler_thread parameters for thread identification */ static ulint n[SRV_MAX_N_IO_THREADS]; @@ -553,7 +556,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t create_log_file( /*============*/ - os_file_t* file, /*!< out: file handle */ + pfs_os_file_t* file, /*!< out: file handle */ const char* name) /*!< in: log file name */ { ibool ret; @@ -770,7 +773,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t open_log_file( /*==========*/ - os_file_t* file, /*!< out: file handle */ + pfs_os_file_t* file, /*!< out: file handle */ const char* name, /*!< in: log file name */ os_offset_t* size) /*!< out: file size */ { @@ -886,7 +889,7 @@ open_or_create_data_files( && os_file_get_last_error(false) != OS_FILE_ALREADY_EXISTS #ifdef UNIV_AIX - /* AIX 5.1 after security patch ML7 may have + /* AIX 5.1 after security patch ML7 may have errno set to 0 here, which causes our function to return 100; work around that AIX problem */ @@ -1183,7 +1186,7 @@ srv_undo_tablespace_create( const char* name, /*!< in: tablespace name */ ulint size) /*!< in: tablespace size in pages */ { - os_file_t fh; + pfs_os_file_t fh; ibool ret; dberr_t err = DB_SUCCESS; @@ -1260,7 +1263,7 @@ srv_undo_tablespace_open( const char* name, /*!< in: tablespace name */ ulint space) /*!< in: tablespace id */ { - os_file_t fh; + pfs_os_file_t fh; dberr_t err = DB_ERROR; ibool ret; ulint flags; @@ -1359,13 +1362,23 @@ srv_undo_tablespaces_init( for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) { char name[OS_FILE_MAX_PATH]; + ulint space_id = i + 1; + + DBUG_EXECUTE_IF("innodb_undo_upgrade", + space_id = i + 3;); ut_snprintf( name, sizeof(name), "%s%cundo%03lu", - srv_undo_dir, SRV_PATH_SEPARATOR, i + 1); + srv_undo_dir, SRV_PATH_SEPARATOR, space_id); + + if (i == 0) { + srv_undo_space_id_start = space_id; + prev_space_id = srv_undo_space_id_start - 1; + } + + undo_tablespace_ids[i] = space_id; - /* Undo space ids start from 1. */ err = srv_undo_tablespace_create( name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES); @@ -1387,14 +1400,16 @@ srv_undo_tablespaces_init( if (!create_new_db) { n_undo_tablespaces = trx_rseg_get_n_undo_tablespaces( undo_tablespace_ids); + + if (n_undo_tablespaces != 0) { + srv_undo_space_id_start = undo_tablespace_ids[0]; + prev_space_id = srv_undo_space_id_start - 1; + } + } else { n_undo_tablespaces = n_conf_tablespaces; - for (i = 1; i <= n_undo_tablespaces; ++i) { - undo_tablespace_ids[i - 1] = i; - } - - undo_tablespace_ids[i] = ULINT_UNDEFINED; + undo_tablespace_ids[n_conf_tablespaces] = ULINT_UNDEFINED; } /* Open all the undo tablespaces that are currently in use. If we @@ -1418,8 +1433,6 @@ srv_undo_tablespaces_init( ut_a(undo_tablespace_ids[i] != 0); ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED); - /* Undo space ids start from 1. */ - err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); if (err != DB_SUCCESS) { @@ -1454,11 +1467,23 @@ srv_undo_tablespaces_init( break; } + /** Note the first undo tablespace id in case of + no active undo tablespace. */ + if (n_undo_tablespaces == 0) { + srv_undo_space_id_start = i; + } + ++n_undo_tablespaces; ++*n_opened; } + /** Explictly specify the srv_undo_space_id_start + as zero when there are no undo tablespaces. */ + if (n_undo_tablespaces == 0) { + srv_undo_space_id_start = 0; + } + /* If the user says that there are fewer than what we find we tolerate that discrepancy but not the inverse. Because there could be unused undo tablespaces for future use. */ @@ -1503,10 +1528,11 @@ srv_undo_tablespaces_init( mtr_start(&mtr); /* The undo log tablespace */ - for (i = 1; i <= n_undo_tablespaces; ++i) { + for (i = 0; i < n_undo_tablespaces; ++i) { fsp_header_init( - i, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr); + undo_tablespace_ids[i], + SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr); } mtr_commit(&mtr); @@ -1604,6 +1630,10 @@ innobase_start_or_create_for_mysql(void) char* logfile0 = NULL; size_t dirnamelen; + if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { + srv_read_only_mode = 1; + } + high_level_read_only = srv_read_only_mode || srv_force_recovery > SRV_FORCE_NO_TRX_UNDO; diff --git a/storage/xtradb/trx/trx0purge.cc b/storage/xtradb/trx/trx0purge.cc index d9e40c5d6f5..d0d7ef2432e 100644 --- a/storage/xtradb/trx/trx0purge.cc +++ b/storage/xtradb/trx/trx0purge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -696,7 +696,8 @@ trx_purge_get_rseg_with_min_trx_id( /* We assume in purge of externally stored fields that space id is in the range of UNDO tablespace space ids */ - ut_a(purge_sys->rseg->space <= srv_undo_tablespaces_open); + ut_a(purge_sys->rseg->space == 0 + || srv_is_undo_tablespace(purge_sys->rseg->space)); zip_size = purge_sys->rseg->zip_size; diff --git a/storage/xtradb/trx/trx0rec.cc b/storage/xtradb/trx/trx0rec.cc index 868a8a6c0b6..200ce015a7d 100644 --- a/storage/xtradb/trx/trx0rec.cc +++ b/storage/xtradb/trx/trx0rec.cc @@ -781,7 +781,8 @@ trx_undo_page_report_modify( } pos = dict_index_get_nth_col_pos(index, - col_no); + col_no, + NULL); ptr += mach_write_compressed(ptr, pos); /* Save the old value of field */ diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc index e1e253cbb76..09e8e018c4f 100644 --- a/storage/xtradb/trx/trx0roll.cc +++ b/storage/xtradb/trx/trx0roll.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -800,6 +800,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)( /*!< in: a dummy parameter required by os_thread_create */ { + my_thread_init(); ut_ad(!srv_read_only_mode); #ifdef UNIV_PFS_THREAD @@ -810,6 +811,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)( trx_rollback_or_clean_is_active = false; + my_thread_end(); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc index ccec5a7c113..4e8c50784bb 100644 --- a/storage/xtradb/trx/trx0sys.cc +++ b/storage/xtradb/trx/trx0sys.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, 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 @@ -918,18 +918,12 @@ trx_sys_create_rsegs( ulint new_rsegs = n_rsegs - n_used; for (i = 0; i < new_rsegs; ++i) { - ulint space; + ulint space_id; + space_id = (n_spaces == 0) ? 0 + : (srv_undo_space_id_start + i % n_spaces); - /* Tablespace 0 is the system tablespace. All UNDO - log tablespaces start from 1. */ - - if (n_spaces > 0) { - space = (i % n_spaces) + 1; - } else { - space = 0; /* System tablespace */ - } - - if (trx_rseg_create(space) != NULL) { + /* Tablespace 0 is the system tablespace. */ + if (trx_rseg_create(space_id) != NULL) { ++n_used; } else { break; From 97c53cdfcc01a4f47d2757f5ca0b040f0e5a30e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 May 2017 14:26:11 +0300 Subject: [PATCH 115/148] 5.6.36-82.0 --- storage/tokudb/CMakeLists.txt | 5 +- .../tokudb/PerconaFT/buildheader/make_tdb.cc | 3 + storage/tokudb/PerconaFT/ft/ft-ops.cc | 387 ++++++++++++------ storage/tokudb/PerconaFT/src/ydb.cc | 162 +++++++- storage/tokudb/ha_tokudb.cc | 28 +- .../mysql-test/tokudb/r/bug-1657908.result | 70 ++++ .../tokudb/mysql-test/tokudb/r/dir_cmd.result | 58 +++ .../mysql-test/tokudb/t/bug-1657908.test | 72 ++++ .../tokudb/mysql-test/tokudb/t/dir_cmd.test | 51 +++ .../tokudb_backup/r/backup_master_info.result | 26 ++ .../r/backup_master_state.result | 36 ++ .../r/empty_slave_info_file.result | 1 + .../r/innodb_use_native_aio_enabled.result | 5 + .../tokudb_backup/r/rpl_safe_slave.result | 77 ++++ .../r/rpl_tokudb_commit_sync.result | 59 +++ .../tokudb_backup/t/backup_master_info.test | 94 +++++ .../tokudb_backup/t/backup_master_state.test | 87 ++++ .../t/empty_slave_info_file.test | 23 ++ .../innodb_use_native_aio_enabled-master.opt | 1 + .../t/innodb_use_native_aio_enabled.test | 19 + .../tokudb_backup/t/rpl_safe_slave-master.opt | 1 + .../tokudb_backup/t/rpl_safe_slave-slave.opt | 1 + .../tokudb_backup/t/rpl_safe_slave.cnf | 14 + .../tokudb_backup/t/rpl_safe_slave.inc | 112 +++++ .../tokudb_backup/t/rpl_safe_slave.test | 49 +++ .../t/rpl_tokudb_commit_sync-slave.opt | 1 + .../t/rpl_tokudb_commit_sync.test | 72 ++++ .../mysql-test/tokudb_backup/t/suite.opt | 2 +- .../mysql-test/tokudb_bugs/r/db233.result | 10 - .../tokudb_bugs/r/simple_icp.result | 4 +- .../mysql-test/tokudb_bugs/t/db233.test | 18 - .../mysql-test/tokudb_bugs/t/leak172.test | 4 +- storage/tokudb/tokudb_dir_cmd.cc | 331 +++++++++++++++ storage/tokudb/tokudb_dir_cmd.h | 46 +++ storage/tokudb/tokudb_sysvars.cc | 72 +++- 35 files changed, 1814 insertions(+), 187 deletions(-) create mode 100644 storage/tokudb/mysql-test/tokudb/r/bug-1657908.result create mode 100644 storage/tokudb/mysql-test/tokudb/r/dir_cmd.result create mode 100644 storage/tokudb/mysql-test/tokudb/t/bug-1657908.test create mode 100644 storage/tokudb/mysql-test/tokudb/t/dir_cmd.test create mode 100644 storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result create mode 100644 storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result create mode 100644 storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result create mode 100644 storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result create mode 100644 storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result create mode 100644 storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt create mode 100644 storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test create mode 100644 storage/tokudb/tokudb_dir_cmd.cc create mode 100644 storage/tokudb/tokudb_dir_cmd.h diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index 311df22ca5f..2438b7ac3fe 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(TOKUDB_VERSION 5.6.35-80.0) +SET(TOKUDB_VERSION 5.6.36-82.0) # PerconaFT only supports x86-64 and cmake-2.8.9+ IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT CMAKE_VERSION VERSION_LESS "2.8.9") @@ -111,7 +111,8 @@ SET(TOKUDB_SOURCES tokudb_background.cc tokudb_information_schema.cc tokudb_sysvars.cc - tokudb_thread.cc) + tokudb_thread.cc + tokudb_dir_cmd.cc) MYSQL_ADD_PLUGIN(tokudb ${TOKUDB_SOURCES} STORAGE_ENGINE MODULE_ONLY LINK_LIBRARIES tokufractaltree_static tokuportability_static ${ZLIB_LIBRARY} stdc++) SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} -flto -fuse-linker-plugin") diff --git a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc index 7ede78b3c0d..d0404b420f4 100644 --- a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc +++ b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc @@ -425,6 +425,9 @@ static void print_db_env_struct (void) { "bool (*set_dir_per_db)(DB_ENV *, bool new_val)", "bool (*get_dir_per_db)(DB_ENV *)", "const char *(*get_data_dir)(DB_ENV *env)", + "int (*dirtool_attach)(DB_ENV *, DB_TXN *, const char *, const char *)", + "int (*dirtool_detach)(DB_ENV *, DB_TXN *, const char *)", + "int (*dirtool_move)(DB_ENV *, DB_TXN *, const char *, const char *)", NULL}; sort_and_dump_fields("db_env", true, extra); diff --git a/storage/tokudb/PerconaFT/ft/ft-ops.cc b/storage/tokudb/PerconaFT/ft/ft-ops.cc index ad9ecb1d074..63c6335dafd 100644 --- a/storage/tokudb/PerconaFT/ft/ft-ops.cc +++ b/storage/tokudb/PerconaFT/ft/ft-ops.cc @@ -3900,25 +3900,34 @@ struct keyrange_compare_s { }; // TODO: Remove me, I'm boring -static int keyrange_compare(DBT const &kdbt, const struct keyrange_compare_s &s) { +static int keyrange_compare(DBT const &kdbt, + const struct keyrange_compare_s &s) { return s.ft->cmp(&kdbt, s.key); } -static void -keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node, - DBT* key_left, DBT* key_right, - int left_child_number, int right_child_number, uint64_t estimated_num_rows, - uint64_t *less, uint64_t* equal_left, uint64_t* middle, - uint64_t* equal_right, uint64_t* greater, bool* single_basement_node) +static void keysrange_in_leaf_partition(FT_HANDLE ft_handle, + FTNODE node, + DBT *key_left, + DBT *key_right, + int left_child_number, + int right_child_number, + uint64_t estimated_num_rows, + uint64_t *less, + uint64_t *equal_left, + uint64_t *middle, + uint64_t *equal_right, + uint64_t *greater, + bool *single_basement_node) // If the partition is in main memory then estimate the number // Treat key_left == NULL as negative infinity // Treat key_right == NULL as positive infinity { - paranoid_invariant(node->height == 0); // we are in a leaf + paranoid_invariant(node->height == 0); // we are in a leaf paranoid_invariant(!(key_left == NULL && key_right != NULL)); paranoid_invariant(left_child_number <= right_child_number); bool single_basement = left_child_number == right_child_number; - paranoid_invariant(!single_basement || (BP_STATE(node, left_child_number) == PT_AVAIL)); + paranoid_invariant(!single_basement || + (BP_STATE(node, left_child_number) == PT_AVAIL)); if (BP_STATE(node, left_child_number) == PT_AVAIL) { int r; // The partition is in main memory then get an exact count. @@ -3926,29 +3935,35 @@ keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node, BASEMENTNODE bn = BLB(node, left_child_number); uint32_t idx_left = 0; // if key_left is NULL then set r==-1 and idx==0. - r = key_left ? bn->data_buffer.find_zero(s_left, nullptr, nullptr, nullptr, &idx_left) : -1; + r = key_left + ? bn->data_buffer.find_zero( + s_left, nullptr, nullptr, nullptr, &idx_left) + : -1; *less = idx_left; - *equal_left = (r==0) ? 1 : 0; + *equal_left = (r == 0) ? 1 : 0; uint32_t size = bn->data_buffer.num_klpairs(); uint32_t idx_right = size; r = -1; if (single_basement && key_right) { struct keyrange_compare_s s_right = {ft_handle->ft, key_right}; - r = bn->data_buffer.find_zero(s_right, nullptr, nullptr, nullptr, &idx_right); + r = bn->data_buffer.find_zero( + s_right, nullptr, nullptr, nullptr, &idx_right); } *middle = idx_right - idx_left - *equal_left; - *equal_right = (r==0) ? 1 : 0; + *equal_right = (r == 0) ? 1 : 0; *greater = size - idx_right - *equal_right; } else { paranoid_invariant(!single_basement); uint32_t idx_left = estimated_num_rows / 2; if (!key_left) { - //Both nullptr, assume key_left belongs before leftmost entry, key_right belongs after rightmost entry + // Both nullptr, assume key_left belongs before leftmost entry, + // key_right belongs after rightmost entry idx_left = 0; paranoid_invariant(!key_right); } - // Assume idx_left and idx_right point to where key_left and key_right belong, (but are not there). + // Assume idx_left and idx_right point to where key_left and key_right + // belong, (but are not there). *less = idx_left; *equal_left = 0; *middle = estimated_num_rows - idx_left; @@ -3958,44 +3973,76 @@ keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node, *single_basement_node = single_basement; } -static int -toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node, - DBT* key_left, DBT* key_right, bool may_find_right, - uint64_t* less, uint64_t* equal_left, uint64_t* middle, - uint64_t* equal_right, uint64_t* greater, bool* single_basement_node, - uint64_t estimated_num_rows, - ftnode_fetch_extra *min_bfe, // set up to read a minimal read. - ftnode_fetch_extra *match_bfe, // set up to read a basement node iff both keys in it - struct unlockers *unlockers, ANCESTORS ancestors, const pivot_bounds &bounds) -// Implementation note: Assign values to less, equal, and greater, and then on the way out (returning up the stack) we add more values in. +static int toku_ft_keysrange_internal( + FT_HANDLE ft_handle, + FTNODE node, + DBT *key_left, + DBT *key_right, + bool may_find_right, + uint64_t *less, + uint64_t *equal_left, + uint64_t *middle, + uint64_t *equal_right, + uint64_t *greater, + bool *single_basement_node, + uint64_t estimated_num_rows, + ftnode_fetch_extra *min_bfe, // set up to read a minimal read. + ftnode_fetch_extra + *match_bfe, // set up to read a basement node iff both keys in it + struct unlockers *unlockers, + ANCESTORS ancestors, + const pivot_bounds &bounds) +// Implementation note: Assign values to less, equal, and greater, and then on +// the way out (returning up the stack) we add more values in. { int r = 0; // if KEY is NULL then use the leftmost key. - int left_child_number = key_left ? toku_ftnode_which_child (node, key_left, ft_handle->ft->cmp) : 0; - int right_child_number = node->n_children; // Sentinel that does not equal left_child_number. + int left_child_number = + key_left ? toku_ftnode_which_child(node, key_left, ft_handle->ft->cmp) + : 0; + int right_child_number = + node->n_children; // Sentinel that does not equal left_child_number. if (may_find_right) { - right_child_number = key_right ? toku_ftnode_which_child (node, key_right, ft_handle->ft->cmp) : node->n_children - 1; + right_child_number = + key_right + ? toku_ftnode_which_child(node, key_right, ft_handle->ft->cmp) + : node->n_children - 1; } uint64_t rows_per_child = estimated_num_rows / node->n_children; if (node->height == 0) { - keysrange_in_leaf_partition(ft_handle, node, key_left, key_right, left_child_number, right_child_number, - rows_per_child, less, equal_left, middle, equal_right, greater, single_basement_node); + keysrange_in_leaf_partition(ft_handle, + node, + key_left, + key_right, + left_child_number, + right_child_number, + rows_per_child, + less, + equal_left, + middle, + equal_right, + greater, + single_basement_node); - *less += rows_per_child * left_child_number; + *less += rows_per_child * left_child_number; if (*single_basement_node) { - *greater += rows_per_child * (node->n_children - left_child_number - 1); + *greater += + rows_per_child * (node->n_children - left_child_number - 1); } else { - *middle += rows_per_child * (node->n_children - left_child_number - 1); + *middle += + rows_per_child * (node->n_children - left_child_number - 1); } } else { // do the child. struct ancestors next_ancestors = {node, left_child_number, ancestors}; BLOCKNUM childblocknum = BP_BLOCKNUM(node, left_child_number); - uint32_t fullhash = compute_child_fullhash(ft_handle->ft->cf, node, left_child_number); + uint32_t fullhash = + compute_child_fullhash(ft_handle->ft->cf, node, left_child_number); FTNODE childnode; bool msgs_applied = false; - bool child_may_find_right = may_find_right && left_child_number == right_child_number; + bool child_may_find_right = + may_find_right && left_child_number == right_child_number; r = toku_pin_ftnode_for_query( ft_handle, childblocknum, @@ -4006,27 +4053,45 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node, child_may_find_right ? match_bfe : min_bfe, false, &childnode, - &msgs_applied - ); + &msgs_applied); paranoid_invariant(!msgs_applied); if (r != TOKUDB_TRY_AGAIN) { assert_zero(r); - struct unlock_ftnode_extra unlock_extra = {ft_handle,childnode,false}; - struct unlockers next_unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, unlockers}; - const pivot_bounds next_bounds = bounds.next_bounds(node, left_child_number); + struct unlock_ftnode_extra unlock_extra = { + ft_handle, childnode, false}; + struct unlockers next_unlockers = { + true, unlock_ftnode_fun, (void *)&unlock_extra, unlockers}; + const pivot_bounds next_bounds = + bounds.next_bounds(node, left_child_number); - r = toku_ft_keysrange_internal(ft_handle, childnode, key_left, key_right, child_may_find_right, - less, equal_left, middle, equal_right, greater, single_basement_node, - rows_per_child, min_bfe, match_bfe, &next_unlockers, &next_ancestors, next_bounds); + r = toku_ft_keysrange_internal(ft_handle, + childnode, + key_left, + key_right, + child_may_find_right, + less, + equal_left, + middle, + equal_right, + greater, + single_basement_node, + rows_per_child, + min_bfe, + match_bfe, + &next_unlockers, + &next_ancestors, + next_bounds); if (r != TOKUDB_TRY_AGAIN) { assert_zero(r); - *less += rows_per_child * left_child_number; + *less += rows_per_child * left_child_number; if (*single_basement_node) { - *greater += rows_per_child * (node->n_children - left_child_number - 1); + *greater += rows_per_child * + (node->n_children - left_child_number - 1); } else { - *middle += rows_per_child * (node->n_children - left_child_number - 1); + *middle += rows_per_child * + (node->n_children - left_child_number - 1); } assert(unlockers->locked); @@ -4037,10 +4102,21 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node, return r; } -void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint64_t *less_p, uint64_t* equal_left_p, uint64_t* middle_p, uint64_t* equal_right_p, uint64_t* greater_p, bool* middle_3_exact_p) -// Effect: Return an estimate of the number of keys to the left, the number equal (to left key), number between keys, number equal to right key, and the number to the right of both keys. +void toku_ft_keysrange(FT_HANDLE ft_handle, + DBT *key_left, + DBT *key_right, + uint64_t *less_p, + uint64_t *equal_left_p, + uint64_t *middle_p, + uint64_t *equal_right_p, + uint64_t *greater_p, + bool *middle_3_exact_p) +// Effect: Return an estimate of the number of keys to the left, the number +// equal (to left key), number between keys, number equal to right key, and the +// number to the right of both keys. // The values are an estimate. -// If you perform a keyrange on two keys that are in the same basement, equal_less, middle, and equal_right will be exact. +// If you perform a keyrange on two keys that are in the same basement, +// equal_less, middle, and equal_right will be exact. // 4184: What to do with a NULL key? // key_left==NULL is treated as -infinity // key_right==NULL is treated as +infinity @@ -4048,10 +4124,21 @@ void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint6 // key_right can be non-null only if key_left is non-null; { if (!key_left && key_right) { - // Simplify internals by only supporting key_right != null when key_left != null - // If key_right != null and key_left == null, then swap them and fix up numbers. - uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0; - toku_ft_keysrange(ft_handle, key_right, nullptr, &less, &equal_left, &middle, &equal_right, &greater, middle_3_exact_p); + // Simplify internals by only supporting key_right != null when key_left + // != null + // If key_right != null and key_left == null, then swap them and fix up + // numbers. + uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, + greater = 0; + toku_ft_keysrange(ft_handle, + key_right, + nullptr, + &less, + &equal_left, + &middle, + &equal_right, + &greater, + middle_3_exact_p); *less_p = 0; *equal_left_p = 0; *middle_p = less; @@ -4064,98 +4151,132 @@ void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint6 paranoid_invariant(!(!key_left && key_right)); ftnode_fetch_extra min_bfe; ftnode_fetch_extra match_bfe; - min_bfe.create_for_min_read(ft_handle->ft); // read pivot keys but not message buffers - match_bfe.create_for_keymatch(ft_handle->ft, key_left, key_right, false, false); // read basement node only if both keys in it. -try_again: + min_bfe.create_for_min_read( + ft_handle->ft); // read pivot keys but not message buffers + match_bfe.create_for_keymatch( + ft_handle->ft, + key_left, + key_right, + false, + false); // read basement node only if both keys in it. +try_again : { + uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0; + bool single_basement_node = false; + FTNODE node = NULL; { - uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0; - bool single_basement_node = false; - FTNODE node = NULL; - { - uint32_t fullhash; - CACHEKEY root_key; - toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash); - toku_pin_ftnode( - ft_handle->ft, - root_key, - fullhash, - &match_bfe, - PL_READ, // may_modify_node, cannot change root during keyrange - &node, - true - ); + uint32_t fullhash; + CACHEKEY root_key; + toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash); + toku_pin_ftnode( + ft_handle->ft, + root_key, + fullhash, + &match_bfe, + PL_READ, // may_modify_node, cannot change root during keyrange + &node, + true); + } + + struct unlock_ftnode_extra unlock_extra = {ft_handle, node, false}; + struct unlockers unlockers = { + true, unlock_ftnode_fun, (void *)&unlock_extra, (UNLOCKERS)NULL}; + + { + int r; + int64_t numrows = ft_handle->ft->in_memory_logical_rows; + if (numrows < 0) + numrows = 0; // prevent appearance of a negative number + r = toku_ft_keysrange_internal(ft_handle, + node, + key_left, + key_right, + true, + &less, + &equal_left, + &middle, + &equal_right, + &greater, + &single_basement_node, + numrows, + &min_bfe, + &match_bfe, + &unlockers, + (ANCESTORS)NULL, + pivot_bounds::infinite_bounds()); + assert(r == 0 || r == TOKUDB_TRY_AGAIN); + if (r == TOKUDB_TRY_AGAIN) { + assert(!unlockers.locked); + goto try_again; } - - struct unlock_ftnode_extra unlock_extra = {ft_handle,node,false}; - struct unlockers unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, (UNLOCKERS)NULL}; - - { - int r; - int64_t numrows = ft_handle->ft->in_memory_stats.numrows; - if (numrows < 0) - numrows = 0; // prevent appearance of a negative number - r = toku_ft_keysrange_internal (ft_handle, node, key_left, key_right, true, - &less, &equal_left, &middle, &equal_right, &greater, - &single_basement_node, numrows, - &min_bfe, &match_bfe, &unlockers, (ANCESTORS)NULL, pivot_bounds::infinite_bounds()); + // May need to do a second query. + if (!single_basement_node && key_right != nullptr) { + // "greater" is stored in "middle" + invariant_zero(equal_right); + invariant_zero(greater); + uint64_t less2 = 0, equal_left2 = 0, middle2 = 0, equal_right2 = 0, + greater2 = 0; + bool ignore; + r = toku_ft_keysrange_internal(ft_handle, + node, + key_right, + nullptr, + false, + &less2, + &equal_left2, + &middle2, + &equal_right2, + &greater2, + &ignore, + numrows, + &min_bfe, + &match_bfe, + &unlockers, + (ANCESTORS) nullptr, + pivot_bounds::infinite_bounds()); assert(r == 0 || r == TOKUDB_TRY_AGAIN); if (r == TOKUDB_TRY_AGAIN) { assert(!unlockers.locked); goto try_again; } - // May need to do a second query. - if (!single_basement_node && key_right != nullptr) { - // "greater" is stored in "middle" - invariant_zero(equal_right); - invariant_zero(greater); - uint64_t less2 = 0, equal_left2 = 0, middle2 = 0, equal_right2 = 0, greater2 = 0; - bool ignore; - r = toku_ft_keysrange_internal (ft_handle, node, key_right, nullptr, false, - &less2, &equal_left2, &middle2, &equal_right2, &greater2, - &ignore, numrows, - &min_bfe, &match_bfe, &unlockers, (ANCESTORS)nullptr, pivot_bounds::infinite_bounds()); - assert(r == 0 || r == TOKUDB_TRY_AGAIN); - if (r == TOKUDB_TRY_AGAIN) { - assert(!unlockers.locked); - goto try_again; - } - invariant_zero(equal_right2); - invariant_zero(greater2); - // Update numbers. - // less is already correct. - // equal_left is already correct. + invariant_zero(equal_right2); + invariant_zero(greater2); + // Update numbers. + // less is already correct. + // equal_left is already correct. - // "middle" currently holds everything greater than left_key in first query - // 'middle2' currently holds everything greater than right_key in second query - // 'equal_left2' is how many match right_key + // "middle" currently holds everything greater than left_key in + // first query + // 'middle2' currently holds everything greater than right_key in + // second query + // 'equal_left2' is how many match right_key - // Prevent underflow. - if (middle >= equal_left2 + middle2) { - middle -= equal_left2 + middle2; - } else { - middle = 0; - } - equal_right = equal_left2; - greater = middle2; + // Prevent underflow. + if (middle >= equal_left2 + middle2) { + middle -= equal_left2 + middle2; + } else { + middle = 0; } + equal_right = equal_left2; + greater = middle2; } - assert(unlockers.locked); - toku_unpin_ftnode_read_only(ft_handle->ft, node); - if (!key_right) { - paranoid_invariant_zero(equal_right); - paranoid_invariant_zero(greater); - } - if (!key_left) { - paranoid_invariant_zero(less); - paranoid_invariant_zero(equal_left); - } - *less_p = less; - *equal_left_p = equal_left; - *middle_p = middle; - *equal_right_p = equal_right; - *greater_p = greater; - *middle_3_exact_p = single_basement_node; } + assert(unlockers.locked); + toku_unpin_ftnode_read_only(ft_handle->ft, node); + if (!key_right) { + paranoid_invariant_zero(equal_right); + paranoid_invariant_zero(greater); + } + if (!key_left) { + paranoid_invariant_zero(less); + paranoid_invariant_zero(equal_left); + } + *less_p = less; + *equal_left_p = equal_left; + *middle_p = middle; + *equal_right_p = equal_right; + *greater_p = greater; + *middle_3_exact_p = single_basement_node; +} } struct get_key_after_bytes_iterate_extra { diff --git a/storage/tokudb/PerconaFT/src/ydb.cc b/storage/tokudb/PerconaFT/src/ydb.cc index 3341f6d76c6..6dd8564e6a1 100644 --- a/storage/tokudb/PerconaFT/src/ydb.cc +++ b/storage/tokudb/PerconaFT/src/ydb.cc @@ -70,6 +70,8 @@ const char *toku_copyright_string = "Copyright (c) 2006, 2015, Percona and/or it #include "util/status.h" #include "util/context.h" +#include + // Include ydb_lib.cc here so that its constructor/destructor gets put into // ydb.o, to make sure they don't get erased at link time (when linking to // a static libtokufractaltree.a that was compiled with gcc). See #5094. @@ -1314,6 +1316,159 @@ static const char *env_get_data_dir(DB_ENV *env) { return env->i->real_data_dir; } +static int env_dirtool_attach(DB_ENV *env, + DB_TXN *txn, + const char *dname, + const char *iname) { + int r; + DBT dname_dbt; + DBT iname_dbt; + + HANDLE_PANICKED_ENV(env); + if (!env_opened(env)) { + return EINVAL; + } + HANDLE_READ_ONLY_TXN(txn); + toku_fill_dbt(&dname_dbt, dname, strlen(dname) + 1); + toku_fill_dbt(&iname_dbt, iname, strlen(iname) + 1); + + r = toku_db_put(env->i->directory, + txn, + &dname_dbt, + &iname_dbt, + 0, + true); + return r; +} + +static int env_dirtool_detach(DB_ENV *env, + DB_TXN *txn, + const char *dname) { + int r; + DBT dname_dbt; + DBT old_iname_dbt; + + HANDLE_PANICKED_ENV(env); + if (!env_opened(env)) { + return EINVAL; + } + HANDLE_READ_ONLY_TXN(txn); + + toku_fill_dbt(&dname_dbt, dname, strlen(dname) + 1); + toku_init_dbt_flags(&old_iname_dbt, DB_DBT_REALLOC); + + r = toku_db_get(env->i->directory, + txn, + &dname_dbt, + &old_iname_dbt, + DB_SERIALIZABLE); // allocates memory for iname + if (r == DB_NOTFOUND) + return EEXIST; + toku_free(old_iname_dbt.data); + + r = toku_db_del(env->i->directory, txn, &dname_dbt, DB_DELETE_ANY, true); + + return r; +} + +static int env_dirtool_move(DB_ENV *env, + DB_TXN *txn, + const char *old_dname, + const char *new_dname) { + int r; + DBT old_dname_dbt; + DBT new_dname_dbt; + DBT iname_dbt; + + HANDLE_PANICKED_ENV(env); + if (!env_opened(env)) { + return EINVAL; + } + HANDLE_READ_ONLY_TXN(txn); + + toku_fill_dbt(&old_dname_dbt, old_dname, strlen(old_dname) + 1); + toku_fill_dbt(&new_dname_dbt, new_dname, strlen(new_dname) + 1); + toku_init_dbt_flags(&iname_dbt, DB_DBT_REALLOC); + + r = toku_db_get(env->i->directory, + txn, + &old_dname_dbt, + &iname_dbt, + DB_SERIALIZABLE); // allocates memory for iname + if (r == DB_NOTFOUND) + return EEXIST; + + r = toku_db_del( + env->i->directory, txn, &old_dname_dbt, DB_DELETE_ANY, true); + if (r != 0) + goto exit; + + r = toku_db_put( + env->i->directory, txn, &new_dname_dbt, &iname_dbt, 0, true); + +exit: + toku_free(iname_dbt.data); + return r; +} + +static int locked_env_op(DB_ENV *env, + DB_TXN *txn, + std::function f) { + int ret, r; + HANDLE_READ_ONLY_TXN(txn); + HANDLE_ILLEGAL_WORKING_PARENT_TXN(env, txn); + + DB_TXN *child_txn = NULL; + int using_txns = env->i->open_flags & DB_INIT_TXN; + if (using_txns) { + ret = toku_txn_begin(env, txn, &child_txn, 0); + lazy_assert_zero(ret); + } + + // cannot begin a checkpoint + toku_multi_operation_client_lock(); + r = f(child_txn); + toku_multi_operation_client_unlock(); + + if (using_txns) { + if (r == 0) { + ret = locked_txn_commit(child_txn, 0); + lazy_assert_zero(ret); + } else { + ret = locked_txn_abort(child_txn); + lazy_assert_zero(ret); + } + } + return r; + +} + +static int locked_env_dirtool_attach(DB_ENV *env, + DB_TXN *txn, + const char *dname, + const char *iname) { + auto f = std::bind( + env_dirtool_attach, env, std::placeholders::_1, dname, iname); + return locked_env_op(env, txn, f); +} + +static int locked_env_dirtool_detach(DB_ENV *env, + DB_TXN *txn, + const char *dname) { + auto f = std::bind( + env_dirtool_detach, env, std::placeholders::_1, dname); + return locked_env_op(env, txn, f); +} + +static int locked_env_dirtool_move(DB_ENV *env, + DB_TXN *txn, + const char *old_dname, + const char *new_dname) { + auto f = std::bind( + env_dirtool_move, env, std::placeholders::_1, old_dname, new_dname); + return locked_env_op(env, txn, f); +} + static int env_dbremove(DB_ENV * env, DB_TXN *txn, const char *fname, const char *dbname, uint32_t flags); static int @@ -2646,6 +2801,9 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) { #define SENV(name) result->name = locked_env_ ## name SENV(dbremove); SENV(dbrename); + SENV(dirtool_attach); + SENV(dirtool_detach); + SENV(dirtool_move); //SENV(set_noticecall); #undef SENV #define USENV(name) result->name = env_ ## name @@ -2975,8 +3133,10 @@ env_dbremove(DB_ENV * env, DB_TXN *txn, const char *fname, const char *dbname, u if (txn && r) { if (r == EMFILE || r == ENFILE) r = toku_ydb_do_error(env, r, "toku dbremove failed because open file limit reached\n"); - else + else if (r != ENOENT) r = toku_ydb_do_error(env, r, "toku dbremove failed\n"); + else + r = 0; goto exit; } if (txn) { diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 14d278a47d6..15276f2fb85 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -5254,17 +5254,17 @@ int ha_tokudb::fill_range_query_buf( DEBUG_SYNC(ha_thd(), "tokudb_icp_asc_scan_out_of_range"); goto cleanup; } else if (result == ICP_NO_MATCH) { - // if we are performing a DESC ICP scan and have no end_range - // to compare to stop using ICP filtering as there isn't much more - // that we can do without going through contortions with remembering - // and comparing key parts. + // Optimizer change for MyRocks also benefits us here in TokuDB as + // opt_range.cc QUICK_SELECT::get_next now sets end_range during + // descending scan. We should not ever hit this condition, but + // leaving this code in to prevent any possibility of a descending + // scan to the beginning of an index and catch any possibility + // in debug builds with an assertion + assert_debug(!(!end_range && direction < 0)); if (!end_range && direction < 0) { - cancel_pushed_idx_cond(); - DEBUG_SYNC(ha_thd(), "tokudb_icp_desc_scan_invalidate"); } - error = TOKUDB_CURSOR_CONTINUE; goto cleanup; } @@ -6122,7 +6122,6 @@ int ha_tokudb::info(uint flag) { stats.records = share->row_count() + share->rows_from_locked_table; stats.deleted = 0; if (!(flag & HA_STATUS_NO_LOCK)) { - uint64_t num_rows = 0; error = txn_begin(db_env, NULL, &txn, DB_READ_UNCOMMITTED, ha_thd()); if (error) { @@ -6132,20 +6131,13 @@ int ha_tokudb::info(uint flag) { // we should always have a primary key assert_always(share->file != NULL); - error = estimate_num_rows(share->file, &num_rows, txn); - if (error == 0) { - share->set_row_count(num_rows, false); - stats.records = num_rows; - } else { - goto cleanup; - } - DB_BTREE_STAT64 dict_stats; error = share->file->stat64(share->file, txn, &dict_stats); if (error) { goto cleanup; } - + share->set_row_count(dict_stats.bt_ndata, false); + stats.records = dict_stats.bt_ndata; stats.create_time = dict_stats.bt_create_time_sec; stats.update_time = dict_stats.bt_modify_time_sec; stats.check_time = dict_stats.bt_verify_time_sec; @@ -7841,7 +7833,7 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* // As a result, equal may be 0 and greater may actually be equal+greater // So, we call key_range64 on the key, and the key that is after it. if (!start_key && !end_key) { - error = estimate_num_rows(kfile, &rows, transaction); + error = estimate_num_rows(share->file, &rows, transaction); if (error) { ret_val = HA_TOKUDB_RANGE_COUNT; goto cleanup; diff --git a/storage/tokudb/mysql-test/tokudb/r/bug-1657908.result b/storage/tokudb/mysql-test/tokudb/r/bug-1657908.result new file mode 100644 index 00000000000..1d86478d833 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/bug-1657908.result @@ -0,0 +1,70 @@ +SET GLOBAL tokudb_dir_per_db=ON; +CREATE PROCEDURE create_table() +BEGIN +CREATE TABLE test.t1 ( +a INT +) ENGINE = TokuDB +PARTITION BY RANGE (a) +(PARTITION p100 VALUES LESS THAN (100) ENGINE = TokuDB, +PARTITION p_to_del VALUES LESS THAN (200) ENGINE = TokuDB, +PARTITION p300 VALUES LESS THAN (300) ENGINE = TokuDB, +PARTITION p400 VALUES LESS THAN (400) ENGINE = TokuDB +); +END| +### Create partitioned table +CALL create_table(); +## Looking for *.tokudb files in data_dir +## Looking for *.tokudb files in data_dir/test +t1_P_p100_main_id.tokudb +t1_P_p100_status_id.tokudb +t1_P_p300_main_id.tokudb +t1_P_p300_status_id.tokudb +t1_P_p400_main_id.tokudb +t1_P_p400_status_id.tokudb +t1_P_p_to_del_main_id.tokudb +t1_P_p_to_del_status_id.tokudb +### Stop server +### Remove 'main' file of one of the partitions +### Start server +### Make sure 'main' partition file is deleted +## Looking for *.tokudb files in data_dir +## Looking for *.tokudb files in data_dir/test +t1_P_p100_main_id.tokudb +t1_P_p100_status_id.tokudb +t1_P_p300_main_id.tokudb +t1_P_p300_status_id.tokudb +t1_P_p400_main_id.tokudb +t1_P_p400_status_id.tokudb +t1_P_p_to_del_status_id.tokudb +### Make sure the table still exists +SHOW TABLES; +Tables_in_test +t1 +### Drop table +DROP TABLE t1; +### Make sure the table is dropped +SHOW TABLES; +Tables_in_test +### Check what files still exist after DROP TABLE +## Looking for *.tokudb files in data_dir +## Looking for *.tokudb files in data_dir/test +### Remove the rest of the files +### Make sure there are no tokudb files +## Looking for *.tokudb files in data_dir +## Looking for *.tokudb files in data_dir/test +### Create the same table once more +CALL create_table(); +## Looking for *.tokudb files in data_dir +## Looking for *.tokudb files in data_dir/test +t1_P_p100_main_id.tokudb +t1_P_p100_status_id.tokudb +t1_P_p300_main_id.tokudb +t1_P_p300_status_id.tokudb +t1_P_p400_main_id.tokudb +t1_P_p400_status_id.tokudb +t1_P_p_to_del_main_id.tokudb +t1_P_p_to_del_status_id.tokudb +### Restore state +DROP TABLE t1; +DROP PROCEDURE create_table; +SET GLOBAL tokudb_dir_per_db=default; diff --git a/storage/tokudb/mysql-test/tokudb/r/dir_cmd.result b/storage/tokudb/mysql-test/tokudb/r/dir_cmd.result new file mode 100644 index 00000000000..dd3b693db49 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/dir_cmd.result @@ -0,0 +1,58 @@ +SET GLOBAL tokudb_dir_per_db = ON; +SET tokudb_dir_cmd = "attach test_dname_1 test_iname_1"; +SET tokudb_dir_cmd = "attach test_dname_2 test_iname_2"; +SELECT dictionary_name, internal_file_name +FROM information_schema.TokuDB_file_map; +dictionary_name internal_file_name +test_dname_1 test_iname_1 +test_dname_2 test_iname_2 +SET tokudb_dir_cmd = "detach test_dname_1"; +SELECT dictionary_name, internal_file_name +FROM information_schema.TokuDB_file_map; +dictionary_name internal_file_name +test_dname_2 test_iname_2 +SET tokudb_dir_cmd = "move test_dname_2 test_dname_3"; +SELECT dictionary_name, internal_file_name +FROM information_schema.TokuDB_file_map; +dictionary_name internal_file_name +test_dname_3 test_iname_2 +SET tokudb_dir_cmd = "detach test_dname_3"; +SELECT dictionary_name, internal_file_name +FROM information_schema.TokuDB_file_map; +dictionary_name internal_file_name +CREATE TABLE t1(a int) ENGINE=tokudb; +INSERT INTO t1 (a) VALUES (10); +SELECT dictionary_name, internal_file_name +FROM information_schema.TokuDB_file_map; +dictionary_name internal_file_name +./test/t1-main ./test/t1_main_id.tokudb +./test/t1-status ./test/t1_status_id.tokudb +SET tokudb_dir_cmd = "attach ./test/t1-main test/t1-main-renamed.tokudb"; +SELECT dictionary_name, internal_file_name +FROM information_schema.TokuDB_file_map; +dictionary_name internal_file_name +./test/t1-main test/t1-main-renamed.tokudb +./test/t1-status ./test/t1_status_id.tokudb +### rename t1_main_id.tokudb to t1-main-renamed.tokudb +SELECT * FROM t1; +a +10 +### Test for errors notification +SET tokudb_dir_cmd = "detach foo"; +ERROR 42000: Variable 'tokudb_dir_cmd' can't be set to the value of 'detach foo' +SELECT @@tokudb_dir_cmd_last_error; +@@tokudb_dir_cmd_last_error +17 +SELECT @@tokudb_dir_cmd_last_error_string; +@@tokudb_dir_cmd_last_error_string +detach command error +SET @@tokudb_dir_cmd_last_error_string = "blablabla"; +SELECT @@tokudb_dir_cmd_last_error_string; +@@tokudb_dir_cmd_last_error_string +blablabla +SET STATEMENT tokudb_dir_cmd_last_error_string = "statement_blablabla" FOR +SELECT @@tokudb_dir_cmd_last_error_string; +@@tokudb_dir_cmd_last_error_string +statement_blablabla +DROP TABLE t1; +SET GLOBAL tokudb_dir_per_db = default; diff --git a/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test b/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test new file mode 100644 index 00000000000..3c7b602b96d --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test @@ -0,0 +1,72 @@ +# See https://bugs.launchpad.net/percona-server/+bug/1657908 + +source include/have_tokudb.inc; + +SET GLOBAL tokudb_dir_per_db=ON; + +--let $DB= test +--let $DATADIR= `SELECT @@datadir` + +--delimiter | +CREATE PROCEDURE create_table() +BEGIN +CREATE TABLE test.t1 ( + a INT +) ENGINE = TokuDB +PARTITION BY RANGE (a) +(PARTITION p100 VALUES LESS THAN (100) ENGINE = TokuDB, + PARTITION p_to_del VALUES LESS THAN (200) ENGINE = TokuDB, + PARTITION p300 VALUES LESS THAN (300) ENGINE = TokuDB, + PARTITION p400 VALUES LESS THAN (400) ENGINE = TokuDB +); +END| +--delimiter ; + +--echo ### Create partitioned table +CALL create_table(); +--source dir_per_db_show_table_files.inc + +--echo ### Stop server +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--echo ### Remove 'main' file of one of the partitions +--remove_files_wildcard $DATADIR/$DB t1_P_p_to_del_main_*.tokudb + +--echo ### Start server +--enable_reconnect +--exec echo "restart: --loose-tokudb-dir-per-db=ON" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--source include/wait_until_connected_again.inc + +--echo ### Make sure 'main' partition file is deleted +--source dir_per_db_show_table_files.inc + +--echo ### Make sure the table still exists +SHOW TABLES; + +--echo ### Drop table +# error 1051 was here before the fix +DROP TABLE t1; + +--echo ### Make sure the table is dropped +SHOW TABLES; + +--echo ### Check what files still exist after DROP TABLE +--source dir_per_db_show_table_files.inc + +--echo ### Remove the rest of the files +--remove_files_wildcard $DATADIR/$DB *.tokudb + +--echo ### Make sure there are no tokudb files +--source dir_per_db_show_table_files.inc + +--echo ### Create the same table once more +# engine error 17 (EEXIST) was here before the fix +CALL create_table(); +--source dir_per_db_show_table_files.inc + +--echo ### Restore state +DROP TABLE t1; +DROP PROCEDURE create_table; +SET GLOBAL tokudb_dir_per_db=default; diff --git a/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test b/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test new file mode 100644 index 00000000000..102e8217e2b --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test @@ -0,0 +1,51 @@ +source include/have_tokudb.inc; + +--let $MYSQL_DATADIR=`select @@datadir` + +SET GLOBAL tokudb_dir_per_db = ON; + +SET tokudb_dir_cmd = "attach test_dname_1 test_iname_1"; +SET tokudb_dir_cmd = "attach test_dname_2 test_iname_2"; +SELECT dictionary_name, internal_file_name + FROM information_schema.TokuDB_file_map; + +SET tokudb_dir_cmd = "detach test_dname_1"; +SELECT dictionary_name, internal_file_name + FROM information_schema.TokuDB_file_map; + +SET tokudb_dir_cmd = "move test_dname_2 test_dname_3"; +SELECT dictionary_name, internal_file_name + FROM information_schema.TokuDB_file_map; + +SET tokudb_dir_cmd = "detach test_dname_3"; +SELECT dictionary_name, internal_file_name + FROM information_schema.TokuDB_file_map; + +CREATE TABLE t1(a int) ENGINE=tokudb; +INSERT INTO t1 (a) VALUES (10); +--source include/table_files_replace_pattern.inc +SELECT dictionary_name, internal_file_name + FROM information_schema.TokuDB_file_map; + +SET tokudb_dir_cmd = "attach ./test/t1-main test/t1-main-renamed.tokudb"; +--source include/table_files_replace_pattern.inc +SELECT dictionary_name, internal_file_name + FROM information_schema.TokuDB_file_map; + +--echo ### rename t1_main_id.tokudb to t1-main-renamed.tokudb +--exec mv $MYSQL_DATADIR/test/t1_main_*.tokudb $MYSQL_DATADIR/test/t1-main-renamed.tokudb + +SELECT * FROM t1; + +--echo ### Test for errors notification +--error 1231 +SET tokudb_dir_cmd = "detach foo"; +SELECT @@tokudb_dir_cmd_last_error; +SELECT @@tokudb_dir_cmd_last_error_string; +SET @@tokudb_dir_cmd_last_error_string = "blablabla"; +SELECT @@tokudb_dir_cmd_last_error_string; +SET STATEMENT tokudb_dir_cmd_last_error_string = "statement_blablabla" FOR + SELECT @@tokudb_dir_cmd_last_error_string; + +DROP TABLE t1; +SET GLOBAL tokudb_dir_per_db = default; diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result new file mode 100644 index 00000000000..992a828e287 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result @@ -0,0 +1,26 @@ +### +# Test for binlog position +##### +include/master-slave.inc +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. +[connection master] +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; +Backup +include/filter_file.inc +### tokubackup_slave_info content: +host: #.#.#.#, user: ####, port: ####, master log file: ####, relay log file: ####, exec master log pos: ####, executed gtid set: , channel name: +### +# Test for gtid set +##### +include/rpl_set_gtid_mode.inc +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; +Backup +include/filter_file.inc +### tokubackup_slave_info content: +host: #.#.#.#, user: ####, port: ####, master log file: ####, relay log file: ####, exec master log pos: ####, executed gtid set: ####, channel name: +include/rpl_set_gtid_mode.inc +include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result new file mode 100644 index 00000000000..072dfff448b --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result @@ -0,0 +1,36 @@ +### Create backup dir +include/master-slave.inc +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. +[connection master] +### Check for settings +SELECT @@gtid_mode; +@@gtid_mode +OFF +### Generate some binlog events +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; +### Master backup +include/filter_file.inc +### tokubackup_binlog_info content: +filename: ####, position: ####, gtid_mode: OFF, GTID of last change: +### Delete backup dir +### Create backup dir +### GTID-mode on +include/rpl_set_gtid_mode.inc +### Check for settings +SELECT @@gtid_mode; +@@gtid_mode +ON +### Generate some binlog events +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; +### Master backup +include/filter_file.inc +### tokubackup_binlog_info content: +filename: ####, position: ####, gtid_mode: ON, GTID of last change: ##### +### Delete backup dir +### GTID-mode off +include/rpl_set_gtid_mode.inc +include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result b/storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result new file mode 100644 index 00000000000..a0af40d80cc --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result @@ -0,0 +1 @@ +Backup diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result b/storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result new file mode 100644 index 00000000000..94e113fc87d --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result @@ -0,0 +1,5 @@ +SELECT @@innodb_use_native_aio; +@@innodb_use_native_aio +1 +SET SESSION tokudb_backup_dir='MYSQL_TMP_DIR/tokudb_backup'; +ERROR 42000: Variable 'tokudb_backup_dir' can't be set to the value of 'MYSQL_TMP_DIR/tokudb_backup' diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result new file mode 100644 index 00000000000..13b5915354f --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result @@ -0,0 +1,77 @@ +### +# Master-slave test +#### +include/rpl_init.inc [topology=1->2] +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. +### Create temp table on master +CREATE TEMPORARY TABLE t1 (a INT); +include/sync_slave_sql_with_master.inc +### Setup debug_sync points and prepare for slave backup +SET SESSION debug="+d,debug_sync_abort_on_timeout"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 1 +SET DEBUG_SYNC= 'tokudb_backup_wait_for_safe_slave_entered SIGNAL sse WAIT_FOR sse_continue'; +SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_begin SIGNAL ttlb WAIT_FOR ttlb_continue'; +SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_slave_started SIGNAL ttlss WAIT_FOR ttlss_continue EXECUTE 2'; +SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_end SIGNAL ttle WAIT_FOR ttle_continue'; +### Turn-on safe-slave option +SET GLOBAL tokudb_backup_safe_slave=ON; +SET GLOBAL tokudb_backup_safe_slave_timeout=30; +### Start slave backup +SET SESSION debug="+d,debug_sync_abort_on_timeout"; +### Wait for safe slave function to start +SET DEBUG_SYNC = "now WAIT_FOR sse"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 1 +### Wait for safe slave loop start +SET DEBUG_SYNC = "now SIGNAL sse_continue WAIT_FOR ttlb"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 1 +### Wait for safe thread loop point just after slave sql thread start 1 +SET DEBUG_SYNC = "now SIGNAL ttlb_continue WAIT_FOR ttlss"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 1 +### Wait for safe thread loop end +SET DEBUG_SYNC = "now SIGNAL ttlss_continue WAIT_FOR ttle"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 1 +### Wait for safe thread loop point just after slave sql thread start 2 +SET DEBUG_SYNC = "now SIGNAL ttle_continue WAIT_FOR ttlss"; +### Drop temp table on master +DROP TABLE t1; +### and syncronize slave +include/sync_slave_sql_with_master.inc +SHOW STATUS LIKE 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 0 +### Continue backup +SET DEBUG_SYNC = "now SIGNAL ttlss_continue"; +## Reset debug_sync points +SET DEBUG_SYNC = "RESET"; +### Wait for backup finish +include/filter_file.inc +### Slave tokubackup_slave_info content: +host: #.#.#.#, user: ####, port: ####, master log file: ####, relay log file: ####, exec master log pos: ####, executed gtid set: , channel name: +### Delete slave backup dir +### Turn-off safe-slave option for slave +SET GLOBAL tokudb_backup_safe_slave=default; +SET GLOBAL tokudb_backup_safe_slave_timeout=default; +### Turn-on safe-slave option for master +SET GLOBAL tokudb_backup_safe_slave=ON; +SET GLOBAL tokudb_backup_safe_slave_timeout=30; +### Backup master +### Turn-off safe-slave option for master +SET GLOBAL tokudb_backup_safe_slave=default; +SET GLOBAL tokudb_backup_safe_slave_timeout=default; +include/filter_file.inc +### Master tokubackup_binlog_info content: +filename: ####, position: ####, gtid_mode: OFF, GTID of last change: +### Delete master backup dir +include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result new file mode 100644 index 00000000000..50508f073ab --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result @@ -0,0 +1,59 @@ +include/master-slave.inc +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. +[connection master] +### Create some data on master +CREATE TABLE t1(a INT, b INT, PRIMARY KEY (a)) ENGINE=TokuDB; +INSERT INTO t1 SET a=100, b=100; +INSERT INTO t1 SET a=200, b=100; +INSERT INTO t1 SET a=300, b=100; +INSERT INTO t1 SET a=400, b=100; +INSERT INTO t1 SET a=500, b=100; +UPDATE t1 SET b = 200 WHERE a = 200; +DELETE FROM t1 WHERE a = 100; +SELECT * FROM t1; +a b +200 200 +300 100 +400 100 +500 100 +### Check for slave options +SELECT @@tokudb_commit_sync; +@@tokudb_commit_sync +0 +SELECT @@tokudb_fsync_log_period; +@@tokudb_fsync_log_period +1000000 +### Check data on slave after sync +SELECT * FROM t1; +a b +200 200 +300 100 +400 100 +500 100 +### Do backup on slave +### Check for errors +SELECT @@session.tokudb_backup_last_error; +@@session.tokudb_backup_last_error +0 +SELECT @@session.tokudb_backup_last_error_string; +@@session.tokudb_backup_last_error_string +NULL +### Stop slave server +include/rpl_stop_server.inc [server_number=2] +### Restore backup +### Start slave server and slave threads +include/rpl_start_server.inc [server_number=2] +include/start_slave.inc +### Sync slave with master +### Check data on slave +SELECT * FROM t1; +a b +200 200 +300 100 +400 100 +500 100 +### Cleanup +DROP TABLE t1; +include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test new file mode 100644 index 00000000000..8e9f6df4b1d --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test @@ -0,0 +1,94 @@ +--source include/have_tokudb_backup.inc +--source include/not_gtid_enabled.inc + + +--let $SLAVE_INFO_FILE=tokubackup_slave_info +--let $BACKUP_DIR_SLAVE=$MYSQL_TMP_DIR/tokudb_backup_slave +--let $SLAVE_INFO_FILE_PATH=$BACKUP_DIR_SLAVE/$SLAVE_INFO_FILE +--let DDIR=$BACKUP_DIR_SLAVE + +# Settings for include/filter_file.inc + +--delimiter | +let $script= + s{host: [^,]+,}{host: #.#.#.#,}; + s{user: [^,]+,}{user: ####,}; + s{port: [^,]+,}{port: ####,}; + s{master log file: [^,]+,}{master log file: ####,}; + s{relay log file: [^,]+,}{relay log file: ####,}; + s{exec master log pos: [^,]+,}{exec master log pos: ####,}; + s{executed gtid set: [^,]+, }{executed gtid set: ####, }; + s{executed gtid set: [^,]+,[^,]+, }{executed gtid set: ####,####, }; +| +--delimiter ; +--let $input_file = $SLAVE_INFO_FILE_PATH +--let $skip_column_names= 1 + +--echo ### +--echo # Test for binlog position +--echo ##### + +--mkdir $BACKUP_DIR_SLAVE + +--source include/master-slave.inc + +--connection master +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; + +--sync_slave_with_master + +--connection slave +--echo Backup +--disable_query_log +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE' +--enable_query_log + +--source include/filter_file.inc +--echo ### $SLAVE_INFO_FILE content: +--cat_file $SLAVE_INFO_FILE_PATH + +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"DDIR"}; +rmtree([ "$DDIR" ]); +EOF + +--echo ### +--echo # Test for gtid set +--echo ##### + +--mkdir $BACKUP_DIR_SLAVE + +--let $rpl_server_numbers= 1,2 +--let $rpl_set_enforce_gtid_consistency= 1 +--source include/rpl_set_gtid_mode.inc + +--connection master +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; + +--sync_slave_with_master + +--connection slave +--echo Backup +--disable_query_log +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE' +--enable_query_log + +--source include/filter_file.inc +--echo ### $SLAVE_INFO_FILE content: +--cat_file $SLAVE_INFO_FILE_PATH + +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"DDIR"}; +rmtree([ "$DDIR" ]); +EOF + +--let $rpl_gtid_mode= OFF +--let $rpl_set_enforce_gtid_consistency= 0 +--let $rpl_server_numbers= 1,2 +--let $rpl_skip_sync= 1 +--source include/rpl_set_gtid_mode.inc +--source include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test new file mode 100644 index 00000000000..c301d55f8fa --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test @@ -0,0 +1,87 @@ +--source include/have_tokudb_backup.inc +--source include/not_gtid_enabled.inc + +--let $MASTER_STATE_FILE=tokubackup_binlog_info +--let $BACKUP_DIR_MASTER=$MYSQL_TMP_DIR/tokudb_backup_master +--let $MASTER_STATE_FILE_PATH=$BACKUP_DIR_MASTER/$MASTER_STATE_FILE +--let DDIR=$BACKUP_DIR_MASTER + +# Settings for include/filter_file.inc +--delimiter | +let $script= + s{filename: [^,]+,}{filename: ####,}; + s{position: [^,]+,}{position: ####,}; + s{GTID of last change: [^ ]+}{GTID of last change: #####}; +| +--delimiter ; +--let $input_file = $MASTER_STATE_FILE_PATH +--let $skip_column_names= 1 + +--echo ### Create backup dir +--mkdir $BACKUP_DIR_MASTER + +--source include/master-slave.inc + +--connection master + +--echo ### Check for settings +SELECT @@gtid_mode; + +--echo ### Generate some binlog events +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; + +--echo ### Master backup +--disable_query_log +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_MASTER' +--enable_query_log + +--source include/filter_file.inc +--echo ### $MASTER_STATE_FILE content: +--cat_file $MASTER_STATE_FILE_PATH + +--echo ### Delete backup dir +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"DDIR"}; +rmtree([ "$DDIR" ]); +EOF + +--echo ### Create backup dir +--mkdir $BACKUP_DIR_MASTER + +--echo ### GTID-mode on +--let $rpl_server_numbers= 1,2 +--let $rpl_set_enforce_gtid_consistency= 1 +--source include/rpl_set_gtid_mode.inc + +--echo ### Check for settings +SELECT @@gtid_mode; + +--echo ### Generate some binlog events +CREATE TABLE t1(a INT) ENGINE=TokuDB; +DROP TABLE t1; + +--echo ### Master backup +--disable_query_log +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_MASTER' +--enable_query_log + +--source include/filter_file.inc +--echo ### $MASTER_STATE_FILE content: +--cat_file $MASTER_STATE_FILE_PATH + +--echo ### Delete backup dir +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"DDIR"}; +rmtree([ "$DDIR" ]); +EOF + +--echo ### GTID-mode off +--let $rpl_gtid_mode= OFF +--let $rpl_set_enforce_gtid_consistency= 0 +--let $rpl_server_numbers= 1,2 +--source include/rpl_set_gtid_mode.inc + +--source include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test b/storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test new file mode 100644 index 00000000000..53592903a27 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test @@ -0,0 +1,23 @@ +--source include/have_tokudb_backup.inc +--source include/not_gtid_enabled.inc + + +--let $SLAVE_INFO_FILE=tokubackup_slave_info +--let $BACKUP_DIR_SLAVE=$MYSQL_TMP_DIR/tokudb_backup_slave +--let DDIR=$BACKUP_DIR_SLAVE + +--mkdir $BACKUP_DIR_SLAVE + +--echo Backup +--disable_query_log +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE' +--enable_query_log + +--list_files $BACKUP_DIR_SLAVE $SLAVE_INFO_FILE + +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"DDIR"}; +rmtree([ "$DDIR" ]); +EOF + diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt new file mode 100644 index 00000000000..5f5dbb9c7c6 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt @@ -0,0 +1 @@ +--innodb_use_native_aio=on diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test new file mode 100644 index 00000000000..3e09b465c02 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test @@ -0,0 +1,19 @@ +# Check if tokudb hot backup is prevented if innodb_use_native_aio enabled +--source include/have_tokudb_backup.inc +--source include/have_innodb.inc + +SELECT @@innodb_use_native_aio; + +--let BACKUP_DIR= $MYSQL_TMP_DIR/tokudb_backup + +--mkdir $BACKUP_DIR + +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--error ER_WRONG_VALUE_FOR_VAR +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR' + +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"BACKUP_DIR"}; +rmtree([ "$DDIR" ]); +EOF diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt new file mode 100644 index 00000000000..af3a211967b --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt @@ -0,0 +1 @@ +--binlog-format=statement diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt new file mode 100644 index 00000000000..49405b1aec3 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt @@ -0,0 +1 @@ +--master-info-repository=TABLE --relay-log-info-repository=TABLE diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf new file mode 100644 index 00000000000..321be4ab2fc --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf @@ -0,0 +1,14 @@ +!include ../../rpl/my.cnf + +[mysqld.1] + +[mysqld.2] + +[mysqld.3] +master-info-repository=TABLE +relay-log-info-repository=TABLE + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc new file mode 100644 index 00000000000..e0732ee63fc --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc @@ -0,0 +1,112 @@ +--connection server_1 +--echo ### Create temp table on master +CREATE TEMPORARY TABLE t1 (a INT); + +--let $sync_slave_connection= server_2 +--source include/sync_slave_sql_with_master.inc + +--echo ### Setup debug_sync points and prepare for slave backup +--connection slave_2 +SET SESSION debug="+d,debug_sync_abort_on_timeout"; + +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +SET DEBUG_SYNC= 'tokudb_backup_wait_for_safe_slave_entered SIGNAL sse WAIT_FOR sse_continue'; +SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_begin SIGNAL ttlb WAIT_FOR ttlb_continue'; +SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_slave_started SIGNAL ttlss WAIT_FOR ttlss_continue EXECUTE 2'; +SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_end SIGNAL ttle WAIT_FOR ttle_continue'; + +--mkdir $BACKUP_DIR_SLAVE + +--echo ### Turn-on safe-slave option +SET GLOBAL tokudb_backup_safe_slave=ON; +SET GLOBAL tokudb_backup_safe_slave_timeout=30; + +--echo ### Start slave backup +--disable_query_log +--send_eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE' +--enable_query_log + +--connection server_2 +SET SESSION debug="+d,debug_sync_abort_on_timeout"; + +--echo ### Wait for safe slave function to start +SET DEBUG_SYNC = "now WAIT_FOR sse"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +--echo ### Wait for safe slave loop start +SET DEBUG_SYNC = "now SIGNAL sse_continue WAIT_FOR ttlb"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +--echo ### Wait for safe thread loop point just after slave sql thread start 1 +SET DEBUG_SYNC = "now SIGNAL ttlb_continue WAIT_FOR ttlss"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; +--echo ### Wait for safe thread loop end +SET DEBUG_SYNC = "now SIGNAL ttlss_continue WAIT_FOR ttle"; +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +--echo ### Wait for safe thread loop point just after slave sql thread start 2 +SET DEBUG_SYNC = "now SIGNAL ttle_continue WAIT_FOR ttlss"; + +--connection server_1 +--echo ### Drop temp table on master +DROP TABLE t1; + +--echo ### and syncronize slave +--let $sync_slave_connection= server_2 +--source include/sync_slave_sql_with_master.inc + +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +--echo ### Continue backup +SET DEBUG_SYNC = "now SIGNAL ttlss_continue"; + +--echo ## Reset debug_sync points +SET DEBUG_SYNC = "RESET"; + +--connection slave_2 +--echo ### Wait for backup finish +--reap + +--let $input_file = $S_SLAVE_INFO_FILE_PATH +--source include/filter_file.inc +--echo ### Slave $SLAVE_INFO_FILE content: +--cat_file $S_SLAVE_INFO_FILE_PATH + +--echo ### Delete slave backup dir +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"BACKUP_DIR_SLAVE"}; +rmtree([ "$DDIR" ]); +EOF + +--echo ### Turn-off safe-slave option for slave +SET GLOBAL tokudb_backup_safe_slave=default; +SET GLOBAL tokudb_backup_safe_slave_timeout=default; + +--connection server_1 + +--echo ### Turn-on safe-slave option for master +SET GLOBAL tokudb_backup_safe_slave=ON; +SET GLOBAL tokudb_backup_safe_slave_timeout=30; + +--echo ### Backup master +--mkdir $BACKUP_DIR_MASTER +--disable_query_log +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_MASTER' +--enable_query_log + +--echo ### Turn-off safe-slave option for master +SET GLOBAL tokudb_backup_safe_slave=default; +SET GLOBAL tokudb_backup_safe_slave_timeout=default; + +--let $input_file = $M_MASTER_INFO_FILE_PATH +--source include/filter_file.inc +--echo ### Master $MASTER_INFO_FILE content: +--cat_file $M_MASTER_INFO_FILE_PATH + +--echo ### Delete master backup dir +--perl +use File::Path 'rmtree'; +$DDIR=$ENV{"BACKUP_DIR_MASTER"}; +rmtree([ "$DDIR" ]); +EOF + diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test new file mode 100644 index 00000000000..15ba1d8bb66 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test @@ -0,0 +1,49 @@ +--source include/have_tokudb_backup.inc +--source include/have_binlog_format_statement.inc +--source include/have_debug_sync.inc + +--let $SLAVE_INFO_FILE=tokubackup_slave_info +--let $MASTER_INFO_FILE=tokubackup_binlog_info + +--let BACKUP_DIR_SLAVE=$MYSQL_TMP_DIR/tokudb_backup_slave +--let $S_SLAVE_INFO_FILE_PATH=$BACKUP_DIR_SLAVE/$SLAVE_INFO_FILE + +--let BACKUP_DIR_MASTER=$MYSQL_TMP_DIR/tokudb_backup_master +--let $M_MASTER_INFO_FILE_PATH=$BACKUP_DIR_MASTER/$MASTER_INFO_FILE + +# Settings for include/filter_file.inc +--delimiter | +let $script= + s{filename: [^,]+,}{filename: ####,}; + s{position: [^,]+,}{position: ####,}; + s{GTID of last change: [^ ]+}{GTID of last change: #####}; + s{host: [^,]+,}{host: #.#.#.#,}; + s{user: [^,]+,}{user: ####,}; + s{port: [^,]+,}{port: ####,}; + s{master log file: [^,]+,}{master log file: ####,}; + s{relay log file: [^,]+,}{relay log file: ####,}; + s{exec master log pos: [^,]+,}{exec master log pos: ####,}; + s{executed gtid set: [^,]+, }{executed gtid set: ####, }; + s{executed gtid set: [^,]+,[^,]+, }{executed gtid set: ####,####, }; +| +--delimiter ; +--let $skip_column_names= 1 + +--disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +CALL mtr.add_suppression("Sending passwords in plain text without SSL/TLS is extremely insecure"); +--enable_query_log + +--echo ### +--echo # Master-slave test +--echo #### + +--let $rpl_server_count=3 +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connect (slave_2,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK) + +--source rpl_safe_slave.inc + +--source include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt new file mode 100644 index 00000000000..263e1aef0ab --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt @@ -0,0 +1 @@ +--loose-tokudb-commit-sync=OFF --loose-tokudb-fsync-log-period=1000000 diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test new file mode 100644 index 00000000000..5bd53cacdab --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test @@ -0,0 +1,72 @@ +# if --tokudb-commit-sync is off on slave tokudb log must be flushed on backup +# to provide the ability to restore replication after backup restoring + +--source include/have_tokudb_backup.inc + +--let $BACKUP_DIR_SLAVE= $MYSQL_TMP_DIR/tokudb_backup_slave +--let $BACKUP_MYSQL_DATA_DIR= $BACKUP_DIR_SLAVE/mysql_data_dir + +--mkdir $BACKUP_DIR_SLAVE + +--source include/master-slave.inc + +--echo ### Create some data on master +--connection master +CREATE TABLE t1(a INT, b INT, PRIMARY KEY (a)) ENGINE=TokuDB; +INSERT INTO t1 SET a=100, b=100; +INSERT INTO t1 SET a=200, b=100; +INSERT INTO t1 SET a=300, b=100; +INSERT INTO t1 SET a=400, b=100; +INSERT INTO t1 SET a=500, b=100; +UPDATE t1 SET b = 200 WHERE a = 200; +DELETE FROM t1 WHERE a = 100; + +SELECT * FROM t1; + +--sync_slave_with_master +--let $SLAVE_DATA_DIR=`SELECT @@DATADIR` + +--echo ### Check for slave options +SELECT @@tokudb_commit_sync; +SELECT @@tokudb_fsync_log_period; + +--echo ### Check data on slave after sync +SELECT * FROM t1; + + +--echo ### Do backup on slave +--disable_query_log +--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE' +--enable_query_log + +--echo ### Check for errors +SELECT @@session.tokudb_backup_last_error; +SELECT @@session.tokudb_backup_last_error_string; + +--echo ### Stop slave server +--connection slave +--let $rpl_server_number= 2 +--let $rpl_force_stop= 1 +--source include/rpl_stop_server.inc + +--echo ### Restore backup +--exec rm -rf $SLAVE_DATA_DIR; +--exec mv $BACKUP_MYSQL_DATA_DIR $SLAVE_DATA_DIR; + +--echo ### Start slave server and slave threads +--connection slave +--source include/rpl_start_server.inc +--source include/start_slave.inc + +--echo ### Sync slave with master +--connection master +--sync_slave_with_master + +--echo ### Check data on slave +SELECT * FROM t1; + +--echo ### Cleanup +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt b/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt index 5d4cb245e27..a624d6895cc 100644 --- a/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt +++ b/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt @@ -1 +1 @@ -$TOKUDB_OPT $TOKUDB_LOAD_ADD_PATH $TOKUDB_BACKUP_OPT $TOKUDB_BACKUP_LOAD_ADD_PATH --loose-tokudb-check-jemalloc=0 --loose-tokudb-cache-size=512M --loose-tokudb-block-size=1M +$TOKUDB_OPT $TOKUDB_LOAD_ADD_PATH $TOKUDB_BACKUP_OPT $TOKUDB_BACKUP_LOAD_ADD_PATH --loose-innodb_use_native_aio=off --loose-tokudb-check-jemalloc=0 --loose-tokudb-cache-size=512M --loose-tokudb-block-size=1M diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result index e5808f52e69..a7cdbcae1e2 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result @@ -14,16 +14,6 @@ INSERT INTO t1 VALUES(1, 1, '1', '1'), (2, 2, '2', '2'), (3, 3, '3', '3'), (4, 4 ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status OK -set DEBUG_SYNC = 'tokudb_icp_desc_scan_invalidate SIGNAL hit1 WAIT_FOR done1'; -SELECT c FROM t1 WHERE id BETWEEN 5 AND 8 ORDER BY id DESC; -set DEBUG_SYNC = 'now WAIT_FOR hit1'; -set DEBUG_SYNC = 'now SIGNAL done1'; -c -8 -7 -6 -6 -5 set DEBUG_SYNC = 'tokudb_icp_asc_scan_out_of_range SIGNAL hit2 WAIT_FOR done2'; SELECT c FROM t1 WHERE id BETWEEN 5 AND 8 ORDER BY id ASC; set DEBUG_SYNC = 'now WAIT_FOR hit2'; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result b/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result index 6cc499389bb..2975d7d3116 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result @@ -110,7 +110,7 @@ a b c d e 5 1 10 NULL NULL show status like '%Handler_read_prev%'; Variable_name Value -Handler_read_prev 799 +Handler_read_prev 41 flush status; show status like '%Handler_read_prev%'; Variable_name Value @@ -142,7 +142,7 @@ a b c d e 20 1 10 NULL NULL show status like '%Handler_read_prev%'; Variable_name Value -Handler_read_prev 399 +Handler_read_prev 21 flush status; show status like '%Handler_read_next%'; Variable_name Value diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test index 8e4c3b73c09..fec11bf0553 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test @@ -29,24 +29,6 @@ ANALYZE TABLE t1; # lets flip to another connection connect(conn1, localhost, root); -# set up the DEBUG_SYNC point -set DEBUG_SYNC = 'tokudb_icp_desc_scan_invalidate SIGNAL hit1 WAIT_FOR done1'; - -# send the query -send SELECT c FROM t1 WHERE id BETWEEN 5 AND 8 ORDER BY id DESC; - -# back to default connection -connection default; - -# wait for the ICP reverse scan to invalidate -set DEBUG_SYNC = 'now WAIT_FOR hit1'; - -# lets release and clean up -set DEBUG_SYNC = 'now SIGNAL done1'; - -connection conn1; -reap; - # set up the DEBUG_SYNC point again, but for the out of range set DEBUG_SYNC = 'tokudb_icp_asc_scan_out_of_range SIGNAL hit2 WAIT_FOR done2'; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test b/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test index fd4c5fad534..957fdadb71f 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test @@ -132,6 +132,7 @@ CREATE TABLE `t2` ( ); LOAD DATA INFILE 'leak172_t1.data' INTO TABLE `t1` fields terminated by ','; +remove_file $MYSQLD_DATADIR/test/leak172_t1.data; connect(conn1,localhost,root,,); set session debug="+d,tokudb_end_bulk_insert_sleep"; @@ -145,8 +146,9 @@ UPDATE t1, t2 SET t1.`c5` = 4 WHERE t1.`c6` <= 'o'; connection conn1; reap; +remove_file $MYSQLD_DATADIR/test/leak172_t2.data; connection default; disconnect conn1; -drop table t1,t2; \ No newline at end of file +drop table t1,t2; diff --git a/storage/tokudb/tokudb_dir_cmd.cc b/storage/tokudb/tokudb_dir_cmd.cc new file mode 100644 index 00000000000..f9995302d49 --- /dev/null +++ b/storage/tokudb/tokudb_dir_cmd.cc @@ -0,0 +1,331 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +/* -*- mode: C; c-basic-offset: 4 -*- */ +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 TokuDB. If not, see . + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include "hatoku_hton.h" +#include "tokudb_dir_cmd.h" +#include "my_dbug.h" +#include "sql_base.h" + +#include +#include + +namespace tokudb { + +const char tokens_delimiter = ' '; +const char tokens_escape_delimiter_char = '\\'; + +static int MDL_and_TDC(THD *thd, + const char *db, + const char *table, + const dir_cmd_callbacks &cb) { + int error; + LEX_STRING db_arg; + LEX_STRING table_arg; + + db_arg.str = const_cast(db); + db_arg.length = strlen(db);; + table_arg.str = const_cast(table); + table_arg.length = strlen(table); + Table_ident table_ident(thd, db_arg, table_arg, true);; + thd->lex->select_lex.add_table_to_list( + thd, &table_ident, NULL, 1, TL_UNLOCK, MDL_EXCLUSIVE, 0, 0, 0); + /* The lock will be released at the end of mysq_execute_command() */ + error = lock_table_names(thd, + thd->lex->select_lex.table_list.first, + NULL, + thd->variables.lock_wait_timeout, + 0); + if (error) { + if (cb.set_error) + cb.set_error(thd, + error, + "Can't lock table '%s.%s'", + db, + table); + return error; + } + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db, table, false); + return error; +} + +static bool parse_db_and_table(const char *dname, + std::string /*out*/ &db_name, + std::string /*out*/ &table_name) { + const char *begin; + const char *end; + const char *db_name_begin; + const char *db_name_end; + + begin = strchr(dname, '/'); + if (!begin) + return false; + ++begin; + end = strchr(begin, '/'); + if (!end) + return false; + + db_name_begin = begin; + db_name_end = end; + + begin = end + 1; + + end = strchr(begin, '-'); + if (!end) + return false; + + if (strncmp(end, "-main", strlen("-main")) && + strncmp(end, "-status", strlen("-status")) && + strncmp(end, "-key", strlen("-key"))) + return false; + + db_name.assign(db_name_begin, db_name_end); + table_name.assign(begin, end); + + return true; +} + +static int attach(THD *thd, + const std::string &dname, + const std::string &iname, + const dir_cmd_callbacks &cb) { + int error; + DB_TXN* txn = NULL; + DB_TXN *parent_txn = NULL; + tokudb_trx_data *trx = NULL; + + std::string db_name; + std::string table_name; + + if (parse_db_and_table(dname.c_str(), db_name, table_name)) { + error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb); + if (error) + goto cleanup; + } + + trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton); + if (trx && trx->sub_sp_level) + parent_txn = trx->sub_sp_level; + error = txn_begin(db_env, parent_txn, &txn, 0, thd); + if (error) + goto cleanup; + + error = db_env->dirtool_attach(db_env, + txn, + dname.c_str(), + iname.c_str()); +cleanup: + if (txn) { + if (error) { + abort_txn(txn); + } + else { + commit_txn(txn, 0); + } + } + return error; +} + +static int detach(THD *thd, + const std::string &dname, + const dir_cmd_callbacks &cb) { + int error; + DB_TXN* txn = NULL; + DB_TXN *parent_txn = NULL; + tokudb_trx_data *trx = NULL; + + std::string db_name; + std::string table_name; + + if (parse_db_and_table(dname.c_str(), db_name, table_name)) { + error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb); + if (error) + goto cleanup; + } + + trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton); + if (trx && trx->sub_sp_level) + parent_txn = trx->sub_sp_level; + error = txn_begin(db_env, parent_txn, &txn, 0, thd); + if (error) + goto cleanup; + + error = db_env->dirtool_detach(db_env, + txn, + dname.c_str()); +cleanup: + if (txn) { + if (error) { + abort_txn(txn); + } + else { + commit_txn(txn, 0); + } + } + return error; +} + +static int move(THD *thd, + const std::string &old_dname, + const std::string &new_dname, + const dir_cmd_callbacks &cb) { + int error; + DB_TXN* txn = NULL; + DB_TXN *parent_txn = NULL; + tokudb_trx_data *trx = NULL; + + std::string db_name; + std::string table_name; + + if (parse_db_and_table(old_dname.c_str(), db_name, table_name)) { + error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb); + if (error) + goto cleanup; + } + + trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton); + if (trx && trx->sub_sp_level) + parent_txn = trx->sub_sp_level; + error = txn_begin(db_env, parent_txn, &txn, 0, thd); + if (error) + goto cleanup; + + error = db_env->dirtool_move(db_env, + txn, + old_dname.c_str(), + new_dname.c_str()); +cleanup: + if (txn) { + if (error) { + abort_txn(txn); + } + else { + commit_txn(txn, 0); + } + } + return error; +} + +static void tokenize(const char *cmd_str, + std::vector /*out*/ &tokens) { + DBUG_ASSERT(cmd_str); + + bool was_escape = false; + const char *token_begin = cmd_str; + const char *token_end = token_begin; + + while (*token_end) { + if (*token_end == tokens_escape_delimiter_char) { + was_escape = true; + } + else if (*token_end == tokens_delimiter) { + if (was_escape) + was_escape = false; + else { + if (token_begin == token_end) + ++token_begin; + else { + tokens.push_back(std::string(token_begin, token_end)); + token_begin = token_end + 1; + } + } + } + else { + was_escape = false; + } + ++token_end; + } + + if (token_begin != token_end) + tokens.push_back(std::string(token_begin, token_end)); +} + +void process_dir_cmd(THD *thd, + const char *cmd_str, + const dir_cmd_callbacks &cb) { + + DBUG_ASSERT(thd); + DBUG_ASSERT(cmd_str); + + std::vector tokens; + tokenize(cmd_str, tokens); + + if (tokens.empty()) + return; + + const std::string &cmd = tokens[0]; + + if (!cmd.compare("attach")) { + if (tokens.size() != 3) { + if (cb.set_error) + cb.set_error(thd, + EINVAL, + "attach command requires two arguments"); + } + else { + int r = attach(thd, tokens[1], tokens[2], cb); + if (r && cb.set_error) + cb.set_error(thd, r, "Attach command error"); + } + } + else if (!cmd.compare("detach")) { + if (tokens.size() != 2) { + if (cb.set_error) + cb.set_error(thd, + EINVAL, + "detach command requires one argument"); + } + else { + int r = detach(thd, tokens[1], cb); + if (r && cb.set_error) + cb.set_error(thd, r, "detach command error"); + } + } + else if (!cmd.compare("move")) { + if (tokens.size() != 3) { + if (cb.set_error) + cb.set_error(thd, + EINVAL, + "move command requires two arguments"); + } + else { + int r = move(thd, tokens[1], tokens[2], cb); + if (r && cb.set_error) + cb.set_error(thd, r, "move command error"); + } + } + else { + if (cb.set_error) + cb.set_error(thd, + ENOENT, + "Unknown command '%s'", + cmd.c_str()); + } + + return; +}; + + +} // namespace tokudb diff --git a/storage/tokudb/tokudb_dir_cmd.h b/storage/tokudb/tokudb_dir_cmd.h new file mode 100644 index 00000000000..b39caadc7c3 --- /dev/null +++ b/storage/tokudb/tokudb_dir_cmd.h @@ -0,0 +1,46 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 TokuDB. If not, see . + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#ifndef _TOKUDB_DIR_CMD_H +#define _TOKUDB_DIR_CMD_H + +#include + +namespace tokudb { + +struct dir_cmd_callbacks { + void (*set_error)(THD *thd, + int error, + const char *error_fmt, + ...); +}; + +void process_dir_cmd(THD *thd, + const char *cmd_str, + const dir_cmd_callbacks &cb); + +}; + +#endif // _TOKUDB_DIR_CMD_H diff --git a/storage/tokudb/tokudb_sysvars.cc b/storage/tokudb/tokudb_sysvars.cc index e5185615279..31c44c45500 100644 --- a/storage/tokudb/tokudb_sysvars.cc +++ b/storage/tokudb/tokudb_sysvars.cc @@ -25,6 +25,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." #include "hatoku_hton.h" +#include "sql_acl.h" +#include "tokudb_dir_cmd.h" +#include "sql_parse.h" namespace tokudb { namespace sysvars { @@ -40,6 +43,8 @@ namespace sysvars { #define TOKUDB_VERSION_STR NULL #endif +const size_t error_buffer_max_size = 1024; + ulonglong cache_size = 0; uint cachetable_pool_threads = 0; int cardinality_scale_percent = 0; @@ -918,7 +923,70 @@ static MYSQL_THDVAR_BOOL( true); #endif +static int dir_cmd_check(THD* thd, struct st_mysql_sys_var* var, + void* save, struct st_mysql_value* value) ; +static MYSQL_THDVAR_INT(dir_cmd_last_error, + PLUGIN_VAR_THDLOCAL, + "error from the last dir command. 0 is success", + NULL, NULL, 0, 0, 0, 1); + +static MYSQL_THDVAR_STR(dir_cmd_last_error_string, + PLUGIN_VAR_THDLOCAL + PLUGIN_VAR_MEMALLOC, + "error string from the last dir command", + NULL, NULL, NULL); + +static MYSQL_THDVAR_STR(dir_cmd, + PLUGIN_VAR_THDLOCAL + PLUGIN_VAR_MEMALLOC, + "name of the directory where the backup is stored", + dir_cmd_check, NULL, NULL); + +static void dir_cmd_set_error(THD *thd, + int error, + const char *error_fmt, + ...) { + char buff[error_buffer_max_size]; + va_list varargs; + + assert(thd); + assert(error_fmt); + + va_start(varargs, error_fmt); + vsnprintf(buff, sizeof(buff), error_fmt, varargs); + va_end(varargs); + + THDVAR_SET(thd, dir_cmd_last_error, &error); + THDVAR_SET(thd, dir_cmd_last_error_string, buff); +} + +static int dir_cmd_check(THD* thd, struct st_mysql_sys_var* var, + void* save, struct st_mysql_value* value) { + int error = 0; + dir_cmd_set_error(thd, error, ""); + + if (check_global_access(thd, SUPER_ACL)) { + return 1; + } + + char buff[STRING_BUFFER_USUAL_SIZE]; + int length = sizeof(buff); + const char *str = value->val_str(value, buff, &length); + if (str) { + str = thd->strmake(str, length); + *(const char**)save = str; + } + + if (str) { + dir_cmd_callbacks callbacks { .set_error = dir_cmd_set_error }; + process_dir_cmd(thd, str, callbacks); + + error = THDVAR(thd, dir_cmd_last_error); + } else { + error = EINVAL; + } + + return error; +} //****************************************************************************** // all system variables @@ -949,7 +1017,6 @@ st_mysql_sys_var* system_variables[] = { MYSQL_SYSVAR(version), MYSQL_SYSVAR(write_status_frequency), MYSQL_SYSVAR(dir_per_db), - #if TOKU_INCLUDE_HANDLERTON_HANDLE_FATAL_SIGNAL MYSQL_SYSVAR(gdb_path), MYSQL_SYSVAR(gdb_on_fatal), @@ -1008,6 +1075,9 @@ st_mysql_sys_var* system_variables[] = { #if TOKUDB_DEBUG MYSQL_SYSVAR(debug_pause_background_job_manager), #endif // TOKUDB_DEBUG + MYSQL_SYSVAR(dir_cmd_last_error), + MYSQL_SYSVAR(dir_cmd_last_error_string), + MYSQL_SYSVAR(dir_cmd), NULL }; From c1b3aaa24eceb59b20cd317256d6522f693a5869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 May 2017 14:28:19 +0300 Subject: [PATCH 116/148] Update perfschema version to 5.6.36 post-merge --- storage/perfschema/ha_perfschema.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index 2445bd80927..837a2463549 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -205,7 +205,7 @@ maria_declare_plugin(perfschema) 0x0001, pfs_status_vars, NULL, - "5.6.33", + "5.6.36", MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; From dfeff407067e2eaa27a51a04306863f912ec4cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 May 2017 17:22:44 +0300 Subject: [PATCH 117/148] Remove tokudb_dir_cmd variable The feature is too dangerous for a stable version. --- storage/tokudb/tokudb_sysvars.cc | 71 -------------------------------- 1 file changed, 71 deletions(-) diff --git a/storage/tokudb/tokudb_sysvars.cc b/storage/tokudb/tokudb_sysvars.cc index 2e356d0fd52..bbc39dc550a 100644 --- a/storage/tokudb/tokudb_sysvars.cc +++ b/storage/tokudb/tokudb_sysvars.cc @@ -43,7 +43,6 @@ namespace sysvars { #define TOKUDB_VERSION_STR NULL #endif -const size_t error_buffer_max_size = 1024; ulonglong cache_size = 0; uint cachetable_pool_threads = 0; @@ -923,73 +922,6 @@ static MYSQL_THDVAR_BOOL( true); #endif -static int dir_cmd_check(THD* thd, struct st_mysql_sys_var* var, - void* save, struct st_mysql_value* value) ; - -static MYSQL_THDVAR_INT(dir_cmd_last_error, - PLUGIN_VAR_THDLOCAL, - "error from the last dir command. 0 is success", - NULL, NULL, 0, 0, 0, 1); - -static MYSQL_THDVAR_STR(dir_cmd_last_error_string, - PLUGIN_VAR_THDLOCAL + PLUGIN_VAR_MEMALLOC, - "error string from the last dir command", - NULL, NULL, NULL); - -static MYSQL_THDVAR_STR(dir_cmd, - PLUGIN_VAR_THDLOCAL + PLUGIN_VAR_MEMALLOC, - "name of the directory where the backup is stored", - dir_cmd_check, NULL, NULL); - -static void dir_cmd_set_error(THD *thd, - int error, - const char *error_fmt, - ...) { - char buff[error_buffer_max_size]; - va_list varargs; - - assert(thd); - assert(error_fmt); - - va_start(varargs, error_fmt); - vsnprintf(buff, sizeof(buff), error_fmt, varargs); - va_end(varargs); - -#if 0 // Disable macros unavailable in MariaDB. - THDVAR_SET(thd, dir_cmd_last_error, &error); - THDVAR_SET(thd, dir_cmd_last_error_string, buff); -#endif -} - -static int dir_cmd_check(THD* thd, struct st_mysql_sys_var* var, - void* save, struct st_mysql_value* value) { - int error = 0; - dir_cmd_set_error(thd, error, ""); - - if (check_global_access(thd, SUPER_ACL)) { - return 1; - } - - char buff[STRING_BUFFER_USUAL_SIZE]; - int length = sizeof(buff); - const char *str = value->val_str(value, buff, &length); - if (str) { - str = thd->strmake(str, length); - *(const char**)save = str; - } - - if (str) { - dir_cmd_callbacks callbacks { .set_error = dir_cmd_set_error }; - process_dir_cmd(thd, str, callbacks); - - error = THDVAR(thd, dir_cmd_last_error); - } else { - error = EINVAL; - } - - return error; -} - //****************************************************************************** // all system variables //****************************************************************************** @@ -1077,9 +1009,6 @@ st_mysql_sys_var* system_variables[] = { #if TOKUDB_DEBUG MYSQL_SYSVAR(debug_pause_background_job_manager), #endif // TOKUDB_DEBUG - MYSQL_SYSVAR(dir_cmd_last_error), - MYSQL_SYSVAR(dir_cmd_last_error_string), - MYSQL_SYSVAR(dir_cmd), NULL }; From 934b8312817d4e8e0387fae0bd9cca3ffafbc7de Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 16 May 2017 08:24:42 -0700 Subject: [PATCH 118/148] Fixed the bug mdev-7791. When an IN subquery predicate was converted to a semi-join that were materialized and the result of the materialization happened to be the last in the execution plan then any conjunctive condition with RAND() turned out to be lost. Fixed by attaching this condition to the last top base table. --- mysql-test/r/subselect_sj2_mat.result | 23 +++++++++++++++++++++++ mysql-test/t/subselect_sj2_mat.test | 20 ++++++++++++++++++++ sql/sql_select.cc | 18 +++++++++++++----- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index 4e75aee24a2..202e6cc4b9e 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -1556,3 +1556,26 @@ i1 DROP TABLE t1,t2,t3; set join_cache_level= @save_join_cache_level; set optimizer_switch=@save_optimizer_switch; +# +# mdev-7791: materialization of a semi-join subquery + +# RAND() in WHERE +# (materialized table is accessed last) +# +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='materialization=on'; +create table t1(i int); +insert into t1 values (1), (2), (3), (7), (9), (10); +create table t2(i int); +insert into t2 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +select * from t1 where (rand() < 0) and i in (select i from t2); +i +explain extended +select * from t1 where (rand() < 0) and i in (select i from t2); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where +1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10 100.00 +Warnings: +Note 1003 select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join (`test`.`t2`) where ((rand() < 0)) +drop table t1,t2; +set optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/subselect_sj2_mat.test b/mysql-test/t/subselect_sj2_mat.test index 61d9b09edff..0f2892ae2dc 100644 --- a/mysql-test/t/subselect_sj2_mat.test +++ b/mysql-test/t/subselect_sj2_mat.test @@ -263,3 +263,23 @@ DROP TABLE t1,t2,t3; set join_cache_level= @save_join_cache_level; set optimizer_switch=@save_optimizer_switch; +--echo # +--echo # mdev-7791: materialization of a semi-join subquery + +--echo # RAND() in WHERE +--echo # (materialized table is accessed last) +--echo # + +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='materialization=on'; + +create table t1(i int); +insert into t1 values (1), (2), (3), (7), (9), (10); +create table t2(i int); +insert into t2 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +select * from t1 where (rand() < 0) and i in (select i from t2); +explain extended +select * from t1 where (rand() < 0) and i in (select i from t2); + +drop table t1,t2; +set optimizer_switch=@save_optimizer_switch; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 09e6ece7807..bad57aeac87 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8761,12 +8761,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Step #2: Extract WHERE/ON parts */ + uint i; + for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--) + { + if (!join->join_tab[i].bush_children) + break; + } + uint last_top_base_tab_idx= i; + table_map save_used_tables= 0; used_tables=((select->const_tables=join->const_table_map) | OUTER_REF_TABLE_BIT | RAND_TABLE_BIT); JOIN_TAB *tab; table_map current_map; - uint i= join->const_tables; + i= join->const_tables; for (tab= first_depth_first_tab(join); tab; tab= next_depth_first_tab(join, tab), i++) { @@ -8804,7 +8812,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) Following force including random expression in last table condition. It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5 */ - if (tab == join->join_tab + join->top_join_tab_count - 1) + if (tab == join->join_tab + last_top_base_tab_idx) current_map|= RAND_TABLE_BIT; used_tables|=current_map; @@ -8843,10 +8851,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) save_used_tables= 0; } else - { - tmp= make_cond_for_table(thd, cond, used_tables, current_map, i, + { + tmp= make_cond_for_table(thd, cond, used_tables, current_map, i, FALSE, FALSE); - } + } /* Add conditions added by add_not_null_conds(). */ if (tab->select_cond) add_cond_and_fix(thd, &tmp, tab->select_cond); From e63e2fe206a62058c1134e06d25c0a40745f38c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 16 May 2017 17:40:52 +0300 Subject: [PATCH 119/148] Fix warnings in innochecksum compilation --- storage/innobase/page/page0zip.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index e8a147aab47..878a0b8728f 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -2,6 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -68,8 +69,8 @@ using namespace std; # define buf_LRU_stat_inc_unzip() ((void) 0) #endif /* !UNIV_HOTBACKUP */ -#ifndef UNIV_HOTBACKUP #ifndef UNIV_INNOCHECKSUM +#ifndef UNIV_HOTBACKUP /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */ UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_SSIZE_MAX]; /** Statistics on compression, indexed by index->id */ @@ -79,7 +80,6 @@ UNIV_INTERN ib_mutex_t page_zip_stat_per_index_mutex; #ifdef HAVE_PSI_INTERFACE UNIV_INTERN mysql_pfs_key_t page_zip_stat_per_index_mutex_key; #endif /* HAVE_PSI_INTERFACE */ -#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_HOTBACKUP */ /* Compression level to be used by zlib. Settable by user. */ @@ -128,7 +128,6 @@ Compare at most sizeof(field_ref_zero) bytes. /* Enable some extra debugging output. This code can be enabled independently of any UNIV_ debugging conditions. */ -#ifndef UNIV_INNOCHECKSUM #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG # include MY_ATTRIBUTE((format (printf, 1, 2))) From b8187fd005b765b81261908ba9caa667d506e3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 16 May 2017 17:47:04 +0300 Subject: [PATCH 120/148] MDEV-12071 storage/xtradb/handler/ha_innodb.cc: Cannot assign const_iterator to iterator --- storage/xtradb/handler/ha_innodb.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 12ae71508c7..6c390328258 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -13339,7 +13339,8 @@ fill_foreign_key_list(THD* thd, { ut_ad(mutex_own(&dict_sys->mutex)); - for (dict_foreign_set::iterator it = table->referenced_set.begin(); + for (dict_foreign_set::const_iterator it + = table->referenced_set.begin(); it != table->referenced_set.end(); ++it) { dict_foreign_t* foreign = *it; From 492c1e414564b4edc079b2eef7266e1cd551e91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 16 May 2017 18:33:51 +0300 Subject: [PATCH 121/148] Fix an incorrect debug assertion --- storage/innobase/include/page0zip.ic | 4 +++- storage/xtradb/include/page0zip.ic | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic index 6c7d8cd32c7..9a583086925 100644 --- a/storage/innobase/include/page0zip.ic +++ b/storage/innobase/include/page0zip.ic @@ -2,6 +2,7 @@ Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -172,7 +173,8 @@ page_zip_rec_needs_ext( ignored if zip_size == 0 */ ulint zip_size) /*!< in: compressed page size in bytes, or 0 */ { - ut_ad(rec_size > comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES); + ut_ad(rec_size + > (comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES)); ut_ad(ut_is_2pow(zip_size)); ut_ad(comp || !zip_size); diff --git a/storage/xtradb/include/page0zip.ic b/storage/xtradb/include/page0zip.ic index 6c7d8cd32c7..9a583086925 100644 --- a/storage/xtradb/include/page0zip.ic +++ b/storage/xtradb/include/page0zip.ic @@ -2,6 +2,7 @@ Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -172,7 +173,8 @@ page_zip_rec_needs_ext( ignored if zip_size == 0 */ ulint zip_size) /*!< in: compressed page size in bytes, or 0 */ { - ut_ad(rec_size > comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES); + ut_ad(rec_size + > (comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES)); ut_ad(ut_is_2pow(zip_size)); ut_ad(comp || !zip_size); From 7972da8aa1c52121f60fb8fdae534a46892b4e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 16 May 2017 20:08:47 +0300 Subject: [PATCH 122/148] Silence bogus GCC 7 warnings -Wimplicit-fallthrough Do not silence uncertain cases, or fix any bugs. The only functional change should be that ha_federated::extra() is not calling DBUG_PRINT to report an unhandled case for HA_EXTRA_PREPARE_FOR_DROP. --- client/mysqldump.c | 1 + extra/replace.c | 1 + sql/events.cc | 2 ++ sql/field.cc | 2 +- sql/item.cc | 4 ++-- sql/item_func.cc | 3 ++- sql/item_strfunc.cc | 4 ++-- sql/log.cc | 7 ++++++- sql/mysqld.cc | 3 +++ sql/opt_sum.cc | 3 ++- sql/slave.cc | 5 ++--- sql/sp_head.cc | 3 ++- sql/sql_digest.cc | 4 +++- sql/sql_lex.cc | 5 ++++- sql/sql_parse.cc | 6 ++++-- sql/sql_plugin.cc | 5 +++-- sql/sql_prepare.cc | 4 ++-- sql/sql_show.cc | 3 ++- sql/sql_table.cc | 3 ++- sql/sql_yacc.yy | 2 ++ storage/connect/array.cpp | 2 ++ storage/connect/filamdbf.cpp | 4 +++- storage/connect/filamfix.cpp | 3 ++- storage/connect/filamtxt.cpp | 1 + storage/connect/filamvct.cpp | 3 +++ storage/connect/filter.cpp | 3 ++- storage/connect/ha_connect.cc | 8 +++++--- storage/connect/json.cpp | 4 ++-- storage/connect/plgdbutl.cpp | 2 +- storage/connect/reldef.cpp | 1 + storage/connect/tabdos.cpp | 1 + storage/connect/tabjson.cpp | 2 +- storage/connect/value.cpp | 2 +- storage/connect/xindex.cpp | 2 +- storage/connect/xobject.cpp | 2 +- storage/federated/ha_federated.cc | 2 ++ storage/heap/hp_create.c | 4 ++-- storage/innobase/handler/ha_innodb.cc | 11 +++++++---- storage/innobase/include/data0type.ic | 4 +++- storage/innobase/include/mach0data.ic | 15 ++++++++------- storage/innobase/include/ut0rnd.ic | 7 +++++++ storage/innobase/row/row0import.cc | 1 + storage/innobase/row/row0log.cc | 2 ++ storage/innobase/row/row0mysql.cc | 3 ++- storage/innobase/row/row0purge.cc | 4 +++- storage/innobase/sync/sync0sync.cc | 1 + storage/maria/ma_extra.c | 3 ++- storage/maria/ma_recovery.c | 2 +- storage/myisam/mi_extra.c | 3 ++- storage/spider/spd_db_conn.cc | 2 +- storage/xtradb/handler/ha_innodb.cc | 11 +++++++---- storage/xtradb/include/data0type.ic | 3 ++- storage/xtradb/include/mach0data.ic | 15 ++++++++------- storage/xtradb/include/ut0rnd.ic | 7 +++++++ storage/xtradb/row/row0import.cc | 1 + storage/xtradb/row/row0log.cc | 2 ++ storage/xtradb/row/row0mysql.cc | 3 ++- storage/xtradb/row/row0purge.cc | 4 +++- storage/xtradb/sync/sync0sync.cc | 5 +++-- strings/ctype-utf8.c | 10 +++++++++- strings/dtoa.c | 8 +++++--- 61 files changed, 168 insertions(+), 75 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 8ed10f1e5cb..245f24dd508 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2142,6 +2142,7 @@ static void print_xml_comment(FILE *xml_file, size_t len, case '-': if (*(comment_string + 1) == '-') /* Only one hyphen allowed. */ break; + /* fall through */ default: fputc(*comment_string, xml_file); break; diff --git a/extra/replace.c b/extra/replace.c index 56cf02f2002..465c0c48f6e 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -174,6 +174,7 @@ register char **argv[]; break; case 'V': version=1; + /* fall through */ case 'I': case '?': help=1; /* Help text written */ diff --git a/sql/events.cc b/sql/events.cc index 75780cd94c5..8d78497a29e 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2005, 2013, Oracle and/or its affiliates. + 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 @@ -242,6 +243,7 @@ common_1_lev_code: break; case INTERVAL_WEEK: expr/= 7; + /* fall through */ default: close_quote= FALSE; break; diff --git a/sql/field.cc b/sql/field.cc index dec89e16674..7d7fad2d84d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9464,7 +9464,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, case MYSQL_TYPE_DATE: /* We don't support creation of MYSQL_TYPE_DATE anymore */ sql_type= MYSQL_TYPE_NEWDATE; - /* fall trough */ + /* fall through */ case MYSQL_TYPE_NEWDATE: length= MAX_DATE_WIDTH; break; diff --git a/sql/item.cc b/sql/item.cc index ceb8d984d9e..4ce8396f71e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2010, 2016, MariaDB + Copyright (c) 2010, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -5925,7 +5925,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) collation.collation); break; } - /* Fall through to make_string_field() */ + /* Fall through */ case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_VAR_STRING: diff --git a/sql/item_func.cc b/sql/item_func.cc index 2c43181e8bb..13ea5291edc 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2034,6 +2034,7 @@ my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value) return decimal_value; case E_DEC_DIV_ZERO: signal_divide_by_null(); + /* fall through */ default: null_value= 1; return 0; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9baa5d52319..7cd712cc5e1 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5090,7 +5090,7 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) goto null; case DYN_COL_INT: signed_value= 1; // For error message - /* fall_trough */ + /* fall through */ case DYN_COL_UINT: if (signed_value || val.x.ulong_value <= LONGLONG_MAX) { @@ -5103,7 +5103,7 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } /* let double_to_datetime_with_warn() issue the warning message */ val.x.double_value= static_cast(ULONGLONG_MAX); - /* fall_trough */ + /* fall through */ case DYN_COL_DOUBLE: if (double_to_datetime_with_warn(val.x.double_value, ltime, fuzzy_date, 0 /* TODO */)) diff --git a/sql/log.cc b/sql/log.cc index b80d65e20db..6ebfda67ecf 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2016, MariaDB + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -8822,8 +8822,10 @@ void TC_LOG_MMAP::close() mysql_cond_destroy(&COND_pool); mysql_cond_destroy(&COND_active); mysql_cond_destroy(&COND_queue_busy); + /* fall through */ case 5: data[0]='A'; // garble the first (signature) byte, in case mysql_file_delete fails + /* fall through */ case 4: for (i=0; i < npages; i++) { @@ -8832,10 +8834,13 @@ void TC_LOG_MMAP::close() mysql_mutex_destroy(&pages[i].lock); mysql_cond_destroy(&pages[i].cond); } + /* fall through */ case 3: my_free(pages); + /* fall through */ case 2: my_munmap((char*)data, (size_t)file_length); + /* fall through */ case 1: mysql_file_close(fd, MYF(0)); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a8fef1bd8a3..0aa917cb7fe 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8724,6 +8724,9 @@ mysql_getopt_value(const char *name, uint length, return (uchar**) &key_cache->changed_blocks_hash_size; } } + /* We return in all cases above. Let us silence -Wimplicit-fallthrough */ + DBUG_ASSERT(0); + /* fall through */ case OPT_REPLICATE_DO_DB: case OPT_REPLICATE_DO_TABLE: case OPT_REPLICATE_IGNORE_DB: diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 1ff1f4a6449..ed729cb1734 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab + Copyright (c) 2008, 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 @@ -1041,6 +1041,7 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond) case Item_func::LT_FUNC: case Item_func::LE_FUNC: less_fl= 1; + /* fall through */ case Item_func::GT_FUNC: case Item_func::GE_FUNC: { diff --git a/sql/slave.cc b/sql/slave.cc index 3dd17fd7276..8c3627514ac 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2016, MariaDB + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -5798,9 +5798,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) mi->last_queued_gtid.seq_no == 1000) goto skip_relay_logging; }); - /* Fall through to default case ... */ #endif - + /* fall through */ default: default_action: if (mi->using_gtid != Master_info::USE_GTID_NO && mi->gtid_event_seen) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fb0f3132816..ea9e1c1c822 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2002, 2016, Oracle and/or its affiliates. - Copyright (c) 2011, 2016, MariaDB + Copyright (c) 2011, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -142,6 +142,7 @@ sp_get_item_value(THD *thd, Item *item, String *str) if (item->field_type() != MYSQL_TYPE_BIT) return item->val_str(str); else {/* Bit type is handled as binary string */} + /* fall through */ case STRING_RESULT: { String *result= item->val_str(str); diff --git a/sql/sql_digest.cc b/sql/sql_digest.cc index c8ba371ea7e..0cc969b3758 100644 --- a/sql/sql_digest.cc +++ b/sql/sql_digest.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -453,7 +454,8 @@ sql_digest_state* digest_add_token(sql_digest_state *state, } } while (found_unary); } - /* fall through, for case NULL_SYM below */ + /* for case NULL_SYM below */ + /* fall through */ case LEX_HOSTNAME: case TEXT_STRING: case NCHAR_STRING: diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index de450b8ede8..99f43ebda22 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2016, MariaDB + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1174,12 +1174,14 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) state= MY_LEX_HEX_NUMBER; break; } + /* fall through */ case MY_LEX_IDENT_OR_BIN: if (lip->yyPeek() == '\'') { // Found b'bin-number' state= MY_LEX_BIN_NUMBER; break; } + /* fall through */ case MY_LEX_IDENT: const char *start; #if defined(USE_MB) && defined(USE_MB_IDENT) @@ -1527,6 +1529,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) break; } /* " used for strings */ + /* fall through */ case MY_LEX_STRING: // Incomplete text string if (!(yylval->lex_str.str = get_text(lip, 1, 1))) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e57756217ca..b054dd3f5ed 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2518,8 +2518,8 @@ mysql_execute_command(THD *thd) MYF(0)); goto error; } - /* no break; fall through */ } + /* fall through */ case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: case SQLCOM_SHOW_DATABASES: @@ -3323,8 +3323,8 @@ end_with_restore_list: /* mysql_update return 2 if we need to switch to multi-update */ if (up_result != 2) break; - /* Fall through */ } + /* Fall through */ case SQLCOM_UPDATE_MULTI: { DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -3434,6 +3434,7 @@ end_with_restore_list: DBUG_PRINT("debug", ("Just after generate_incident()")); } #endif + /* fall through */ case SQLCOM_INSERT: { DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -4273,6 +4274,7 @@ end_with_restore_list: initialize this variable because RESET shares the same code as FLUSH */ lex->no_write_to_binlog= 1; + /* fall through */ case SQLCOM_FLUSH: { int write_to_binlog; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 23b795cdf7f..63c3933db93 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2005, 2013, Oracle and/or its affiliates. - Copyright (c) 2010, 2014, SkySQL Ab. + Copyright (c) 2010, 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 @@ -1816,8 +1816,8 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) switch ((*(p++)= *(list++))) { case '\0': list= NULL; /* terminate the loop */ - /* fall through */ #ifndef __WIN__ + /* fall through */ case ':': /* can't use this as delimiter as it may be drive letter */ #endif case ';': @@ -1858,6 +1858,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) str->str= p; continue; } + /* fall through */ default: str->length++; continue; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 03624647970..a88e6d776c7 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2002, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, MariaDB + Copyright (c) 2008, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2108,7 +2108,7 @@ static bool check_prepared_statement(Prepared_statement *stmt) /* mysql_test_update returns 2 if we need to switch to multi-update */ if (res != 2) break; - + /* fall through */ case SQLCOM_UPDATE_MULTI: res= mysql_test_multiupdate(stmt, tables, res == 2); break; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ea9f9ec2cca..ae074eee556 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2016, MariaDB + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -983,6 +983,7 @@ public: is_handled= FALSE; break; } + /* fall through */ case ER_COLUMNACCESS_DENIED_ERROR: case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */ case ER_PROCACCESS_DENIED_ERROR: diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 503048f9f6a..2eff8fd5e2f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6851,7 +6851,8 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, case Alter_info::LEAVE_AS_IS: if (!indexes_were_disabled) break; - /* fall-through: disabled indexes */ + /* disabled indexes */ + /* fall through */ case Alter_info::DISABLE: error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cd5b9657730..95a683165e2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4681,9 +4681,11 @@ size_number: case 'g': case 'G': text_shift_number+=10; + /* fall through */ case 'm': case 'M': text_shift_number+=10; + /* fall through */ case 'k': case 'K': text_shift_number+=10; diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index 1998ab890e9..88ab85d20eb 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -155,6 +155,7 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec) switch (type) { case TYPE_STRING: Len = length; + /* fall through */ case TYPE_SHORT: case TYPE_INT: case TYPE_DOUBLE: @@ -592,6 +593,7 @@ int ARRAY::Convert(PGLOBAL g, int k, PVAL vp) switch (Type) { case TYPE_DOUBLE: prec = 2; + /* fall through */ case TYPE_SHORT: case TYPE_INT: case TYPE_DATE: diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 9feb61d7d61..fec98a72544 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -503,7 +503,8 @@ bool DBFFAM::OpenTableFile(PGLOBAL g) break; } // endif - // Selective delete, pass thru + // Selective delete + /* fall through */ case MODE_UPDATE: UseTemp = Tdbp->IsUsingTemp(g); strcpy(opmode, (UseTemp) ? "rb" : "r+b"); @@ -623,6 +624,7 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g) case 'L': // Large (big) integer case 'T': // Tiny integer c = 'N'; // Numeric + /* fall through */ case 'N': // Numeric (integer) case 'F': // Float (double) descp->Decimals = (uchar)cdp->F.Prec; diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp index cd25429318a..dcb677dc848 100644 --- a/storage/connect/filamfix.cpp +++ b/storage/connect/filamfix.cpp @@ -919,7 +919,8 @@ bool BGXFAM::OpenTableFile(PGLOBAL g) break; } // endif - // Selective delete, pass thru + // Selective delete + /* fall through */ case MODE_UPDATE: UseTemp = Tdbp->IsUsingTemp(g); oflag |= (UseTemp) ? O_RDONLY : O_RDWR; diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp index e53cdcd9ba9..12c0a66ecad 100644 --- a/storage/connect/filamtxt.cpp +++ b/storage/connect/filamtxt.cpp @@ -561,6 +561,7 @@ bool DOSFAM::OpenTableFile(PGLOBAL g) // Selective delete, pass thru Bin = true; + /* fall through */ case MODE_UPDATE: if ((UseTemp = Tdbp->IsUsingTemp(g))) { strcpy(opmode, "r"); diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp index fdc5433f4a4..71a8dd98c61 100755 --- a/storage/connect/filamvct.cpp +++ b/storage/connect/filamvct.cpp @@ -440,6 +440,7 @@ bool VCTFAM::OpenTableFile(PGLOBAL g) } // endif // Selective delete, pass thru + /* fall through */ case MODE_UPDATE: UseTemp = Tdbp->IsUsingTemp(g); strcpy(opmode, (UseTemp) ? "rb" : "r+b"); @@ -1918,6 +1919,7 @@ bool VECFAM::OpenTableFile(PGLOBAL g) } // endif filter // Selective delete, pass thru + /* fall through */ case MODE_UPDATE: UseTemp = Tdbp->IsUsingTemp(g); strcpy(opmode, (UseTemp) ? "rb": "r+b"); @@ -3584,6 +3586,7 @@ bool BGVFAM::OpenTableFile(PGLOBAL g) } // endif // Selective delete, pass thru + /* fall through */ case MODE_UPDATE: UseTemp = Tdbp->IsUsingTemp(g); oflag = (UseTemp) ? O_RDONLY : O_RDWR; diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp index 262d6b58a70..35840e9b5e3 100644 --- a/storage/connect/filter.cpp +++ b/storage/connect/filter.cpp @@ -1193,7 +1193,7 @@ bool FILTER::Convert(PGLOBAL g, bool having) Arg(0) = pXVOID; } // endif void - // pass thru + // fall through case OP_IN: // For IN operator do optimize if operand is an array if (GetArgType(1) != TYPE_ARRAY) @@ -1260,6 +1260,7 @@ bool FILTER::Eval(PGLOBAL g) } // endif Opm // For modified operators, pass thru + /* fall through */ case OP_IN: case OP_EXIST: // For IN operations, special processing is done here diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 1f2bd0e5992..e646069c219 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1427,7 +1427,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VAR_STRING: pcf->Flags |= U_VAR; - /* no break */ + /* fall through */ default: pcf->Type= MYSQLtoPLG(fp->type(), &v); break; @@ -2801,6 +2801,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) case Item_func::LIKE_FUNC: vop= OP_LIKE; break; case Item_func::ISNOTNULL_FUNC: neg = true; + /* fall through */ case Item_func::ISNULL_FUNC: vop= OP_NULL; break; case Item_func::IN_FUNC: vop= OP_IN; case Item_func::BETWEEN: @@ -4220,7 +4221,8 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick) } else return false; - /* Fall through to check FILE_ACL */ + /* check FILE_ACL */ + /* fall through */ case TAB_ODBC: case TAB_JDBC: case TAB_MYSQL: @@ -5454,7 +5456,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif // JDBC_SUPPORT case TAB_DBF: dbf= true; - // Passthru + // fall through case TAB_CSV: if (!fn && fnc != FNC_NO) sprintf(g->Message, "Missing %s file name", topt->type); diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index b473871e9f7..6904295066f 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -533,7 +533,7 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src) if (!has_e) goto err; - // passthru + // fall through case '-': if (found_digit) goto err; @@ -826,7 +826,7 @@ bool JOUTSTR::Escape(const char *s) case '\r': case '\b': case '\f': WriteChr('\\'); - // passthru + // fall through default: WriteChr(s[i]); break; diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 1910cdcdec8..52c6058393f 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -917,7 +917,7 @@ int PlugCloseFile(PGLOBAL g __attribute__((unused)), PFBLOCK fp, bool all) fp->Memory = NULL; fp->Mode = MODE_ANY; - // Passthru + // fall through case TYPE_FB_HANDLE: if (fp->Handle && fp->Handle != INVALID_HANDLE_VALUE) if (CloseFileHandle(fp->Handle)) diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 5bb7848ab1c..0bb7adcce83 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -128,6 +128,7 @@ int RELDEF::GetSizeCatInfo(PSZ what, PSZ sdef) switch (toupper(c)) { case 'M': n *= 1024; + // fall through case 'K': n *= 1024; } // endswitch c diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index d2bb3d7a4af..2da92741e4f 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -1307,6 +1307,7 @@ PBF TDBDOS::InitBlockFilter(PGLOBAL g, PFIL filp) } // endif !opm // if opm, pass thru + /* fall through */ case OP_IN: if (filp->GetArgType(0) == TYPE_COLBLK && filp->GetArgType(1) == TYPE_ARRAY) { diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 1e11d454cfc..2addcc139fb 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1530,7 +1530,7 @@ void JSONCOL::WriteColumn(PGLOBAL g) break; } // endif Op - // Passthru + // fall through case TYPE_DATE: case TYPE_INT: case TYPE_SHORT: diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index ced690e77c0..7660ee0a630 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -118,7 +118,7 @@ ulonglong CharToNumber(char *p, int n, ulonglong maxval, maxval++; if (minus) *minus = true; } // endif Unsigned - + /* fall through */ case '+': p++; break; diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index 15fb71ab88a..ae210cb900c 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -464,7 +464,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp) if (ApplyFilter(g, filp)) break; - // passthru + // fall through case RC_NF: continue; case RC_EF: diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp index a0b7849543d..746de097918 100644 --- a/storage/connect/xobject.cpp +++ b/storage/connect/xobject.cpp @@ -405,7 +405,7 @@ bool STRING::Append_quoted(PSZ s) case '\r': case '\b': case '\f': b |= Append('\\'); - // passthru + // fall through default: b |= Append(*p); break; diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 97baa27aba6..927921d6df4 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2004, 2015, Oracle and/or its affiliates. + 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 @@ -2952,6 +2953,7 @@ int ha_federated::extra(ha_extra_function operation) break; case HA_EXTRA_PREPARE_FOR_DROP: table_will_be_deleted = TRUE; + break; default: /* do nothing */ DBUG_PRINT("info",("unhandled operation: %d", (uint) operation)); diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c index a68a35e63fb..d03c7c46f15 100644 --- a/storage/heap/hp_create.c +++ b/storage/heap/hp_create.c @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2010, 2014, SkySQL Ab. + Copyright (c) 2010, 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 @@ -94,7 +94,7 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info, case HA_KEYTYPE_VARBINARY1: /* Case-insensitiveness is handled in coll->hash_sort */ keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1; - /* fall_through */ + /* fall through */ case HA_KEYTYPE_VARTEXT1: keyinfo->flag|= HA_VAR_LENGTH_KEY; length+= 2; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1538471db4f..dac70203ee4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7063,8 +7063,8 @@ ha_innobase::innobase_lock_autoinc(void) break; } } - /* Fall through to old style locking. */ - + /* Use old style locking. */ + /* fall through */ case AUTOINC_OLD_STYLE_LOCKING: DBUG_EXECUTE_IF("die_if_autoinc_old_lock_style_used", ut_ad(0);); @@ -9725,7 +9725,8 @@ create_options_are_invalid( case ROW_TYPE_DYNAMIC: CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE(use_tablespace); CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE; - /* fall through since dynamic also shuns KBS */ + /* ROW_FORMAT=DYNAMIC also shuns KEY_BLOCK_SIZE */ + /* fall through */ case ROW_TYPE_COMPACT: case ROW_TYPE_REDUNDANT: if (kbs_specified) { @@ -10111,7 +10112,8 @@ index_bad: break; } zip_allowed = FALSE; - /* fall through to set row_format = COMPACT */ + /* Set ROW_FORMAT = COMPACT */ + /* fall through */ case ROW_TYPE_NOT_USED: case ROW_TYPE_FIXED: case ROW_TYPE_PAGE: @@ -10119,6 +10121,7 @@ index_bad: thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: assuming ROW_FORMAT=COMPACT."); + /* fall through */ case ROW_TYPE_DEFAULT: /* If we fell through, set row format to Compact. */ row_format = ROW_TYPE_COMPACT; diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index d489bef89a8..b4dbf4b1213 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -574,7 +575,8 @@ dtype_get_fixed_size_low( #else /* !UNIV_HOTBACKUP */ return(len); #endif /* !UNIV_HOTBACKUP */ - /* fall through for variable-length charsets */ + /* Treat as variable-length. */ + /* Fall through */ case DATA_VARCHAR: case DATA_BINARY: case DATA_DECIMAL: diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic index 6b303979b18..9a8441280a6 100644 --- a/storage/innobase/include/mach0data.ic +++ b/storage/innobase/include/mach0data.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -787,13 +788,13 @@ mach_swap_byte_order( dest += len; switch (len & 0x7) { - case 0: *--dest = *from++; - case 7: *--dest = *from++; - case 6: *--dest = *from++; - case 5: *--dest = *from++; - case 4: *--dest = *from++; - case 3: *--dest = *from++; - case 2: *--dest = *from++; + case 0: *--dest = *from++; /* fall through */ + case 7: *--dest = *from++; /* fall through */ + case 6: *--dest = *from++; /* fall through */ + case 5: *--dest = *from++; /* fall through */ + case 4: *--dest = *from++; /* fall through */ + case 3: *--dest = *from++; /* fall through */ + case 2: *--dest = *from++; /* fall through */ case 1: *--dest = *from; } } diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic index 024c59e553b..987dfac03c1 100644 --- a/storage/innobase/include/ut0rnd.ic +++ b/storage/innobase/include/ut0rnd.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -237,16 +238,22 @@ ut_fold_binary( switch (len & 0x7) { case 7: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 6: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 5: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 4: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 3: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 2: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 1: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index da8e1aab2c9..1337496b897 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2018,6 +2018,7 @@ PageConverter::update_page( case FIL_PAGE_TYPE_XDES: err = set_current_xdes( buf_block_get_page_no(block), get_frame(block)); + /* fall through */ case FIL_PAGE_INODE: case FIL_PAGE_TYPE_TRX_SYS: case FIL_PAGE_IBUF_FREE_LIST: diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 77cca37ddd1..3a49f033c9c 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1872,6 +1873,7 @@ row_log_table_apply_update( When applying the subsequent ROW_T_DELETE, no matching record will be found. */ + /* fall through */ case DB_SUCCESS: ut_ad(row != NULL); break; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index a3f4355ec6c..69d77060bd8 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -5407,7 +5407,8 @@ loop: fputs(" InnoDB: Warning: CHECK TABLE on ", stderr); dict_index_name_print(stderr, prebuilt->trx, index); fprintf(stderr, " returned %lu\n", ret); - /* fall through (this error is ignored by CHECK TABLE) */ + /* (this error is ignored by CHECK TABLE) */ + /* fall through */ case DB_END_OF_INDEX: func_exit: mem_free(buf); diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index bc2e0b0e1cb..bb883310820 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -488,8 +489,9 @@ row_purge_remove_sec_if_poss_leaf( success = false; } } - /* fall through (the index entry is still needed, + /* (The index entry is still needed, or the deletion succeeded) */ + /* fall through */ case ROW_NOT_DELETED_REF: /* The index entry is still needed. */ case ROW_BUFFERED: diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index a2165a917b8..855fd5dec11 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -1123,6 +1123,7 @@ sync_thread_add_level( upgrading in innobase_start_or_create_for_mysql(). */ break; } + /* fall through */ case SYNC_MEM_POOL: case SYNC_MEM_HASH: case SYNC_RECV: diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index fd21d2863f8..c6f53eaa24b 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -157,6 +157,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, if (info->s->data_file_type != DYNAMIC_RECORD) break; /* Remove read/write cache if dynamic rows */ + /* fall through */ case HA_EXTRA_NO_CACHE: if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) { @@ -313,7 +314,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, share->state.open_count= 1; share->changed= 1; _ma_mark_file_changed_now(share); - /* Fall trough */ + /* Fall through */ case HA_EXTRA_PREPARE_FOR_RENAME: { my_bool do_flush= MY_TEST(function != HA_EXTRA_PREPARE_FOR_DROP); diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 59e0630be8c..a09662544a2 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -3061,7 +3061,7 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const case LOGREC_REDO_INDEX: case LOGREC_REDO_INDEX_FREE_PAGE: index_page_redo_entry= 1; - /* Fall trough*/ + /* Fall through */ case LOGREC_REDO_INSERT_ROW_HEAD: case LOGREC_REDO_INSERT_ROW_TAIL: case LOGREC_REDO_PURGE_ROW_HEAD: diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index a47c1987e38..04e32378fd3 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -150,6 +150,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) if (info->s->data_file_type != DYNAMIC_RECORD) break; /* Remove read/write cache if dynamic rows */ + /* fall through */ case HA_EXTRA_NO_CACHE: if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) { @@ -262,7 +263,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) //share->deleting= TRUE; share->global_changed= FALSE; /* force writing changed flag */ _mi_mark_file_changed(info); - /* Fall trough */ + /* Fall through */ case HA_EXTRA_PREPARE_FOR_RENAME: mysql_mutex_lock(&THR_LOCK_myisam); share->last_version= 0L; /* Impossible version */ diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index c29172a474a..495420dad32 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -1844,8 +1844,8 @@ int spider_db_append_key_where_internal( #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000 case HA_READ_PREFIX_LAST: result_list->desc_flg = TRUE; - /* fall through */ #endif + /* fall through */ case HA_READ_KEY_EXACT: if (sql_kind == SPIDER_SQL_KIND_SQL) { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 6c390328258..2c6f844d026 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -7749,8 +7749,8 @@ ha_innobase::innobase_lock_autoinc(void) break; } } - /* Fall through to old style locking. */ - + /* Use old style locking. */ + /* fall through */ case AUTOINC_OLD_STYLE_LOCKING: DBUG_EXECUTE_IF("die_if_autoinc_old_lock_style_used", ut_ad(0);); @@ -10473,7 +10473,8 @@ create_options_are_invalid( case ROW_TYPE_DYNAMIC: CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE(use_tablespace); CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE; - /* fall through since dynamic also shuns KBS */ + /* ROW_FORMAT=DYNAMIC also shuns KEY_BLOCK_SIZE */ + /* fall through */ case ROW_TYPE_COMPACT: case ROW_TYPE_REDUNDANT: if (kbs_specified) { @@ -10855,7 +10856,8 @@ index_bad: break; } zip_allowed = FALSE; - /* fall through to set row_format = COMPACT */ + /* Set ROW_FORMAT = COMPACT */ + /* fall through */ case ROW_TYPE_NOT_USED: case ROW_TYPE_FIXED: case ROW_TYPE_PAGE: @@ -10864,6 +10866,7 @@ index_bad: thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: assuming ROW_FORMAT=COMPACT."); + /* fall through */ case ROW_TYPE_DEFAULT: /* If we fell through, set row format to Compact. */ row_format = ROW_TYPE_COMPACT; diff --git a/storage/xtradb/include/data0type.ic b/storage/xtradb/include/data0type.ic index 555852474aa..8f5cee0fd5f 100644 --- a/storage/xtradb/include/data0type.ic +++ b/storage/xtradb/include/data0type.ic @@ -576,7 +576,8 @@ dtype_get_fixed_size_low( #else /* !UNIV_HOTBACKUP */ return(len); #endif /* !UNIV_HOTBACKUP */ - /* fall through for variable-length charsets */ + /* Treat as variable-length. */ + /* Fall through */ case DATA_VARCHAR: case DATA_BINARY: case DATA_DECIMAL: diff --git a/storage/xtradb/include/mach0data.ic b/storage/xtradb/include/mach0data.ic index 4b9275cc12c..26d6c879c9b 100644 --- a/storage/xtradb/include/mach0data.ic +++ b/storage/xtradb/include/mach0data.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -779,13 +780,13 @@ mach_swap_byte_order( dest += len; switch (len & 0x7) { - case 0: *--dest = *from++; - case 7: *--dest = *from++; - case 6: *--dest = *from++; - case 5: *--dest = *from++; - case 4: *--dest = *from++; - case 3: *--dest = *from++; - case 2: *--dest = *from++; + case 0: *--dest = *from++; /* fall through */ + case 7: *--dest = *from++; /* fall through */ + case 6: *--dest = *from++; /* fall through */ + case 5: *--dest = *from++; /* fall through */ + case 4: *--dest = *from++; /* fall through */ + case 3: *--dest = *from++; /* fall through */ + case 2: *--dest = *from++; /* fall through */ case 1: *--dest = *from; } } diff --git a/storage/xtradb/include/ut0rnd.ic b/storage/xtradb/include/ut0rnd.ic index 024c59e553b..987dfac03c1 100644 --- a/storage/xtradb/include/ut0rnd.ic +++ b/storage/xtradb/include/ut0rnd.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -237,16 +238,22 @@ ut_fold_binary( switch (len & 0x7) { case 7: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 6: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 5: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 4: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 3: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 2: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + /* fall through */ case 1: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); } diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index 23b9ba60269..bc7b5206a64 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -2018,6 +2018,7 @@ PageConverter::update_page( case FIL_PAGE_TYPE_XDES: err = set_current_xdes( buf_block_get_page_no(block), get_frame(block)); + /* fall through */ case FIL_PAGE_INODE: case FIL_PAGE_TYPE_TRX_SYS: case FIL_PAGE_IBUF_FREE_LIST: diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 3c5d5773aee..bc40a8f7c05 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/row/row0log.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1872,6 +1873,7 @@ row_log_table_apply_update( When applying the subsequent ROW_T_DELETE, no matching record will be found. */ + /* fall through */ case DB_SUCCESS: ut_ad(row != NULL); break; diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index c0c2b6fbabe..eca26ce9763 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -5421,7 +5421,8 @@ loop: fputs(" InnoDB: Warning: CHECK TABLE on ", stderr); dict_index_name_print(stderr, prebuilt->trx, index); fprintf(stderr, " returned %lu\n", ret); - /* fall through (this error is ignored by CHECK TABLE) */ + /* (this error is ignored by CHECK TABLE) */ + /* fall through */ case DB_END_OF_INDEX: func_exit: mem_free(buf); diff --git a/storage/xtradb/row/row0purge.cc b/storage/xtradb/row/row0purge.cc index 35b3520749b..d1a7ac2036e 100644 --- a/storage/xtradb/row/row0purge.cc +++ b/storage/xtradb/row/row0purge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -488,8 +489,9 @@ row_purge_remove_sec_if_poss_leaf( success = false; } } - /* fall through (the index entry is still needed, + /* (The index entry is still needed, or the deletion succeeded) */ + /* fall through */ case ROW_NOT_DELETED_REF: /* The index entry is still needed. */ case ROW_BUFFERED: diff --git a/storage/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc index c270b73e5a0..48cfbf4d6c3 100644 --- a/storage/xtradb/sync/sync0sync.cc +++ b/storage/xtradb/sync/sync0sync.cc @@ -1220,6 +1220,7 @@ sync_thread_add_level( upgrading in innobase_start_or_create_for_mysql(). */ break; } + /* fall through */ case SYNC_MEM_POOL: case SYNC_MEM_HASH: case SYNC_RECV: @@ -1282,9 +1283,9 @@ sync_thread_add_level( } } ut_ad(found_current); - - /* fallthrough */ } + + /* fall through */ case SYNC_BUF_FLUSH_LIST: case SYNC_BUF_LRU_LIST: case SYNC_BUF_FREE_LIST: diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index b4fc6297afd..f32150efa40 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2016, MariaDB + Copyright (c) 2009, 2017, MariaDB This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -5031,7 +5031,9 @@ static int my_uni_utf8_no_range(CHARSET_INFO *cs __attribute__((unused)), { /* Fall through all cases!!! */ case 3: r[2]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x800; + /* fall through */ case 2: r[1]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0xc0; + /* fall through */ case 1: r[0]= (uchar) wc; } return count; @@ -7509,8 +7511,11 @@ my_wc_mb_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), switch (count) { /* Fall through all cases!!! */ case 4: r[3] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x10000; + /* fall through */ case 3: r[2] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x800; + /* fall through */ case 2: r[1] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0xc0; + /* fall through */ case 1: r[0] = (uchar) wc; } return count; @@ -7541,8 +7546,11 @@ my_wc_mb_utf8mb4_no_range(CHARSET_INFO *cs __attribute__((unused)), { /* Fall through all cases!!! */ case 4: r[3]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x10000; + /* fall through */ case 3: r[2]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x800; + /* fall through */ case 2: r[1]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0xc0; + /* fall through */ case 1: r[0]= (uchar) wc; } return count; diff --git a/strings/dtoa.c b/strings/dtoa.c index c3ab347f94c..e66db5fed3d 100644 --- a/strings/dtoa.c +++ b/strings/dtoa.c @@ -1,4 +1,5 @@ /* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, MariaDB Corporation. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -1377,7 +1378,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s switch (*s) { case '-': sign= 1; - /* no break */ + /* fall through */ case '+': s++; goto break2; @@ -1467,6 +1468,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s switch (c= *s) { case '-': esign= 1; + /* fall through */ case '+': c= *++s; } @@ -2360,7 +2362,7 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, break; case 2: leftright= 0; - /* no break */ + /* fall through */ case 4: if (ndigits <= 0) ndigits= 1; @@ -2368,7 +2370,7 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, break; case 3: leftright= 0; - /* no break */ + /* fall through */ case 5: i= ndigits + k + 1; ilim= i; From 4754f88cff3aa40706740c5656f97ff56d1f5c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 16 May 2017 17:45:22 +0300 Subject: [PATCH 123/148] Never pass NULL to innobase_get_stmt() --- storage/innobase/handler/ha_innodb.cc | 10 +++------- storage/innobase/lock/lock0lock.cc | 12 +++++------- storage/innobase/trx/trx0i_s.cc | 4 +++- storage/xtradb/handler/ha_innodb.cc | 10 +++------- storage/xtradb/lock/lock0lock.cc | 12 +++++------- storage/xtradb/trx/trx0i_s.cc | 4 +++- 6 files changed, 22 insertions(+), 30 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index dac70203ee4..26c9d0321d4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1998,15 +1998,11 @@ innobase_get_stmt( THD* thd, /*!< in: MySQL thread handle */ size_t* length) /*!< out: length of the SQL statement */ { - const char* query = NULL; - LEX_STRING *stmt = NULL; - ut_ad(thd != NULL); - stmt = thd_query_string(thd); - if (stmt) { + if (const LEX_STRING *stmt = thd_query_string(thd)) { *length = stmt->length; - query = stmt->str; + return stmt->str; } - return (query); + return NULL; } /**********************************************************************//** diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 0a75389094d..869de0be182 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4742,13 +4742,11 @@ lock_rec_unlock( trx_mutex_exit(trx); stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: unlock row could not" - " find a %lu mode lock on the record\n", - (ulong) lock_mode); - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: current statement: %.*s\n", + + ib_logf(IB_LOG_LEVEL_ERROR, + "unlock row could not find a %u mode lock on the record;" + " statement=%.*s", + lock_mode, (int) stmt_len, stmt); return; diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index 993006efc6d..b05161a9932 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -503,7 +503,9 @@ fill_trx_row( row->trx_mysql_thread_id = thd_get_thread_id(trx->mysql_thd); - stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len); + stmt = trx->mysql_thd + ? innobase_get_stmt(trx->mysql_thd, &stmt_len) + : NULL; if (stmt != NULL) { char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1]; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 2c6f844d026..c1b9f59fea4 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -2324,15 +2324,11 @@ innobase_get_stmt( THD* thd, /*!< in: MySQL thread handle */ size_t* length) /*!< out: length of the SQL statement */ { - const char* query = NULL; - LEX_STRING *stmt = NULL; - ut_ad(thd != NULL); - stmt = thd_query_string(thd); - if (stmt) { + if (const LEX_STRING *stmt = thd_query_string(thd)) { *length = stmt->length; - query = stmt->str; + return stmt->str; } - return (query); + return NULL; } /**********************************************************************//** diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index ffbb1601ca5..e570f7ed494 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -4788,13 +4788,11 @@ lock_rec_unlock( trx_mutex_exit(trx); stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: unlock row could not" - " find a %lu mode lock on the record\n", - (ulong) lock_mode); - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: current statement: %.*s\n", + + ib_logf(IB_LOG_LEVEL_ERROR, + "unlock row could not find a %u mode lock on the record;" + " statement=%.*s", + lock_mode, (int) stmt_len, stmt); return; diff --git a/storage/xtradb/trx/trx0i_s.cc b/storage/xtradb/trx/trx0i_s.cc index eacd9212d2f..0c9618d98eb 100644 --- a/storage/xtradb/trx/trx0i_s.cc +++ b/storage/xtradb/trx/trx0i_s.cc @@ -507,7 +507,9 @@ fill_trx_row( row->trx_mysql_thread_id = thd_get_thread_id(trx->mysql_thd); - stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len); + stmt = trx->mysql_thd + ? innobase_get_stmt(trx->mysql_thd, &stmt_len) + : NULL; if (stmt != NULL) { char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1]; From 956d2540c456059db85af860ce5cf47e5a5dd796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 May 2017 10:27:01 +0300 Subject: [PATCH 124/148] Remove redundant UT_LIST_INIT() calls The macro UT_LIST_INIT() zero-initializes the UT_LIST_NODE. There is no need to call this macro on a buffer that has already been zero-initialized by mem_zalloc() or mem_heap_zalloc() or similar. For some reason, the statement UT_LIST_INIT(srv_sys->tasks) in srv_init() caused a SIGSEGV on server startup when compiling with GCC 7.1.0 for AMD64 using -O3. The zero-initialization was attempted by the instruction movaps %xmm0,0x50(%rax), while the proper offset of srv_sys->tasks would seem to have been 0x48. --- storage/innobase/buf/buf0buf.cc | 3 +-- storage/innobase/fil/fil0fil.cc | 4 +--- storage/innobase/row/row0ftsort.cc | 4 +--- storage/innobase/srv/srv0srv.cc | 2 -- storage/innobase/usr/usr0sess.cc | 3 +-- storage/xtradb/buf/buf0buf.cc | 3 +-- storage/xtradb/fil/fil0fil.cc | 4 +--- storage/xtradb/row/row0ftsort.cc | 4 +--- storage/xtradb/srv/srv0srv.cc | 2 -- storage/xtradb/usr/usr0sess.cc | 3 +-- 10 files changed, 8 insertions(+), 24 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 0b305507271..83102ab1616 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2,6 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1343,8 +1344,6 @@ buf_pool_init_instance( buf_pool->chunks = chunk = (buf_chunk_t*) mem_zalloc(sizeof *chunk); - UT_LIST_INIT(buf_pool->free); - if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) { mem_free(chunk); mem_free(buf_pool); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 72ee8d74a82..36179960054 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2014, 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 @@ -1546,8 +1546,6 @@ fil_init( fil_system->spaces = hash_create(hash_size); fil_system->name_hash = hash_create(hash_size); - UT_LIST_INIT(fil_system->LRU); - fil_system->max_n_open = max_n_open; } diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 5b8ed009a2a..db570467414 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -225,9 +226,6 @@ row_fts_psort_info_init( each parallel sort thread. Each "sort bucket" holds records for a particular "FTS index partition" */ for (j = 0; j < fts_sort_pll_degree; j++) { - - UT_LIST_INIT(psort_info[j].fts_doc_list); - for (i = 0; i < FTS_NUM_AUX_INDEX; i++) { psort_info[j].merge_file[i] = diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 067e32a83aa..7beacc76615 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1011,8 +1011,6 @@ srv_init(void) srv_monitor_event = os_event_create(); srv_buf_dump_event = os_event_create(); - - UT_LIST_INIT(srv_sys->tasks); } /* page_zip_stat_per_index_mutex is acquired from: diff --git a/storage/innobase/usr/usr0sess.cc b/storage/innobase/usr/usr0sess.cc index ab7ba6bea09..e1bd71ff1a0 100644 --- a/storage/innobase/usr/usr0sess.cc +++ b/storage/innobase/usr/usr0sess.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -48,8 +49,6 @@ sess_open(void) sess->trx = trx_allocate_for_background(); sess->trx->sess = sess; - UT_LIST_INIT(sess->graphs); - return(sess); } diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 07b84c60c76..2785a2a33df 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -2,6 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1432,8 +1433,6 @@ buf_pool_init_instance( buf_pool->chunks = chunk = (buf_chunk_t*) mem_zalloc(sizeof *chunk); - UT_LIST_INIT(buf_pool->free); - if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) { mem_free(chunk); mem_free(buf_pool); diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 1a866a693ca..d528164c6f4 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2014, 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 @@ -1598,8 +1598,6 @@ fil_init( fil_system->spaces = hash_create(hash_size); fil_system->name_hash = hash_create(hash_size); - UT_LIST_INIT(fil_system->LRU); - fil_system->max_n_open = max_n_open; } diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc index 13877b8fe08..734b4f8b2f7 100644 --- a/storage/xtradb/row/row0ftsort.cc +++ b/storage/xtradb/row/row0ftsort.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -228,9 +229,6 @@ row_fts_psort_info_init( each parallel sort thread. Each "sort bucket" holds records for a particular "FTS index partition" */ for (j = 0; j < fts_sort_pll_degree; j++) { - - UT_LIST_INIT(psort_info[j].fts_doc_list); - for (i = 0; i < FTS_NUM_AUX_INDEX; i++) { psort_info[j].merge_file[i] = diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 5b3f86d8641..22a96b7446a 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -1164,8 +1164,6 @@ srv_init(void) if (srv_track_changed_pages) { os_event_set(srv_redo_log_tracked_event); } - - UT_LIST_INIT(srv_sys->tasks); } /* page_zip_stat_per_index_mutex is acquired from: diff --git a/storage/xtradb/usr/usr0sess.cc b/storage/xtradb/usr/usr0sess.cc index ab7ba6bea09..e1bd71ff1a0 100644 --- a/storage/xtradb/usr/usr0sess.cc +++ b/storage/xtradb/usr/usr0sess.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -48,8 +49,6 @@ sess_open(void) sess->trx = trx_allocate_for_background(); sess->trx->sess = sess; - UT_LIST_INIT(sess->graphs); - return(sess); } From 5064623ce4f721d7b3286296f7cd08e6eb8091b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Wed, 17 May 2017 12:13:09 +0300 Subject: [PATCH 125/148] Revert "Fix unit test after merge from mysql 5.5.35 perfschema" This reverts commit 4799af092574e7957d7143c7751acef74a95a495. Upstream provided adequate fix. This commit is no longer necessary. --- storage/perfschema/unittest/pfs-t.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/perfschema/unittest/pfs-t.cc b/storage/perfschema/unittest/pfs-t.cc index 7883e8070fe..209c4d1ca88 100644 --- a/storage/perfschema/unittest/pfs-t.cc +++ b/storage/perfschema/unittest/pfs-t.cc @@ -1339,7 +1339,6 @@ void test_locker_disabled() /* Pretend the socket does not have a thread owner */ /* ---------------------------------------------- */ - psi->delete_current_thread(); socket_class_A->m_enabled= true; socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 != NULL, "instrumented"); From e22d86a3eb843bbf1664fc4ff8d112416d0eacd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 May 2017 13:49:51 +0300 Subject: [PATCH 126/148] fil_create_new_single_table_tablespace(): Correct a bogus nonnull attribute The parameter path can be passed as NULL. This error was reported by GCC 7.1.0 when compiling CMAKE_BUILD_TYPE=Debug with -O3. --- storage/innobase/fil/fil0fil.cc | 4 +--- storage/innobase/include/fil0fil.h | 4 ++-- storage/xtradb/fil/fil0fil.cc | 4 +--- storage/xtradb/include/fil0fil.h | 4 ++-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 36179960054..a573c6eb4ef 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -2271,14 +2271,12 @@ fil_op_log_parse_or_replay( } else if (log_flags & MLOG_FILE_FLAG_TEMP) { /* Temporary table, do nothing */ } else { - const char* path = NULL; - /* Create the database directory for name, if it does not exist yet */ fil_create_directory_for_tablename(name); if (fil_create_new_single_table_tablespace( - space_id, name, path, flags, + space_id, name, NULL, flags, DICT_TF2_USE_TABLESPACE, FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) { ut_error; diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index f29d1bf3408..d45e14a83de 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -782,7 +782,7 @@ fil_create_new_single_table_tablespace( ulint size) /*!< in: the initial size of the tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + MY_ATTRIBUTE((nonnull(2), warn_unused_result)); #ifndef UNIV_HOTBACKUP /********************************************************************//** Tries to open a single-table tablespace and optionally checks the space id is diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index d528164c6f4..ea984543150 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -2323,14 +2323,12 @@ fil_op_log_parse_or_replay( } else if (log_flags & MLOG_FILE_FLAG_TEMP) { /* Temporary table, do nothing */ } else { - const char* path = NULL; - /* Create the database directory for name, if it does not exist yet */ fil_create_directory_for_tablename(name); if (fil_create_new_single_table_tablespace( - space_id, name, path, flags, + space_id, name, NULL, flags, DICT_TF2_USE_TABLESPACE, FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) { ut_error; diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 3023b29b793..58bc5322cd9 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -778,7 +778,7 @@ fil_create_new_single_table_tablespace( ulint size) /*!< in: the initial size of the tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + MY_ATTRIBUTE((nonnull(2), warn_unused_result)); #ifndef UNIV_HOTBACKUP /********************************************************************//** Tries to open a single-table tablespace and optionally checks the space id is From 5fe55b1b0251a894d87488d7dc973b044af12736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Wed, 17 May 2017 15:44:11 +0300 Subject: [PATCH 127/148] Fix sys_vars innodb_empty_free_list_algorithm_basic Post xtradb 5.6.36 merge the output has changed. --- .../sys_vars/r/innodb_empty_free_list_algorithm_basic.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result b/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result index f95553e3fa2..771c6e917ac 100644 --- a/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result @@ -1,7 +1,7 @@ SET @start_value = @@GLOBAL.innodb_empty_free_list_algorithm; SELECT @@GLOBAL.innodb_empty_free_list_algorithm; @@GLOBAL.innodb_empty_free_list_algorithm -backoff +legacy SELECT @@SESSION.innodb_empty_free_list_algorithm; ERROR HY000: Variable 'innodb_empty_free_list_algorithm' is a GLOBAL variable SET GLOBAL innodb_empty_free_list_algorithm='legacy'; From 9f89b94ba6d69f896b2af3e84a9b420131c530d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 May 2017 14:08:08 +0300 Subject: [PATCH 128/148] MDEV-12358 Work around what looks like a bug in GCC 7.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parameter thr of the function btr_cur_optimistic_insert() is not declared as nonnull, but GCC 7.1.0 with -O3 is wrongly optimizing away the first part of the condition UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes) when the function is being called by row_merge_insert_index_tuples() with thr==NULL. The fake_changes is an XtraDB addition. This GCC bug only appears to have an impact on XtraDB, not InnoDB. We work around the problem by not attempting to dereference thr when both BTR_NO_LOCKING_FLAG and BTR_NO_UNDO_LOG_FLAG are set in the flags. Probably BTR_NO_LOCKING_FLAG alone should suffice. btr_cur_optimistic_insert(), btr_cur_pessimistic_insert(), btr_cur_pessimistic_update(): Correct comments that disagree with usage and with nonnull attributes. No other parameter than thr can actually be NULL. row_ins_duplicate_error_in_clust(): Remove an unused parameter. innobase_is_fake_change(): Unused function; remove. ibuf_insert_low(), row_log_table_apply(), row_log_apply(), row_undo_mod_clust_low(): Because we will be passing BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG in the flags, the trx->fake_changes flag will be treated as false, which is the right thing to do at these low-level operations (change buffer merge, ALTER TABLE…LOCK=NONE, or ROLLBACK). This might be fixing actual XtraDB bugs. Other callers that pass these two flags are also passing thr=NULL, implying fake_changes=false. (Some callers in ROLLBACK are passing BTR_NO_LOCKING_FLAG and a nonnull thr. In these callers, fake_changes better be false, to avoid corruption.) --- storage/innobase/btr/btr0cur.cc | 27 ++++++++++------- storage/innobase/ibuf/ibuf0ibuf.cc | 3 +- storage/innobase/include/btr0cur.h | 25 +++++++++------- storage/innobase/row/row0ins.cc | 9 ++---- storage/xtradb/btr/btr0cur.cc | 45 +++++++++++++++++++---------- storage/xtradb/handler/ha_innodb.cc | 27 ----------------- storage/xtradb/ibuf/ibuf0ibuf.cc | 3 +- storage/xtradb/include/btr0cur.h | 25 +++++++++------- storage/xtradb/row/row0ins.cc | 9 ++---- 9 files changed, 86 insertions(+), 87 deletions(-) diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 4f24ad75e26..7846debc115 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3,6 +3,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1223,15 +1224,17 @@ btr_cur_optimistic_insert( btr_cur_t* cursor, /*!< in: cursor on page after which to insert; cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ - mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ + mem_heap_t** heap, /*!< in/out: pointer to memory heap */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction; if this function returns DB_SUCCESS on a leaf page of a secondary index in a @@ -1252,6 +1255,7 @@ btr_cur_optimistic_insert( ulint rec_size; dberr_t err; + ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG))); *big_rec = NULL; block = btr_cur_get_block(cursor); @@ -1510,15 +1514,17 @@ btr_cur_pessimistic_insert( cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction */ { dict_index_t* index = cursor->index; @@ -1530,6 +1536,7 @@ btr_cur_pessimistic_insert( ulint n_reserved = 0; ut_ad(dtuple_check_typed(entry)); + ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG))); *big_rec = NULL; @@ -2426,12 +2433,12 @@ btr_cur_pessimistic_update( ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ mem_heap_t** offsets_heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ mem_heap_t* entry_heap, /*!< in/out: memory heap for allocating big_rec and the index tuple */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or NULL */ + be stored externally by the caller */ const upd_t* update, /*!< in: update vector; this is allowed also contain trx id and roll ptr fields, but the values in update vector have no effect */ diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 373c68503d7..55429e3cf34 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -3662,7 +3663,7 @@ fail_exit: if (mode == BTR_MODIFY_PREV) { err = btr_cur_optimistic_insert( - BTR_NO_LOCKING_FLAG, + BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG, cursor, &offsets, &offsets_heap, ibuf_entry, &ins_rec, &dummy_big_rec, 0, thr, &mtr); diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 28e01d4f02e..77de98d5812 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -220,15 +221,17 @@ btr_cur_optimistic_insert( btr_cur_t* cursor, /*!< in: cursor on page after which to insert; cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ - mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ + mem_heap_t** heap, /*!< in/out: pointer to memory heap */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction; if this function returns DB_SUCCESS on a leaf page of a secondary index in a @@ -256,15 +259,17 @@ btr_cur_pessimistic_insert( cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((nonnull(2,3,4,5,6,7,10), warn_unused_result)); /*************************************************************//** @@ -390,12 +395,12 @@ btr_cur_pessimistic_update( ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ mem_heap_t** offsets_heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ mem_heap_t* entry_heap, /*!< in/out: memory heap for allocating big_rec and the index tuple */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or NULL */ + be stored externally by the caller */ const upd_t* update, /*!< in: update vector; this is allowed also contain trx id and roll ptr fields, but the values in update vector have no effect */ diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 9c1b5cb2d09..5cfa21c1fa2 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -2121,14 +2122,10 @@ for a clustered index! @retval DB_SUCCESS if no error @retval DB_DUPLICATE_KEY if error, @retval DB_LOCK_WAIT if we have to wait for a lock on a possible duplicate -record -@retval DB_SUCCESS_LOCKED_REC if an exact match of the record was found -in online table rebuild (flags & (BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG)) */ +record */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t row_ins_duplicate_error_in_clust( -/*=============================*/ - ulint flags, /*!< in: undo logging and locking flags */ btr_cur_t* cursor, /*!< in: B-tree cursor */ const dtuple_t* entry, /*!< in: entry to insert */ que_thr_t* thr, /*!< in: query thread */ @@ -2386,7 +2383,7 @@ row_ins_clust_index_entry_low( DB_LOCK_WAIT */ err = row_ins_duplicate_error_in_clust( - flags, &cursor, entry, thr, &mtr); + &cursor, entry, thr, &mtr); } if (err != DB_SUCCESS) { diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc index dcb197a761f..0b554b271c4 100644 --- a/storage/xtradb/btr/btr0cur.cc +++ b/storage/xtradb/btr/btr0cur.cc @@ -3,6 +3,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1328,15 +1329,17 @@ btr_cur_optimistic_insert( btr_cur_t* cursor, /*!< in: cursor on page after which to insert; cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ - mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ + mem_heap_t** heap, /*!< in/out: pointer to memory heap */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction; if this function returns DB_SUCCESS on a leaf page of a secondary index in a @@ -1357,6 +1360,7 @@ btr_cur_optimistic_insert( ulint rec_size; dberr_t err; + ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG))); *big_rec = NULL; block = btr_cur_get_block(cursor); @@ -1366,7 +1370,10 @@ btr_cur_optimistic_insert( page = buf_block_get_frame(block); index = cursor->index; - ut_ad((thr && thr_get_trx(thr)->fake_changes) + const bool fake_changes = (~flags & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) + && thr_get_trx(thr)->fake_changes; + ut_ad(fake_changes || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); ut_ad(!dict_index_is_online_ddl(index) || dict_index_is_clust(index) @@ -1507,7 +1514,7 @@ fail_err: goto fail_err; } - if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) { + if (UNIV_UNLIKELY(fake_changes)) { /* skip CHANGE, LOG */ *big_rec = big_rec_vec; return(err); /* == DB_SUCCESS */ @@ -1625,15 +1632,17 @@ btr_cur_pessimistic_insert( cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction */ { dict_index_t* index = cursor->index; @@ -1645,13 +1654,17 @@ btr_cur_pessimistic_insert( ulint n_reserved = 0; ut_ad(dtuple_check_typed(entry)); + ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG))); *big_rec = NULL; - ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, + const bool fake_changes = (~flags & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) + && thr_get_trx(thr)->fake_changes; + ut_ad(fake_changes || mtr_memo_contains(mtr, dict_index_get_lock(btr_cur_get_index(cursor)), MTR_MEMO_X_LOCK)); - ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor), + ut_ad(fake_changes || mtr_memo_contains(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX)); ut_ad(!dict_index_is_online_ddl(index) || dict_index_is_clust(index) @@ -1712,7 +1725,7 @@ btr_cur_pessimistic_insert( } } - if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) { + if (UNIV_UNLIKELY(fake_changes)) { /* skip CHANGE, LOG */ if (n_reserved > 0) { fil_space_release_free_extents(index->space, @@ -1803,7 +1816,7 @@ btr_cur_upd_lock_and_undo( ut_ad((thr != NULL) || (flags & BTR_NO_LOCKING_FLAG)); - if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) { + if (!(flags & BTR_NO_LOCKING_FLAG) && thr_get_trx(thr)->fake_changes) { /* skip LOCK, UNDO */ return(DB_SUCCESS); } @@ -2582,12 +2595,12 @@ btr_cur_pessimistic_update( ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ mem_heap_t** offsets_heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ mem_heap_t* entry_heap, /*!< in/out: memory heap for allocating big_rec and the index tuple */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or NULL */ + be stored externally by the caller */ const upd_t* update, /*!< in: update vector; this is allowed also contain trx id and roll ptr fields, but the values in update vector have no effect */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index c1b9f59fea4..9af3c7272fe 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -769,17 +769,6 @@ innobase_purge_changed_page_bitmaps( ulonglong lsn) __attribute__((unused)); /*!< in: LSN to purge files up to */ -/*****************************************************************//** -Check whether this is a fake change transaction. -@return TRUE if a fake change transaction */ -static -my_bool -innobase_is_fake_change( -/*====================*/ - handlerton *hton, /*!< in: InnoDB handlerton */ - THD* thd) __attribute__((unused)); /*!< in: MySQL thread handle of the user for - whom the transaction is being committed */ - /** Get the list of foreign keys referencing a specified table table. @param thd The thread handle @@ -4242,22 +4231,6 @@ innobase_purge_changed_page_bitmaps( return (my_bool)log_online_purge_changed_page_bitmaps(lsn); } -/*****************************************************************//** -Check whether this is a fake change transaction. -@return TRUE if a fake change transaction */ -static -my_bool -innobase_is_fake_change( -/*====================*/ - handlerton *hton MY_ATTRIBUTE((unused)), - /*!< in: InnoDB handlerton */ - THD* thd) /*!< in: MySQL thread handle of the user for - whom the transaction is being committed */ -{ - trx_t* trx = check_trx_exists(thd); - return UNIV_UNLIKELY(trx->fake_changes); -} - /*****************************************************************//** Commits a transaction in an InnoDB database. */ static diff --git a/storage/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc index a9f039d3f0f..e00adefe68f 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.cc +++ b/storage/xtradb/ibuf/ibuf0ibuf.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -3704,7 +3705,7 @@ fail_exit: if (mode == BTR_MODIFY_PREV) { err = btr_cur_optimistic_insert( - BTR_NO_LOCKING_FLAG, + BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG, cursor, &offsets, &offsets_heap, ibuf_entry, &ins_rec, &dummy_big_rec, 0, thr, &mtr); diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h index 19ab7d8bc3a..d973eb80c59 100644 --- a/storage/xtradb/include/btr0cur.h +++ b/storage/xtradb/include/btr0cur.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -220,15 +221,17 @@ btr_cur_optimistic_insert( btr_cur_t* cursor, /*!< in: cursor on page after which to insert; cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ - mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ + mem_heap_t** heap, /*!< in/out: pointer to memory heap */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction; if this function returns DB_SUCCESS on a leaf page of a secondary index in a @@ -256,15 +259,17 @@ btr_cur_pessimistic_insert( cursor stays valid */ ulint** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if succeed */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or - NULL */ + be stored externally by the caller */ ulint n_ext, /*!< in: number of externally stored columns */ - que_thr_t* thr, /*!< in: query thread or NULL */ + que_thr_t* thr, /*!< in/out: query thread; can be NULL if + !(~flags + & (BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG)) */ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((nonnull(2,3,4,5,6,7,10), warn_unused_result)); /*************************************************************//** @@ -392,12 +397,12 @@ btr_cur_pessimistic_update( ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ mem_heap_t** offsets_heap, /*!< in/out: pointer to memory heap - that can be emptied, or NULL */ + that can be emptied */ mem_heap_t* entry_heap, /*!< in/out: memory heap for allocating big_rec and the index tuple */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to - be stored externally by the caller, or NULL */ + be stored externally by the caller */ const upd_t* update, /*!< in: update vector; this is allowed also contain trx id and roll ptr fields, but the values in update vector have no effect */ diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index 49744959dc6..ec9f74cd4ad 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -2139,14 +2140,10 @@ for a clustered index! @retval DB_SUCCESS if no error @retval DB_DUPLICATE_KEY if error, @retval DB_LOCK_WAIT if we have to wait for a lock on a possible duplicate -record -@retval DB_SUCCESS_LOCKED_REC if an exact match of the record was found -in online table rebuild (flags & (BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG)) */ +record */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t row_ins_duplicate_error_in_clust( -/*=============================*/ - ulint flags, /*!< in: undo logging and locking flags */ btr_cur_t* cursor, /*!< in: B-tree cursor */ const dtuple_t* entry, /*!< in: entry to insert */ que_thr_t* thr, /*!< in: query thread */ @@ -2421,7 +2418,7 @@ row_ins_clust_index_entry_low( DB_LOCK_WAIT */ err = row_ins_duplicate_error_in_clust( - flags, &cursor, entry, thr, &mtr); + &cursor, entry, thr, &mtr); } if (err != DB_SUCCESS) { From 8b34aabf86b3f2bab392df8d87b28069e8adfc73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 May 2017 16:09:29 +0300 Subject: [PATCH 129/148] Follow-up to MDEV-12534: Align srv_sys Allocate srv_sys statically so that the desired alignment can be guaranteed. This silences -fsanitize=undefined warnings. There probably is no performance impact of this, because the reason for the alignment to ensure the absence of false sharing between counters. Even with the misalignment, each counter would have been been aligned at 64 bits, and the counters would reside in separate cache lines. --- storage/innobase/srv/srv0srv.cc | 121 +++++++++++++--------------- storage/xtradb/srv/srv0srv.cc | 134 ++++++++++++++------------------ 2 files changed, 112 insertions(+), 143 deletions(-) diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 7beacc76615..cadd3fc1d1a 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -293,7 +293,7 @@ UNIV_INTERN double srv_adaptive_flushing_lwm = 10.0; UNIV_INTERN ulong srv_flushing_avg_loops = 30; /* The number of purge threads to use.*/ -UNIV_INTERN ulong srv_n_purge_threads = 1; +UNIV_INTERN ulong srv_n_purge_threads; /* the number of pages to purge in one batch */ UNIV_INTERN ulong srv_purge_batch_size = 20; @@ -490,16 +490,16 @@ UNIV_INTERN uint srv_simulate_comp_failures = 0; /** Acquire the system_mutex. */ #define srv_sys_mutex_enter() do { \ - mutex_enter(&srv_sys->mutex); \ + mutex_enter(&srv_sys.mutex); \ } while (0) /** Test if the system mutex is owned. */ -#define srv_sys_mutex_own() (mutex_own(&srv_sys->mutex) \ +#define srv_sys_mutex_own() (mutex_own(&srv_sys.mutex) \ && !srv_read_only_mode) /** Release the system mutex. */ #define srv_sys_mutex_exit() do { \ - mutex_exit(&srv_sys->mutex); \ + mutex_exit(&srv_sys.mutex); \ } while (0) #define fetch_lock_wait_timeout(trx) \ @@ -591,7 +591,7 @@ struct srv_sys_t{ ulint n_sys_threads; /*!< size of the sys_threads array */ - srv_slot_t* sys_threads; /*!< server thread table; + srv_slot_t sys_threads[32 + 1]; /*!< server thread table; os_event_set() and os_event_reset() on sys_threads[]->event are @@ -611,7 +611,7 @@ struct srv_sys_t{ UNIV_INTERN ib_mutex_t server_mutex; #endif /* !HAVE_ATOMIC_BUILTINS */ -static srv_sys_t* srv_sys = NULL; +static srv_sys_t srv_sys; /** Event to signal srv_monitor_thread. Not protected by a mutex. Set after setting srv_print_innodb_monitor. */ @@ -633,10 +633,10 @@ and/or load it during startup. */ UNIV_INTERN char srv_buffer_pool_dump_at_shutdown = FALSE; UNIV_INTERN char srv_buffer_pool_load_at_startup = FALSE; -/** Slot index in the srv_sys->sys_threads array for the purge thread. */ +/** Slot index in the srv_sys.sys_threads array for the purge thread. */ static const ulint SRV_PURGE_SLOT = 1; -/** Slot index in the srv_sys->sys_threads array for the master thread. */ +/** Slot index in the srv_sys.sys_threads array for the master thread. */ static const ulint SRV_MASTER_SLOT = 0; /*********************************************************************//** @@ -737,21 +737,21 @@ srv_reserve_slot( switch (type) { case SRV_MASTER: - slot = &srv_sys->sys_threads[SRV_MASTER_SLOT]; + slot = &srv_sys.sys_threads[SRV_MASTER_SLOT]; break; case SRV_PURGE: - slot = &srv_sys->sys_threads[SRV_PURGE_SLOT]; + slot = &srv_sys.sys_threads[SRV_PURGE_SLOT]; break; case SRV_WORKER: /* Find an empty slot, skip the master and purge slots. */ - for (slot = &srv_sys->sys_threads[2]; + for (slot = &srv_sys.sys_threads[2]; slot->in_use; ++slot) { - ut_a(slot < &srv_sys->sys_threads[ - srv_sys->n_sys_threads]); + ut_a(slot < &srv_sys.sys_threads[ + srv_sys.n_sys_threads]); } break; @@ -767,7 +767,7 @@ srv_reserve_slot( ut_ad(srv_slot_get_type(slot) == type); - ++srv_sys->n_threads_active[type]; + ++srv_sys.n_threads_active[type]; srv_sys_mutex_exit(); @@ -797,27 +797,27 @@ srv_suspend_thread_low( case SRV_MASTER: /* We have only one master thread and it should be the first entry always. */ - ut_a(srv_sys->n_threads_active[type] == 1); + ut_a(srv_sys.n_threads_active[type] == 1); break; case SRV_PURGE: /* We have only one purge coordinator thread and it should be the second entry always. */ - ut_a(srv_sys->n_threads_active[type] == 1); + ut_a(srv_sys.n_threads_active[type] == 1); break; case SRV_WORKER: ut_a(srv_n_purge_threads > 1); - ut_a(srv_sys->n_threads_active[type] > 0); + ut_a(srv_sys.n_threads_active[type] > 0); break; } ut_a(!slot->suspended); slot->suspended = TRUE; - ut_a(srv_sys->n_threads_active[type] > 0); + ut_a(srv_sys.n_threads_active[type] > 0); - srv_sys->n_threads_active[type]--; + srv_sys.n_threads_active[type]--; return(os_event_reset(slot->event)); } @@ -872,7 +872,7 @@ srv_resume_thread(srv_slot_t* slot, ib_int64_t sig_count = 0, bool wait = true, ut_ad(slot->suspended); slot->suspended = FALSE; - ++srv_sys->n_threads_active[slot->type]; + ++srv_sys.n_threads_active[slot->type]; srv_sys_mutex_exit(); return(timeout); } @@ -894,8 +894,8 @@ srv_release_threads(enum srv_thread_type type, ulint n) srv_sys_mutex_enter(); - for (ulint i = 0; i < srv_sys->n_sys_threads; i++) { - srv_slot_t* slot = &srv_sys->sys_threads[i]; + for (ulint i = 0; i < srv_sys.n_sys_threads; i++) { + srv_slot_t* slot = &srv_sys.sys_threads[i]; if (!slot->in_use || srv_slot_get_type(slot) != type) { continue; @@ -915,7 +915,7 @@ srv_release_threads(enum srv_thread_type type, ulint n) should be the first entry always. */ ut_a(n == 1); ut_a(i == SRV_MASTER_SLOT); - ut_a(srv_sys->n_threads_active[type] == 0); + ut_a(srv_sys.n_threads_active[type] == 0); break; case SRV_PURGE: @@ -924,12 +924,12 @@ srv_release_threads(enum srv_thread_type type, ulint n) ut_a(n == 1); ut_a(i == SRV_PURGE_SLOT); ut_a(srv_n_purge_threads > 0); - ut_a(srv_sys->n_threads_active[type] == 0); + ut_a(srv_sys.n_threads_active[type] == 0); break; case SRV_WORKER: ut_a(srv_n_purge_threads > 1); - ut_a(srv_sys->n_threads_active[type] + ut_a(srv_sys.n_threads_active[type] < srv_n_purge_threads - 1); break; } @@ -967,9 +967,6 @@ void srv_init(void) /*==========*/ { - ulint n_sys_threads = 0; - ulint srv_sys_sz = sizeof(*srv_sys); - #ifndef HAVE_ATOMIC_BUILTINS mutex_create(server_mutex_key, &server_mutex, SYNC_ANY_LATCH); #endif /* !HAVE_ATOMIC_BUILTINS */ @@ -977,29 +974,19 @@ srv_init(void) mutex_create(srv_innodb_monitor_mutex_key, &srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK); - if (!srv_read_only_mode) { - - /* Number of purge threads + master thread */ - n_sys_threads = srv_n_purge_threads + 1; - - srv_sys_sz += n_sys_threads * sizeof(*srv_sys->sys_threads); - } - - srv_sys = static_cast(mem_zalloc(srv_sys_sz)); - - srv_sys->n_sys_threads = n_sys_threads; + srv_sys.n_sys_threads = srv_read_only_mode + ? 0 + : srv_n_purge_threads + 1/* purge coordinator */; if (!srv_read_only_mode) { - mutex_create(srv_sys_mutex_key, &srv_sys->mutex, SYNC_THREADS); + mutex_create(srv_sys_mutex_key, &srv_sys.mutex, SYNC_THREADS); mutex_create(srv_sys_tasks_mutex_key, - &srv_sys->tasks_mutex, SYNC_ANY_LATCH); + &srv_sys.tasks_mutex, SYNC_ANY_LATCH); - srv_sys->sys_threads = (srv_slot_t*) &srv_sys[1]; - - for (ulint i = 0; i < srv_sys->n_sys_threads; ++i) { - srv_slot_t* slot = &srv_sys->sys_threads[i]; + for (ulint i = 0; i < srv_sys.n_sys_threads; ++i) { + srv_slot_t* slot = &srv_sys.sys_threads[i]; slot->event = os_event_create(); @@ -1048,10 +1035,8 @@ srv_free(void) { srv_conc_free(); - /* The mutexes srv_sys->mutex and srv_sys->tasks_mutex should have + /* The mutexes srv_sys.mutex and srv_sys.tasks_mutex should have been freed by sync_close() already. */ - mem_free(srv_sys); - srv_sys = NULL; trx_i_s_cache_free(trx_i_s_cache); @@ -1882,7 +1867,7 @@ void srv_inc_activity_count(void) /*========================*/ { - srv_sys->activity_count.inc(); + srv_sys.activity_count.inc(); } /**********************************************************************//** @@ -1904,7 +1889,7 @@ srv_get_active_thread_type(void) srv_sys_mutex_enter(); for (ulint i = SRV_WORKER; i <= SRV_MASTER; ++i) { - if (srv_sys->n_threads_active[i] != 0) { + if (srv_sys.n_threads_active[i] != 0) { ret = static_cast(i); break; } @@ -1977,12 +1962,12 @@ srv_active_wake_master_thread(void) srv_inc_activity_count(); - if (srv_sys->n_threads_active[SRV_MASTER] == 0) { + if (srv_sys.n_threads_active[SRV_MASTER] == 0) { srv_slot_t* slot; srv_sys_mutex_enter(); - slot = &srv_sys->sys_threads[SRV_MASTER_SLOT]; + slot = &srv_sys.sys_threads[SRV_MASTER_SLOT]; /* Only if the master thread has been started. */ @@ -2009,7 +1994,7 @@ srv_wake_purge_thread_if_not_active(void) ut_ad(!srv_sys_mutex_own()); if (purge_sys->state == PURGE_STATE_RUN - && srv_sys->n_threads_active[SRV_PURGE] == 0) { + && srv_sys.n_threads_active[SRV_PURGE] == 0) { srv_release_threads(SRV_PURGE, 1); } @@ -2038,7 +2023,7 @@ ulint srv_get_activity_count(void) /*========================*/ { - return(srv_sys->activity_count); + return(srv_sys.activity_count); } /*******************************************************************//** @@ -2050,7 +2035,7 @@ srv_check_activity( /*===============*/ ulint old_activity_count) /*!< in: old activity count */ { - return(srv_sys->activity_count != old_activity_count); + return(srv_sys.activity_count != old_activity_count); } /********************************************************************//** @@ -2415,7 +2400,7 @@ DECLARE_THREAD(srv_master_thread)( srv_main_thread_id = os_thread_pf(os_thread_get_curr_id()); slot = srv_reserve_slot(SRV_MASTER); - ut_a(slot == srv_sys->sys_threads); + ut_a(slot == srv_sys.sys_threads); last_print_time = ut_time(); loop: @@ -2505,18 +2490,18 @@ srv_task_execute(void) ut_ad(!srv_read_only_mode); ut_a(srv_force_recovery < SRV_FORCE_NO_BACKGROUND); - mutex_enter(&srv_sys->tasks_mutex); + mutex_enter(&srv_sys.tasks_mutex); - if (UT_LIST_GET_LEN(srv_sys->tasks) > 0) { + if (UT_LIST_GET_LEN(srv_sys.tasks) > 0) { - thr = UT_LIST_GET_FIRST(srv_sys->tasks); + thr = UT_LIST_GET_FIRST(srv_sys.tasks); ut_a(que_node_get_type(thr->child) == QUE_NODE_PURGE); - UT_LIST_REMOVE(queue, srv_sys->tasks, thr); + UT_LIST_REMOVE(queue, srv_sys.tasks, thr); } - mutex_exit(&srv_sys->tasks_mutex); + mutex_exit(&srv_sys.tasks_mutex); if (thr != NULL) { @@ -2556,7 +2541,7 @@ DECLARE_THREAD(srv_worker_thread)( srv_sys_mutex_enter(); - ut_a(srv_sys->n_threads_active[SRV_WORKER] < srv_n_purge_threads); + ut_a(srv_sys.n_threads_active[SRV_WORKER] < srv_n_purge_threads); srv_sys_mutex_exit(); @@ -2885,11 +2870,11 @@ srv_que_task_enqueue_low( que_thr_t* thr) /*!< in: query thread */ { ut_ad(!srv_read_only_mode); - mutex_enter(&srv_sys->tasks_mutex); + mutex_enter(&srv_sys.tasks_mutex); - UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr); + UT_LIST_ADD_LAST(queue, srv_sys.tasks, thr); - mutex_exit(&srv_sys->tasks_mutex); + mutex_exit(&srv_sys.tasks_mutex); srv_release_threads(SRV_WORKER, 1); } @@ -2906,11 +2891,11 @@ srv_get_task_queue_length(void) ut_ad(!srv_read_only_mode); - mutex_enter(&srv_sys->tasks_mutex); + mutex_enter(&srv_sys.tasks_mutex); - n_tasks = UT_LIST_GET_LEN(srv_sys->tasks); + n_tasks = UT_LIST_GET_LEN(srv_sys.tasks); - mutex_exit(&srv_sys->tasks_mutex); + mutex_exit(&srv_sys.tasks_mutex); return(n_tasks); } diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 22a96b7446a..80241d9947f 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -400,7 +400,7 @@ UNIV_INTERN my_bool srv_cleaner_thread_priority = FALSE; UNIV_INTERN my_bool srv_master_thread_priority = FALSE; /* The number of purge threads to use.*/ -UNIV_INTERN ulong srv_n_purge_threads = 1; +UNIV_INTERN ulong srv_n_purge_threads; /* the number of pages to purge in one batch */ UNIV_INTERN ulong srv_purge_batch_size = 20; @@ -619,16 +619,16 @@ current_time % 5 != 0. */ /** Acquire the system_mutex. */ #define srv_sys_mutex_enter() do { \ - mutex_enter(&srv_sys->mutex); \ + mutex_enter(&srv_sys.mutex); \ } while (0) /** Test if the system mutex is owned. */ -#define srv_sys_mutex_own() (mutex_own(&srv_sys->mutex) \ +#define srv_sys_mutex_own() (mutex_own(&srv_sys.mutex) \ && !srv_read_only_mode) /** Release the system mutex. */ #define srv_sys_mutex_exit() do { \ - mutex_exit(&srv_sys->mutex); \ + mutex_exit(&srv_sys.mutex); \ } while (0) #define fetch_lock_wait_timeout(trx) \ @@ -723,7 +723,7 @@ struct srv_sys_t{ ulint n_sys_threads; /*!< size of the sys_threads array */ - srv_slot_t* sys_threads; /*!< server thread table; + srv_slot_t sys_threads[32 + 1]; /*!< server thread table; os_event_set() and os_event_reset() on sys_threads[]->event are @@ -747,7 +747,7 @@ struct srv_sys_t{ UNIV_INTERN ib_mutex_t server_mutex; #endif /* !HAVE_ATOMIC_BUILTINS */ -static srv_sys_t* srv_sys = NULL; +static srv_sys_t srv_sys; /** Event to signal srv_monitor_thread. Not protected by a mutex. Set after setting srv_print_innodb_monitor. */ @@ -769,10 +769,10 @@ and/or load it during startup. */ UNIV_INTERN char srv_buffer_pool_dump_at_shutdown = FALSE; UNIV_INTERN char srv_buffer_pool_load_at_startup = FALSE; -/** Slot index in the srv_sys->sys_threads array for the purge thread. */ +/** Slot index in the srv_sys.sys_threads array for the purge thread. */ static const ulint SRV_PURGE_SLOT = 1; -/** Slot index in the srv_sys->sys_threads array for the master thread. */ +/** Slot index in the srv_sys.sys_threads array for the master thread. */ static const ulint SRV_MASTER_SLOT = 0; UNIV_INTERN os_event_t srv_checkpoint_completed_event; @@ -882,21 +882,21 @@ srv_reserve_slot( switch (type) { case SRV_MASTER: - slot = &srv_sys->sys_threads[SRV_MASTER_SLOT]; + slot = &srv_sys.sys_threads[SRV_MASTER_SLOT]; break; case SRV_PURGE: - slot = &srv_sys->sys_threads[SRV_PURGE_SLOT]; + slot = &srv_sys.sys_threads[SRV_PURGE_SLOT]; break; case SRV_WORKER: /* Find an empty slot, skip the master and purge slots. */ - for (slot = &srv_sys->sys_threads[2]; + for (slot = &srv_sys.sys_threads[2]; slot->in_use; ++slot) { - ut_a(slot < &srv_sys->sys_threads[ - srv_sys->n_sys_threads]); + ut_a(slot < &srv_sys.sys_threads[ + srv_sys.n_sys_threads]); } break; @@ -912,7 +912,7 @@ srv_reserve_slot( ut_ad(srv_slot_get_type(slot) == type); - ++srv_sys->n_threads_active[type]; + ++srv_sys.n_threads_active[type]; srv_sys_mutex_exit(); @@ -942,27 +942,27 @@ srv_suspend_thread_low( case SRV_MASTER: /* We have only one master thread and it should be the first entry always. */ - ut_a(srv_sys->n_threads_active[type] == 1); + ut_a(srv_sys.n_threads_active[type] == 1); break; case SRV_PURGE: /* We have only one purge coordinator thread and it should be the second entry always. */ - ut_a(srv_sys->n_threads_active[type] == 1); + ut_a(srv_sys.n_threads_active[type] == 1); break; case SRV_WORKER: ut_a(srv_n_purge_threads > 1); - ut_a(srv_sys->n_threads_active[type] > 0); + ut_a(srv_sys.n_threads_active[type] > 0); break; } ut_a(!slot->suspended); slot->suspended = TRUE; - ut_a(srv_sys->n_threads_active[type] > 0); + ut_a(srv_sys.n_threads_active[type] > 0); - srv_sys->n_threads_active[type]--; + srv_sys.n_threads_active[type]--; return(os_event_reset(slot->event)); } @@ -1017,7 +1017,7 @@ srv_resume_thread(srv_slot_t* slot, ib_int64_t sig_count = 0, bool wait = true, ut_ad(slot->suspended); slot->suspended = FALSE; - ++srv_sys->n_threads_active[slot->type]; + ++srv_sys.n_threads_active[slot->type]; srv_sys_mutex_exit(); return(timeout); } @@ -1039,8 +1039,8 @@ srv_release_threads(enum srv_thread_type type, ulint n) srv_sys_mutex_enter(); - for (ulint i = 0; i < srv_sys->n_sys_threads; i++) { - srv_slot_t* slot = &srv_sys->sys_threads[i]; + for (ulint i = 0; i < srv_sys.n_sys_threads; i++) { + srv_slot_t* slot = &srv_sys.sys_threads[i]; if (!slot->in_use || srv_slot_get_type(slot) != type) { continue; @@ -1060,7 +1060,7 @@ srv_release_threads(enum srv_thread_type type, ulint n) should be the first entry always. */ ut_a(n == 1); ut_a(i == SRV_MASTER_SLOT); - ut_a(srv_sys->n_threads_active[type] == 0); + ut_a(srv_sys.n_threads_active[type] == 0); break; case SRV_PURGE: @@ -1069,12 +1069,12 @@ srv_release_threads(enum srv_thread_type type, ulint n) ut_a(n == 1); ut_a(i == SRV_PURGE_SLOT); ut_a(srv_n_purge_threads > 0); - ut_a(srv_sys->n_threads_active[type] == 0); + ut_a(srv_sys.n_threads_active[type] == 0); break; case SRV_WORKER: ut_a(srv_n_purge_threads > 1); - ut_a(srv_sys->n_threads_active[type] + ut_a(srv_sys.n_threads_active[type] < srv_n_purge_threads - 1); break; } @@ -1112,9 +1112,6 @@ void srv_init(void) /*==========*/ { - ulint n_sys_threads = 0; - ulint srv_sys_sz = sizeof(*srv_sys); - #ifndef HAVE_ATOMIC_BUILTINS mutex_create(server_mutex_key, &server_mutex, SYNC_ANY_LATCH); #endif /* !HAVE_ATOMIC_BUILTINS */ @@ -1122,29 +1119,19 @@ srv_init(void) mutex_create(srv_innodb_monitor_mutex_key, &srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK); - if (!srv_read_only_mode) { - - /* Number of purge threads + master thread */ - n_sys_threads = srv_n_purge_threads + 1; - - srv_sys_sz += n_sys_threads * sizeof(*srv_sys->sys_threads); - } - - srv_sys = static_cast(mem_zalloc(srv_sys_sz)); - - srv_sys->n_sys_threads = n_sys_threads; + srv_sys.n_sys_threads = srv_read_only_mode + ? 0 + : srv_n_purge_threads + 1/* purge coordinator */; if (!srv_read_only_mode) { - mutex_create(srv_sys_mutex_key, &srv_sys->mutex, SYNC_THREADS); + mutex_create(srv_sys_mutex_key, &srv_sys.mutex, SYNC_THREADS); mutex_create(srv_sys_tasks_mutex_key, - &srv_sys->tasks_mutex, SYNC_ANY_LATCH); + &srv_sys.tasks_mutex, SYNC_ANY_LATCH); - srv_sys->sys_threads = (srv_slot_t*) &srv_sys[1]; - - for (ulint i = 0; i < srv_sys->n_sys_threads; ++i) { - srv_slot_t* slot = &srv_sys->sys_threads[i]; + for (ulint i = 0; i < srv_sys.n_sys_threads; ++i) { + srv_slot_t* slot = &srv_sys.sys_threads[i]; slot->event = os_event_create(); @@ -1203,8 +1190,8 @@ srv_free(void) if (!srv_read_only_mode) { - for (ulint i = 0; i < srv_sys->n_sys_threads; i++) - os_event_free(srv_sys->sys_threads[i].event); + for (ulint i = 0; i < srv_sys.n_sys_threads; i++) + os_event_free(srv_sys.sys_threads[i].event); os_event_free(srv_error_event); srv_error_event = NULL; @@ -1216,8 +1203,8 @@ srv_free(void) srv_checkpoint_completed_event = NULL; os_event_free(srv_redo_log_tracked_event); srv_redo_log_tracked_event = NULL; - mutex_free(&srv_sys->mutex); - mutex_free(&srv_sys->tasks_mutex); + mutex_free(&srv_sys.mutex); + mutex_free(&srv_sys.tasks_mutex); } #ifndef HAVE_ATOMIC_BUILTINS @@ -1226,9 +1213,6 @@ srv_free(void) mutex_free(&srv_innodb_monitor_mutex); mutex_free(&page_zip_stat_per_index_mutex); - mem_free(srv_sys); - srv_sys = NULL; - trx_i_s_cache_free(trx_i_s_cache); } @@ -2305,9 +2289,9 @@ srv_inc_activity_count( is caused by the background change buffer merge */ { - srv_sys->activity_count.inc(); + srv_sys.activity_count.inc(); if (ibuf_merge_activity) - srv_sys->ibuf_merge_activity_count.inc(); + srv_sys.ibuf_merge_activity_count.inc(); } /**********************************************************************//** @@ -2329,7 +2313,7 @@ srv_get_active_thread_type(void) srv_sys_mutex_enter(); for (ulint i = SRV_WORKER; i <= SRV_MASTER; ++i) { - if (srv_sys->n_threads_active[i] != 0) { + if (srv_sys.n_threads_active[i] != 0) { ret = static_cast(i); break; } @@ -2582,12 +2566,12 @@ srv_active_wake_master_thread(void) srv_inc_activity_count(); - if (srv_sys->n_threads_active[SRV_MASTER] == 0) { + if (srv_sys.n_threads_active[SRV_MASTER] == 0) { srv_slot_t* slot; srv_sys_mutex_enter(); - slot = &srv_sys->sys_threads[SRV_MASTER_SLOT]; + slot = &srv_sys.sys_threads[SRV_MASTER_SLOT]; /* Only if the master thread has been started. */ @@ -2614,7 +2598,7 @@ srv_wake_purge_thread_if_not_active(void) ut_ad(!srv_sys_mutex_own()); if (purge_sys->state == PURGE_STATE_RUN - && srv_sys->n_threads_active[SRV_PURGE] == 0) { + && srv_sys.n_threads_active[SRV_PURGE] == 0) { srv_release_threads(SRV_PURGE, 1); } @@ -2643,7 +2627,7 @@ ulint srv_get_activity_count(void) /*========================*/ { - return(srv_sys->activity_count); + return(srv_sys.activity_count); } /** Get current server ibuf merge activity count. @@ -2652,7 +2636,7 @@ static ulint srv_get_ibuf_merge_activity_count(void) { - return(srv_sys->ibuf_merge_activity_count); + return(srv_sys.ibuf_merge_activity_count); } /*******************************************************************//** @@ -2671,14 +2655,14 @@ srv_check_activity( ULINT_UNDEFINED */ ulint old_ibuf_merge_activity_count) { - ulint new_activity_count = srv_sys->activity_count; + ulint new_activity_count = srv_sys.activity_count; if (old_ibuf_merge_activity_count == ULINT_UNDEFINED) return(new_activity_count != old_activity_count); /* If we care about ibuf merge activity, then the server is considered idle if all activity, if any, was due to ibuf merge. */ ulint new_ibuf_merge_activity_count - = srv_sys->ibuf_merge_activity_count; + = srv_sys.ibuf_merge_activity_count; ut_ad(new_ibuf_merge_activity_count <= new_activity_count); ut_ad(new_ibuf_merge_activity_count >= old_ibuf_merge_activity_count); @@ -3069,7 +3053,7 @@ DECLARE_THREAD(srv_master_thread)( srv_main_thread_id = os_thread_pf(os_thread_get_curr_id()); slot = srv_reserve_slot(SRV_MASTER); - ut_a(slot == srv_sys->sys_threads); + ut_a(slot == srv_sys.sys_threads); last_print_time = ut_time(); loop: @@ -3165,18 +3149,18 @@ srv_task_execute(void) ut_ad(!srv_read_only_mode); ut_a(srv_force_recovery < SRV_FORCE_NO_BACKGROUND); - mutex_enter(&srv_sys->tasks_mutex); + mutex_enter(&srv_sys.tasks_mutex); - if (UT_LIST_GET_LEN(srv_sys->tasks) > 0) { + if (UT_LIST_GET_LEN(srv_sys.tasks) > 0) { - thr = UT_LIST_GET_FIRST(srv_sys->tasks); + thr = UT_LIST_GET_FIRST(srv_sys.tasks); ut_a(que_node_get_type(thr->child) == QUE_NODE_PURGE); - UT_LIST_REMOVE(queue, srv_sys->tasks, thr); + UT_LIST_REMOVE(queue, srv_sys.tasks, thr); } - mutex_exit(&srv_sys->tasks_mutex); + mutex_exit(&srv_sys.tasks_mutex); if (thr != NULL) { @@ -3226,7 +3210,7 @@ DECLARE_THREAD(srv_worker_thread)( srv_sys_mutex_enter(); - ut_a(srv_sys->n_threads_active[SRV_WORKER] < srv_n_purge_threads); + ut_a(srv_sys.n_threads_active[SRV_WORKER] < srv_n_purge_threads); srv_sys_mutex_exit(); @@ -3566,11 +3550,11 @@ srv_que_task_enqueue_low( que_thr_t* thr) /*!< in: query thread */ { ut_ad(!srv_read_only_mode); - mutex_enter(&srv_sys->tasks_mutex); + mutex_enter(&srv_sys.tasks_mutex); - UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr); + UT_LIST_ADD_LAST(queue, srv_sys.tasks, thr); - mutex_exit(&srv_sys->tasks_mutex); + mutex_exit(&srv_sys.tasks_mutex); srv_release_threads(SRV_WORKER, 1); } @@ -3587,11 +3571,11 @@ srv_get_task_queue_length(void) ut_ad(!srv_read_only_mode); - mutex_enter(&srv_sys->tasks_mutex); + mutex_enter(&srv_sys.tasks_mutex); - n_tasks = UT_LIST_GET_LEN(srv_sys->tasks); + n_tasks = UT_LIST_GET_LEN(srv_sys.tasks); - mutex_exit(&srv_sys->tasks_mutex); + mutex_exit(&srv_sys.tasks_mutex); return(n_tasks); } From 3670d167a6261a867b8a5e64028e7b580ca5991a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Wed, 17 May 2017 16:19:01 +0300 Subject: [PATCH 130/148] Fix tokudb test failures post merge --- storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt | 1 - storage/tokudb/mysql-test/tokudb/t/background_job_manager.test | 1 + storage/tokudb/mysql-test/tokudb/t/bug-1657908.test | 1 + storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test | 1 + storage/tokudb/mysql-test/tokudb/t/dir_cmd.test | 1 + .../mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test | 1 + storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test | 1 + storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test | 1 + .../tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test | 1 + .../tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test | 1 + .../tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test | 1 + storage/tokudb/mysql-test/tokudb_bugs/t/db938.test | 1 + storage/tokudb/mysql-test/tokudb_bugs/t/db945.test | 1 + storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test | 1 + 14 files changed, 13 insertions(+), 1 deletion(-) delete mode 100644 storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt diff --git a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt b/storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt deleted file mode 100644 index 3cc9ea3009e..00000000000 --- a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt +++ /dev/null @@ -1 +0,0 @@ ---tokudb-background-job-status diff --git a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test b/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test index 933814442e0..709fc463696 100644 --- a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test +++ b/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test @@ -1,3 +1,4 @@ +skip Background Job Manager not supported in MariaDB; # This is a comprehensive test for the background job manager and # the information_schema.tokudb_background_job_status table # diff --git a/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test b/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test index 3c7b602b96d..adcf4ef55f6 100644 --- a/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test +++ b/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test @@ -1,3 +1,4 @@ +--source include/have_partition.inc # See https://bugs.launchpad.net/percona-server/+bug/1657908 source include/have_tokudb.inc; diff --git a/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test b/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test index ec74a4a28bc..9675449372b 100644 --- a/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test +++ b/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test @@ -1,3 +1,4 @@ +skip Background Job Manager not supported in MariaDB; # Test the auto analyze on lots of tables -- source include/have_tokudb.inc diff --git a/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test b/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test index 102e8217e2b..b9d8c80de65 100644 --- a/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test +++ b/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test @@ -1,3 +1,4 @@ +skip TokuDB dir CMD disabled in MariaDB; source include/have_tokudb.inc; --let $MYSQL_DATADIR=`select @@datadir` diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test index 42fb548814f..8fe5e66a9b3 100644 --- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test +++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test @@ -1,3 +1,4 @@ +skip Tokudb Lock Waits not in I_S in MariaDB; # verify that tokudb_locks and tokudb_lock_waits contents for 2 conflicting transactions with a lock timeout source include/have_tokudb.inc; diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test index 8f205ad7f45..59d04ead386 100644 --- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test +++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test @@ -1,3 +1,4 @@ +skip Tokudb Lock Waits not in I_S in MariaDB; # verify that information_schema.tokudb_locks gets populated with locks for 2 clients source include/have_tokudb.inc; diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test index 517280391c4..b4ab64be962 100644 --- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test +++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test @@ -1,3 +1,4 @@ +skip Tokudb trx not in I_S in MariaDB; # verify that information_schema.tokudb_trx gets populated with transactions source include/have_tokudb.inc; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test index 79043664607..7343768a7d7 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test @@ -1,3 +1,4 @@ +skip Tokudb Lock Waits not in I_S in MariaDB; # check for any locking weirdness on DELETE triggers source include/have_tokudb.inc; set default_storage_engine='tokudb'; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test index ffe2face9f2..313b1f96b52 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test @@ -1,3 +1,4 @@ +skip Tokudb Lock Waits not in I_S in MariaDB; # check for any locking weirdness on INSERT triggers source include/have_tokudb.inc; set default_storage_engine='tokudb'; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test index 063a88cb4ab..ce1eb6bddd1 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test @@ -1,3 +1,4 @@ +skip Tokudb Lock Waits not in I_S in MariaDB; # check for any locking weirdness on UPDATE triggers source include/have_tokudb.inc; set default_storage_engine='tokudb'; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test index 50434a79a00..d65bf3d95de 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test @@ -1,3 +1,4 @@ +skip Background Job Manager not supported in MariaDB; # This test for DB-938 tests a race condition where a scheduled background job # (analyze) ends up operating on a set of DB* key_file[] in TOKUDB_SHARE that # were set to NULL during a TRUNCATE TABLE operation. diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test index 27b0d284484..7996f9f5792 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test @@ -1,3 +1,4 @@ +skip Background Job Manager not supported in MariaDB; source include/have_tokudb.inc; set default_storage_engine='tokudb'; disable_warnings; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test b/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test index 735a88afed8..e7ef3211401 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test @@ -1,3 +1,4 @@ +skip Tokudb Fractal Tree info not in I_S in MariaDB; # test DB-718, a crash caused by broken error handling in tokudb's fractal_tree_info information schema source include/have_tokudb.inc; set default_storage_engine='tokudb'; From 8b0db08f36e779694510f28d10be0c9d6c2f3501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Wed, 17 May 2017 18:39:25 +0300 Subject: [PATCH 131/148] Fix windows compilation in xtradb post-merge --- storage/xtradb/os/os0file.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 9e5da12bb41..5e67d2473f0 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -1859,17 +1859,17 @@ os_file_create_func( *success = TRUE; retry = FALSE; if (srv_use_native_aio && ((attributes & FILE_FLAG_OVERLAPPED) != 0)) { - ut_a(CreateIoCompletionPort(file, completion_port, 0, 0)); + ut_a(CreateIoCompletionPort(file.m_file, completion_port, 0, 0)); } } } while (retry); if (srv_use_atomic_writes && type == OS_DATA_FILE && - !os_file_set_atomic_writes(name, file)) { - CloseHandle(file); + !os_file_set_atomic_writes(name, file.m_file)) { + CloseHandle(file.m_file); *success = FALSE; - file = INVALID_HANDLE_VALUE; + file.m_file = INVALID_HANDLE_VALUE; } #else /* __WIN__ */ @@ -5040,7 +5040,7 @@ os_aio_windows_handle( switch (slot->type) { case OS_FILE_WRITE: - ret_val = os_file_write(slot->name, slot->file.m_file, slot->buf, + ret_val = os_file_write(slot->name, slot->file, slot->buf, li.QuadPart, slot->len); break; case OS_FILE_READ: From 0e3ca225ad65f14da79c9a73aeadcc2a3e1c0c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Wed, 17 May 2017 22:09:58 +0300 Subject: [PATCH 132/148] Change lower_case_file_system definition to feature MYSQL_PLUGIN_IMPORT --- sql/mysqld.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.h b/sql/mysqld.h index e771a0c0da2..78e832e4abc 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -106,7 +106,7 @@ extern ulong slave_run_triggers_for_rbr; #endif //RBR_TRIGGERS extern ulonglong slave_type_conversions_options; extern my_bool read_only, opt_readonly; -extern my_bool lower_case_file_system; +extern MYSQL_PLUGIN_IMPORT my_bool lower_case_file_system; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern char* opt_secure_file_priv; From 7e9716310261bce124585cbffd85f3402390ec9d Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 17 May 2017 14:29:13 -0700 Subject: [PATCH 133/148] Fixed the bug mdev-12817/mdev-12820. This patch is a correction of the patch for bug mdev-12670. With the current code handling semi-joins the following must be taken into account. Conversion of an IN subquery predicate into semi-join has to be blocked if the predicate occurs: (a) in the ON expression of an outer join (b) in the ON expression of an inner join embedded directly or indirectly in the inner nest of an outer join. The patch for mdev-12670 blocked conversion to semi-joins only in the case (a), but not in the case (b). This patch blocks the conversion in both cases. --- mysql-test/r/subselect_sj.result | 54 +++++++++++++++++++++++++++ mysql-test/r/subselect_sj_jcl6.result | 54 +++++++++++++++++++++++++++ mysql-test/t/subselect_sj.test | 40 ++++++++++++++++++++ sql/opt_subselect.cc | 21 ++++++++++- 4 files changed, 168 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index c14b82f274e..74384141998 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -3099,4 +3099,58 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join) drop table t1,t2; set optimizer_switch= @tmp_mdev12675; +# +# MDEV-12817: subquery NOT subject to semi-join optimizations +# in ON expression of INNER JOIN +# +CREATE TABLE t1 (c1 int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (c2 int) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3),(4); +CREATE TABLE t3 (c3 int) ENGINE=MyISAM; +INSERT INTO t3 VALUES (5),(6); +CREATE TABLE t4 (c4 int) ENGINE=MyISAM; +INSERT INTO t4 VALUES (7),(8); +SELECT c1 +FROM t1 +LEFT JOIN +( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) ) +ON (c1 = c3); +c1 +1 +2 +EXPLAIN EXTENDED SELECT c1 +FROM t1 +LEFT JOIN +( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) ) +ON (c1 = c3); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 Using where +2 SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t3`.`c3` = `test`.`t1`.`c1`) and ((1,(select `test`.`t4`.`c4` from `test`.`t4` where (1 = `test`.`t4`.`c4`)))))) where 1 +# mdev-12820 +SELECT * +FROM t1 +LEFT JOIN +( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 ) +ON (c1 = c2); +c1 c2 c4 +1 NULL NULL +2 NULL NULL +EXPLAIN EXTENDED SELECT * +FROM t1 +LEFT JOIN +( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 ) +ON (c1 = c2); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 2 100.00 +3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(((`test`.`t2`.`c2` = `test`.`t1`.`c1`) and (`test`.`t1`.`c1`,(select `test`.`t3`.`c3` from `test`.`t3` where ((`test`.`t2`.`c2`) = `test`.`t3`.`c3`))))) where 1 +DROP TABLE t1,t2,t3,t4; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 33fd4c519ff..47dbdd782b5 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -3113,6 +3113,60 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join) drop table t1,t2; set optimizer_switch= @tmp_mdev12675; +# +# MDEV-12817: subquery NOT subject to semi-join optimizations +# in ON expression of INNER JOIN +# +CREATE TABLE t1 (c1 int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (c2 int) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3),(4); +CREATE TABLE t3 (c3 int) ENGINE=MyISAM; +INSERT INTO t3 VALUES (5),(6); +CREATE TABLE t4 (c4 int) ENGINE=MyISAM; +INSERT INTO t4 VALUES (7),(8); +SELECT c1 +FROM t1 +LEFT JOIN +( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) ) +ON (c1 = c3); +c1 +1 +2 +EXPLAIN EXTENDED SELECT c1 +FROM t1 +LEFT JOIN +( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) ) +ON (c1 = c3); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (incremental, BNL join) +2 SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t3`.`c3` = `test`.`t1`.`c1`) and ((1,(select `test`.`t4`.`c4` from `test`.`t4` where (1 = `test`.`t4`.`c4`)))))) where 1 +# mdev-12820 +SELECT * +FROM t1 +LEFT JOIN +( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 ) +ON (c1 = c2); +c1 c2 c4 +1 NULL NULL +2 NULL NULL +EXPLAIN EXTENDED SELECT * +FROM t1 +LEFT JOIN +( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 ) +ON (c1 = c2); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t4 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (incremental, BNL join) +3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(((`test`.`t2`.`c2` = `test`.`t1`.`c1`) and (`test`.`t1`.`c1`,(select `test`.`t3`.`c3` from `test`.`t3` where ((`test`.`t2`.`c2`) = `test`.`t3`.`c3`))))) where 1 +DROP TABLE t1,t2,t3,t4; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 5e9a2c88f22..acee1a67d63 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2801,5 +2801,45 @@ select a from t1 join t2 on b between 1 and 2 and a in (select b from t2); drop table t1,t2; set optimizer_switch= @tmp_mdev12675; +--echo # +--echo # MDEV-12817: subquery NOT subject to semi-join optimizations +--echo # in ON expression of INNER JOIN +--echo # + +CREATE TABLE t1 (c1 int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (c2 int) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3),(4); + +CREATE TABLE t3 (c3 int) ENGINE=MyISAM; +INSERT INTO t3 VALUES (5),(6); + +CREATE TABLE t4 (c4 int) ENGINE=MyISAM; +INSERT INTO t4 VALUES (7),(8); + +let $q1= +SELECT c1 +FROM t1 +LEFT JOIN +( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) ) +ON (c1 = c3); + +eval $q1; +eval EXPLAIN EXTENDED $q1; + +let $q2= +SELECT * +FROM t1 +LEFT JOIN +( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 ) +ON (c1 = c2); + +--echo # mdev-12820 +eval $q2; +eval EXPLAIN EXTENDED $q2; + +DROP TABLE t1,t2,t3,t4; + # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 645afa6744a..84e06fda852 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1103,7 +1103,26 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) do { embedded= embedding; - if (test(embedded->outer_join)) + bool block_conversion_to_sj= false; + if (embedded->on_expr) + { + /* + Conversion of an IN subquery predicate into semi-join + is blocked now if the predicate occurs: + - in the ON expression of an outer join + - in the ON expression of an inner join embedded directly + or indirectly in the inner nest of an outer join + */ + for (TABLE_LIST *tl= embedded; tl; tl= tl->embedding) + { + if (tl->outer_join) + { + block_conversion_to_sj= true; + break; + } + } + } + if (block_conversion_to_sj) { Item *cond= embedded->on_expr; if (!cond) From efb9f2617bde1654006a99af625859eb509d5448 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 17 May 2017 16:16:54 -0700 Subject: [PATCH 134/148] Fixed the bug mdev-12812. This is another correction of the patch for bug mdev-12670. If a derived table is merged into a select with STRAIGHT_JOIN modifier all IN subquery predicates contained in the specification of the derived table cannot be subject to conversion to semi-joins. --- mysql-test/r/derived_view.result | 21 +++++++++++++++++++++ mysql-test/t/derived_view.test | 20 ++++++++++++++++++++ sql/opt_subselect.cc | 10 ++++++++++ 3 files changed, 51 insertions(+) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 8af8db15319..f7062473a3f 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2617,5 +2617,26 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1) drop view v1; drop table t1,t2; +# +# Bug mdev-12812: mergeable derived / view with subqueries +# NOT subject to semi-join optimizations +# +CREATE TABLE t1 (c1 varchar(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),('foo'); +CREATE TABLE t2 (c2 varchar(3)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('bar'),('qux'),('foo'); +SELECT STRAIGHT_JOIN * +FROM ( SELECT * FROM t1 WHERE c1 IN ( SELECT c2 FROM t2 ) ) AS sq; +c1 +foo +foo +EXPLAIN EXTENDED SELECT STRAIGHT_JOIN * +FROM ( SELECT * FROM t1 WHERE c1 IN ( SELECT c2 FROM t2 ) ) AS sq; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select straight_join `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1`,(select `test`.`t2`.`c2` from `test`.`t2` where ((`test`.`t1`.`c1`) = `test`.`t2`.`c2`))) +DROP TABLE t1, t2; set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index cdddaf8f9d8..07fbe4980a5 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1911,6 +1911,26 @@ explain select * from v1; drop view v1; drop table t1,t2; +--echo # +--echo # Bug mdev-12812: mergeable derived / view with subqueries +--echo # NOT subject to semi-join optimizations +--echo # + +CREATE TABLE t1 (c1 varchar(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),('foo'); + +CREATE TABLE t2 (c2 varchar(3)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('bar'),('qux'),('foo'); + +let $q= +SELECT STRAIGHT_JOIN * + FROM ( SELECT * FROM t1 WHERE c1 IN ( SELECT c2 FROM t2 ) ) AS sq; + +eval $q; +eval EXPLAIN EXTENDED $q; + +DROP TABLE t1, t2; + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 84e06fda852..d8b4de29f47 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1161,6 +1161,16 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) in_subq->block_conversion_to_sj(); } } + + if (join->select_options & SELECT_STRAIGHT_JOIN) + { + /* Block conversion to semijoins for all candidates */ + li.rewind(); + while ((in_subq= li++)) + { + in_subq->block_conversion_to_sj(); + } + } li.rewind(); /* First, convert child join's subqueries. We proceed bottom-up here */ From 9f57e595b49744e3c1920f8c46a2ec8e7fc5fd66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 May 2017 16:14:41 +0300 Subject: [PATCH 135/148] Refactor trx_undo_report_row_operation() Fix a -fsanitizer=undefined warning that trx_undo_report_row_operation() was being passed thr=NULL when the BTR_NO_UNDO_LOG_FLAG flag was set. trx_undo_report_row_operation(): Remove the first two parameters. The parameter clust_entry!=NULL distinguishes inserts from updates. This should be a non-functional change (no observable change in behaviour; slightly smaller code). --- storage/innobase/btr/btr0cur.cc | 26 +++++++++-------- storage/innobase/include/trx0rec.h | 11 ++------ storage/innobase/trx/trx0rec.cc | 45 +++++++----------------------- storage/xtradb/btr/btr0cur.cc | 26 +++++++++-------- storage/xtradb/include/trx0rec.h | 11 ++------ storage/xtradb/trx/trx0rec.cc | 42 ++++++---------------------- 6 files changed, 53 insertions(+), 108 deletions(-) diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 7846debc115..7ca38c5b67d 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1164,18 +1164,21 @@ btr_cur_ins_lock_and_undo( index, thr, mtr, inherit); if (err != DB_SUCCESS + || !(~flags | (BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_FLAG)) || !dict_index_is_clust(index) || dict_index_is_ibuf(index)) { return(err); } - err = trx_undo_report_row_operation(flags, TRX_UNDO_INSERT_OP, - thr, index, entry, - NULL, 0, NULL, NULL, - &roll_ptr); - if (err != DB_SUCCESS) { - - return(err); + if (flags & BTR_NO_UNDO_LOG_FLAG) { + roll_ptr = 0; + } else { + err = trx_undo_report_row_operation(thr, index, entry, + NULL, 0, NULL, NULL, + &roll_ptr); + if (err != DB_SUCCESS) { + return(err); + } } /* Now we can fill in the roll ptr field in entry */ @@ -1712,9 +1715,10 @@ btr_cur_upd_lock_and_undo( /* Append the info about the update in the undo log */ - return(trx_undo_report_row_operation( - flags, TRX_UNDO_MODIFY_OP, thr, - index, NULL, update, + return((flags & BTR_NO_UNDO_LOG_FLAG) + ? DB_SUCCESS + : trx_undo_report_row_operation( + thr, index, NULL, update, cmpl_info, rec, offsets, roll_ptr)); } @@ -2985,7 +2989,7 @@ btr_cur_del_mark_set_clust_rec( return(err); } - err = trx_undo_report_row_operation(0, TRX_UNDO_MODIFY_OP, thr, + err = trx_undo_report_row_operation(thr, index, NULL, NULL, 0, rec, offsets, &roll_ptr); if (err != DB_SUCCESS) { diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index 359937e3583..a6e202d04e4 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -212,10 +213,6 @@ UNIV_INTERN dberr_t trx_undo_report_row_operation( /*==========================*/ - ulint flags, /*!< in: if BTR_NO_UNDO_LOG_FLAG bit is - set, does nothing */ - ulint op_type, /*!< in: TRX_UNDO_INSERT_OP or - TRX_UNDO_MODIFY_OP */ que_thr_t* thr, /*!< in: query thread */ dict_index_t* index, /*!< in: clustered index */ const dtuple_t* clust_entry, /*!< in: in the case of an insert, @@ -233,7 +230,7 @@ trx_undo_report_row_operation( inserted undo log record, 0 if BTR_NO_UNDO_LOG flag was specified */ - MY_ATTRIBUTE((nonnull(3,4,10), warn_unused_result)); + MY_ATTRIBUTE((nonnull(1,2,8), warn_unused_result)); /******************************************************************//** Copies an undo record to heap. This function can be called if we know that the undo log record exists. @@ -313,10 +310,6 @@ record */ storage fields: used by purge to free the external storage */ -/* Operation type flags used in trx_undo_report_row_operation */ -#define TRX_UNDO_INSERT_OP 1 -#define TRX_UNDO_MODIFY_OP 2 - #ifndef UNIV_NONINL #include "trx0rec.ic" #endif diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 5fa74846243..f694cdd3d5e 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1185,10 +1186,6 @@ UNIV_INTERN dberr_t trx_undo_report_row_operation( /*==========================*/ - ulint flags, /*!< in: if BTR_NO_UNDO_LOG_FLAG bit is - set, does nothing */ - ulint op_type, /*!< in: TRX_UNDO_INSERT_OP or - TRX_UNDO_MODIFY_OP */ que_thr_t* thr, /*!< in: query thread */ dict_index_t* index, /*!< in: clustered index */ const dtuple_t* clust_entry, /*!< in: in the case of an insert, @@ -1221,17 +1218,8 @@ trx_undo_report_row_operation( ut_ad(!srv_read_only_mode); ut_a(dict_index_is_clust(index)); ut_ad(!rec || rec_offs_validate(rec, index, offsets)); - - if (flags & BTR_NO_UNDO_LOG_FLAG) { - - *roll_ptr = 0; - - return(DB_SUCCESS); - } - ut_ad(thr); - ut_ad((op_type != TRX_UNDO_INSERT_OP) - || (clust_entry && !update && !rec)); + ut_ad(!clust_entry || (!update && !rec)); trx = thr_get_trx(thr); @@ -1252,8 +1240,7 @@ trx_undo_report_row_operation( /* If the undo log is not assigned yet, assign one */ - switch (op_type) { - case TRX_UNDO_INSERT_OP: + if (clust_entry) { undo = trx->insert_undo; if (undo == NULL) { @@ -1269,10 +1256,7 @@ trx_undo_report_row_operation( ut_ad(err == DB_SUCCESS); } - break; - default: - ut_ad(op_type == TRX_UNDO_MODIFY_OP); - + } else { undo = trx->update_undo; if (undo == NULL) { @@ -1296,23 +1280,14 @@ trx_undo_report_row_operation( buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE); do { - page_t* undo_page; - ulint offset; - - undo_page = buf_block_get_frame(undo_block); ut_ad(page_no == buf_block_get_page_no(undo_block)); - - switch (op_type) { - case TRX_UNDO_INSERT_OP: - offset = trx_undo_page_report_insert( - undo_page, trx, index, clust_entry, &mtr); - break; - default: - ut_ad(op_type == TRX_UNDO_MODIFY_OP); - offset = trx_undo_page_report_modify( + page_t* undo_page = buf_block_get_frame(undo_block); + ulint offset = clust_entry + ? trx_undo_page_report_insert( + undo_page, trx, index, clust_entry, &mtr) + : trx_undo_page_report_modify( undo_page, trx, index, rec, offsets, update, cmpl_info, &mtr); - } if (UNIV_UNLIKELY(offset == 0)) { /* The record did not fit on the page. We erase the @@ -1363,7 +1338,7 @@ trx_undo_report_row_operation( mutex_exit(&trx->undo_mutex); *roll_ptr = trx_undo_build_roll_ptr( - op_type == TRX_UNDO_INSERT_OP, + clust_entry != NULL, rseg->id, page_no, offset); return(DB_SUCCESS); } diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc index 0b554b271c4..c495e178b21 100644 --- a/storage/xtradb/btr/btr0cur.cc +++ b/storage/xtradb/btr/btr0cur.cc @@ -1269,18 +1269,21 @@ btr_cur_ins_lock_and_undo( index, thr, mtr, inherit); if (err != DB_SUCCESS + || !(~flags | (BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_FLAG)) || !dict_index_is_clust(index) || dict_index_is_ibuf(index)) { return(err); } - err = trx_undo_report_row_operation(flags, TRX_UNDO_INSERT_OP, - thr, index, entry, - NULL, 0, NULL, NULL, - &roll_ptr); - if (err != DB_SUCCESS) { - - return(err); + if (flags & BTR_NO_UNDO_LOG_FLAG) { + roll_ptr = 0; + } else { + err = trx_undo_report_row_operation(thr, index, entry, + NULL, 0, NULL, NULL, + &roll_ptr); + if (err != DB_SUCCESS) { + return(err); + } } /* Now we can fill in the roll ptr field in entry */ @@ -1851,9 +1854,10 @@ btr_cur_upd_lock_and_undo( /* Append the info about the update in the undo log */ - return(trx_undo_report_row_operation( - flags, TRX_UNDO_MODIFY_OP, thr, - index, NULL, update, + return((flags & BTR_NO_UNDO_LOG_FLAG) + ? DB_SUCCESS + : trx_undo_report_row_operation( + thr, index, NULL, update, cmpl_info, rec, offsets, roll_ptr)); } @@ -3175,7 +3179,7 @@ btr_cur_del_mark_set_clust_rec( return(err); } - err = trx_undo_report_row_operation(0, TRX_UNDO_MODIFY_OP, thr, + err = trx_undo_report_row_operation(thr, index, NULL, NULL, 0, rec, offsets, &roll_ptr); if (err != DB_SUCCESS) { diff --git a/storage/xtradb/include/trx0rec.h b/storage/xtradb/include/trx0rec.h index 359937e3583..a6e202d04e4 100644 --- a/storage/xtradb/include/trx0rec.h +++ b/storage/xtradb/include/trx0rec.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -212,10 +213,6 @@ UNIV_INTERN dberr_t trx_undo_report_row_operation( /*==========================*/ - ulint flags, /*!< in: if BTR_NO_UNDO_LOG_FLAG bit is - set, does nothing */ - ulint op_type, /*!< in: TRX_UNDO_INSERT_OP or - TRX_UNDO_MODIFY_OP */ que_thr_t* thr, /*!< in: query thread */ dict_index_t* index, /*!< in: clustered index */ const dtuple_t* clust_entry, /*!< in: in the case of an insert, @@ -233,7 +230,7 @@ trx_undo_report_row_operation( inserted undo log record, 0 if BTR_NO_UNDO_LOG flag was specified */ - MY_ATTRIBUTE((nonnull(3,4,10), warn_unused_result)); + MY_ATTRIBUTE((nonnull(1,2,8), warn_unused_result)); /******************************************************************//** Copies an undo record to heap. This function can be called if we know that the undo log record exists. @@ -313,10 +310,6 @@ record */ storage fields: used by purge to free the external storage */ -/* Operation type flags used in trx_undo_report_row_operation */ -#define TRX_UNDO_INSERT_OP 1 -#define TRX_UNDO_MODIFY_OP 2 - #ifndef UNIV_NONINL #include "trx0rec.ic" #endif diff --git a/storage/xtradb/trx/trx0rec.cc b/storage/xtradb/trx/trx0rec.cc index 5fa74846243..257e0380db3 100644 --- a/storage/xtradb/trx/trx0rec.cc +++ b/storage/xtradb/trx/trx0rec.cc @@ -1185,10 +1185,6 @@ UNIV_INTERN dberr_t trx_undo_report_row_operation( /*==========================*/ - ulint flags, /*!< in: if BTR_NO_UNDO_LOG_FLAG bit is - set, does nothing */ - ulint op_type, /*!< in: TRX_UNDO_INSERT_OP or - TRX_UNDO_MODIFY_OP */ que_thr_t* thr, /*!< in: query thread */ dict_index_t* index, /*!< in: clustered index */ const dtuple_t* clust_entry, /*!< in: in the case of an insert, @@ -1222,16 +1218,8 @@ trx_undo_report_row_operation( ut_a(dict_index_is_clust(index)); ut_ad(!rec || rec_offs_validate(rec, index, offsets)); - if (flags & BTR_NO_UNDO_LOG_FLAG) { - - *roll_ptr = 0; - - return(DB_SUCCESS); - } - ut_ad(thr); - ut_ad((op_type != TRX_UNDO_INSERT_OP) - || (clust_entry && !update && !rec)); + ut_ad(!clust_entry || (!update && !rec)); trx = thr_get_trx(thr); @@ -1252,8 +1240,7 @@ trx_undo_report_row_operation( /* If the undo log is not assigned yet, assign one */ - switch (op_type) { - case TRX_UNDO_INSERT_OP: + if (clust_entry) { undo = trx->insert_undo; if (undo == NULL) { @@ -1269,10 +1256,7 @@ trx_undo_report_row_operation( ut_ad(err == DB_SUCCESS); } - break; - default: - ut_ad(op_type == TRX_UNDO_MODIFY_OP); - + } else { undo = trx->update_undo; if (undo == NULL) { @@ -1296,23 +1280,15 @@ trx_undo_report_row_operation( buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE); do { - page_t* undo_page; - ulint offset; - - undo_page = buf_block_get_frame(undo_block); ut_ad(page_no == buf_block_get_page_no(undo_block)); - switch (op_type) { - case TRX_UNDO_INSERT_OP: - offset = trx_undo_page_report_insert( - undo_page, trx, index, clust_entry, &mtr); - break; - default: - ut_ad(op_type == TRX_UNDO_MODIFY_OP); - offset = trx_undo_page_report_modify( + page_t* undo_page = buf_block_get_frame(undo_block); + ulint offset = clust_entry + ? trx_undo_page_report_insert( + undo_page, trx, index, clust_entry, &mtr) + : trx_undo_page_report_modify( undo_page, trx, index, rec, offsets, update, cmpl_info, &mtr); - } if (UNIV_UNLIKELY(offset == 0)) { /* The record did not fit on the page. We erase the @@ -1363,7 +1339,7 @@ trx_undo_report_row_operation( mutex_exit(&trx->undo_mutex); *roll_ptr = trx_undo_build_roll_ptr( - op_type == TRX_UNDO_INSERT_OP, + clust_entry != NULL, rseg->id, page_no, offset); return(DB_SUCCESS); } From a436e349dfd0035b2b861ee772b47089043f5a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 May 2017 16:37:33 +0300 Subject: [PATCH 136/148] ibuf_get_volume_buffered_hash(): Use a proper type cast On 64-bit systems, the constant 1 would be 32-bit (int or unsigned) by default. Cast the constant to ulint before shifting to avoid a -fsanitize=undefined warning or any potential overflow. --- storage/innobase/ibuf/ibuf0ibuf.cc | 3 +-- storage/xtradb/ibuf/ibuf0ibuf.cc | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 55429e3cf34..49c1d1a4227 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -2895,8 +2895,7 @@ ibuf_get_volume_buffered_hash( fold = ut_fold_binary(data, len); hash += (fold / (CHAR_BIT * sizeof *hash)) % size; - bitmask = static_cast( - 1 << (fold % (CHAR_BIT * sizeof(*hash)))); + bitmask = static_cast(1) << (fold % (CHAR_BIT * sizeof(*hash))); if (*hash & bitmask) { diff --git a/storage/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc index e00adefe68f..414d7fc39be 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.cc +++ b/storage/xtradb/ibuf/ibuf0ibuf.cc @@ -2935,8 +2935,7 @@ ibuf_get_volume_buffered_hash( fold = ut_fold_binary(data, len); hash += (fold / (CHAR_BIT * sizeof *hash)) % size; - bitmask = static_cast( - 1 << (fold % (CHAR_BIT * sizeof(*hash)))); + bitmask = static_cast(1) << (fold % (CHAR_BIT * sizeof(*hash))); if (*hash & bitmask) { From 54bb04f7efc1d0842b3d8befb670f5d9f05cb211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 May 2017 16:39:57 +0300 Subject: [PATCH 137/148] Fix some __attribute__((nonnull)) misuse This fixes warnings that were emitted when running InnoDB test suites on a debug server that was compiled with GCC 7.1.0 using the flags -O3 -fsanitize=undefined. thd_requested_durability(): XtraDB can call this with trx->mysql_thd=NULL. Remove the function in InnoDB, because it is not used there. calc_row_difference(): Do not call memcmp(o_ptr, NULL, 0). innobase_index_name_is_reserved(): This can be called with key_info=NULL, num_of_keys=0. innobase_dropping_foreign(), innobase_check_foreigns_low(), innobase_check_foreigns(): This can be called with drop_fk=NULL, n_drop_fk=0. rec_convert_dtuple_to_rec_comp(): Do not invoke memcpy(end, NULL, 0). --- storage/innobase/handler/ha_innodb.cc | 17 ++--------------- storage/innobase/handler/ha_innodb.h | 4 ++-- storage/innobase/handler/handler0alter.cc | 13 +++++++------ storage/innobase/include/ha_prototypes.h | 12 ------------ storage/innobase/rem/rem0rec.cc | 6 ++++-- storage/xtradb/handler/ha_innodb.cc | 4 ++-- storage/xtradb/handler/ha_innodb.h | 2 +- storage/xtradb/handler/handler0alter.cc | 12 ++++++------ storage/xtradb/include/ha_prototypes.h | 3 ++- storage/xtradb/rem/rem0rec.cc | 6 ++++-- 10 files changed, 30 insertions(+), 49 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 26c9d0321d4..c0b12ab42df 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1321,19 +1321,6 @@ thd_is_replication_slave_thread( return((ibool) thd_slave_thread(thd)); } -/******************************************************************//** -Gets information on the durability property requested by thread. -Used when writing either a prepare or commit record to the log -buffer. @return the durability property. */ -UNIV_INTERN -enum durability_properties -thd_requested_durability( -/*=====================*/ - const THD* thd) /*!< in: thread handle */ -{ - return(thd_get_durability_property(thd)); -} - /******************************************************************//** Returns true if transaction should be flagged as read-only. @return true if the thd is marked as read-only */ @@ -7519,8 +7506,8 @@ calc_row_difference( } } - if (o_len != n_len || (o_len != UNIV_SQL_NULL && - 0 != memcmp(o_ptr, n_ptr, o_len))) { + if (o_len != n_len || (o_len != 0 && o_len != UNIV_SQL_NULL + && 0 != memcmp(o_ptr, n_ptr, o_len))) { /* The field has changed */ ufield = uvect->fields + n_changed; diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 9ddb1600378..46d689ce1e8 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation. +Copyright (c) 2013, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -476,7 +476,7 @@ innobase_index_name_is_reserved( const KEY* key_info, /*!< in: Indexes to be created */ ulint num_of_keys) /*!< in: Number of indexes to be created. */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + MY_ATTRIBUTE((nonnull(1), warn_unused_result)); /*****************************************************************//** Determines InnoDB table flags. diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index dc084dc1b95..8d6f3e79f61 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -2277,10 +2278,10 @@ online_retry_drop_indexes_with_trx( @param drop_fk constraints being dropped @param n_drop_fk number of constraints that are being dropped @return whether the constraint is being dropped */ -inline MY_ATTRIBUTE((pure, nonnull, warn_unused_result)) +MY_ATTRIBUTE((pure, nonnull(1), warn_unused_result)) +inline bool innobase_dropping_foreign( -/*======================*/ const dict_foreign_t* foreign, dict_foreign_t** drop_fk, ulint n_drop_fk) @@ -2304,10 +2305,10 @@ column that is being dropped or modified to NOT NULL. @retval true Not allowed (will call my_error()) @retval false Allowed */ -static MY_ATTRIBUTE((pure, nonnull, warn_unused_result)) +MY_ATTRIBUTE((pure, nonnull(1,4), warn_unused_result)) +static bool innobase_check_foreigns_low( -/*========================*/ const dict_table_t* user_table, dict_foreign_t** drop_fk, ulint n_drop_fk, @@ -2404,10 +2405,10 @@ column that is being dropped or modified to NOT NULL. @retval true Not allowed (will call my_error()) @retval false Allowed */ -static MY_ATTRIBUTE((pure, nonnull, warn_unused_result)) +MY_ATTRIBUTE((pure, nonnull(1,2,3,4), warn_unused_result)) +static bool innobase_check_foreigns( -/*====================*/ Alter_inplace_info* ha_alter_info, const TABLE* altered_table, const TABLE* old_table, diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 75b81e26f2f..488ed0257a7 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -126,18 +126,6 @@ thd_is_replication_slave_thread( /*============================*/ THD* thd); /*!< in: thread handle */ -/******************************************************************//** -Gets information on the durability property requested by thread. -Used when writing either a prepare or commit record to the log -buffer. -@return the durability property. */ -UNIV_INTERN -enum durability_properties -thd_requested_durability( -/*=====================*/ - const THD* thd) /*!< in: thread handle */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); - /******************************************************************//** Returns true if the transaction this thread is processing has edited non-transactional tables. Used by the deadlock detector when deciding diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index a95e9c23613..a42f8f95083 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -1285,8 +1285,10 @@ rec_convert_dtuple_to_rec_comp( } } - memcpy(end, dfield_get_data(field), len); - end += len; + if (len) { + memcpy(end, dfield_get_data(field), len); + end += len; + } } } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 9af3c7272fe..0f57878ace3 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -8202,8 +8202,8 @@ calc_row_difference( } } - if (o_len != n_len || (o_len != UNIV_SQL_NULL && - 0 != memcmp(o_ptr, n_ptr, o_len))) { + if (o_len != n_len || (o_len != 0 && o_len != UNIV_SQL_NULL + && 0 != memcmp(o_ptr, n_ptr, o_len))) { /* The field has changed */ ufield = uvect->fields + n_changed; diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 38e45647a7c..faf1e5475b5 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -484,7 +484,7 @@ innobase_index_name_is_reserved( const KEY* key_info, /*!< in: Indexes to be created */ ulint num_of_keys) /*!< in: Number of indexes to be created. */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + MY_ATTRIBUTE((nonnull(1), warn_unused_result)); /*****************************************************************//** Determines InnoDB table flags. diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 3d20c9abccf..f60d9938c39 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -2278,10 +2278,10 @@ online_retry_drop_indexes_with_trx( @param drop_fk constraints being dropped @param n_drop_fk number of constraints that are being dropped @return whether the constraint is being dropped */ -inline MY_ATTRIBUTE((pure, nonnull, warn_unused_result)) +MY_ATTRIBUTE((pure, nonnull(1), warn_unused_result)) +inline bool innobase_dropping_foreign( -/*======================*/ const dict_foreign_t* foreign, dict_foreign_t** drop_fk, ulint n_drop_fk) @@ -2305,10 +2305,10 @@ column that is being dropped or modified to NOT NULL. @retval true Not allowed (will call my_error()) @retval false Allowed */ -static MY_ATTRIBUTE((pure, nonnull, warn_unused_result)) +MY_ATTRIBUTE((pure, nonnull(1,4), warn_unused_result)) +static bool innobase_check_foreigns_low( -/*========================*/ const dict_table_t* user_table, dict_foreign_t** drop_fk, ulint n_drop_fk, @@ -2405,10 +2405,10 @@ column that is being dropped or modified to NOT NULL. @retval true Not allowed (will call my_error()) @retval false Allowed */ -static MY_ATTRIBUTE((pure, nonnull, warn_unused_result)) +MY_ATTRIBUTE((pure, nonnull(1,2,3,4), warn_unused_result)) +static bool innobase_check_foreigns( -/*====================*/ Alter_inplace_info* ha_alter_info, const TABLE* altered_table, const TABLE* old_table, diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index b1975287f23..1dfbfe7c8fb 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -143,7 +144,7 @@ enum durability_properties thd_requested_durability( /*=====================*/ const THD* thd) /*!< in: thread handle */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + MY_ATTRIBUTE((warn_unused_result)); /******************************************************************//** Returns true if the transaction this thread is processing has edited diff --git a/storage/xtradb/rem/rem0rec.cc b/storage/xtradb/rem/rem0rec.cc index c6d9ba935e1..1316c4f35c6 100644 --- a/storage/xtradb/rem/rem0rec.cc +++ b/storage/xtradb/rem/rem0rec.cc @@ -1290,8 +1290,10 @@ rec_convert_dtuple_to_rec_comp( } } - memcpy(end, dfield_get_data(field), len); - end += len; + if (len) { + memcpy(end, dfield_get_data(field), len); + end += len; + } } } From bc622fb280638d0ccbc9ba038055525a4074dfdb Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Thu, 18 May 2017 10:47:16 +0300 Subject: [PATCH 138/148] List of unstable tests for 10.0.31 release --- mysql-test/unstable-tests | 145 ++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 77 deletions(-) diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index 6c84d8d3ba6..0a2d5a85e51 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -1,17 +1,17 @@ ############################################################################## # # List the test cases which, unlike tests from disabled.def files, -# can still be run on the current tree meaningfully, but are known +# can still be run on the current tree meaningfully, but are known # or suspected to fail sporadically on different reasons. # # Most common reasons are either test failures observed in buildbot, -# or recent modifications to the tests which make their stability -# unknown. +# or recent modifications to the tests which make their stability +# unknown. # -# Tests included due to recent modifications are later removed from the -# list, if during a certain period they do not fail (and are not -# modified again). Tests included due to intermittent failures are -# removed when corresponding bug reports are closed. +# Tests included due to recent modifications are later removed from the +# list, if during a certain period they do not fail (and are not +# modified again). Tests included due to intermittent failures are +# removed when corresponding bug reports are closed. # # Separate the test case name and the comment with ':'. # @@ -19,44 +19,46 @@ # # '*' wildcard in testcase names is supported. # -# To use the list, run MTR with --skip-test-list=unstable-tests option. +# To use the list, run MTR with --skip-test-list=unstable-tests option. # ############################################################################## -main.alter_table : Modified in 10.0.30 main.count_distinct2 : MDEV-11768 - timeout main.create_delayed : MDEV-10605 - failed with timeout main.debug_sync : MDEV-10607 - internal error -main.derived : Modified in 10.0.30 main.derived_opt : MDEV-11768 - timeout -main.events_restart : MDEV-11221 - assertion failure -main.grant : Modified in 10.0.30 +main.derived_view : Modified in 10.0.31 +main.events_2 : Modified in 10.0.31 +main.events_slowlog : MDEV-12821 - wrong result +main.func_regexp_pcre : Modified in 10.0.31 +main.gis : Modified in 10.0.31 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout main.index_merge_innodb : MDEV-7142 - wrong result main.innodb_mysql_lock : MDEV-7861 - sporadic lock detection failure -main.join_nested : Modified in 10.0.30 +main.loaddata : Modified in 10.0.31 +main.log_tables-big : Modified in 10.0.31 main.mdev-504 : MDEV-10607 - sporadic "can't connect" main.mdev375 : MDEV-10607 - sporadic "can't connect" main.merge : MDEV-10607 - sporadic "can't connect" -main.mysqldump : Modified in 10.0.30 +main.mysqld--help : Modified in 10.0.31 +main.mysqldump : Modified in 10.0.31 main.mysqlhotcopy_myisam : MDEV-10995 - test hangs on debug build main.mysqltest : MDEV-9269 - fails on Alpha -main.partition_innodb : Modified in 10.0.30 -main.partition_myisam : Modified in 10.0.30 main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count -main.range_vs_index_merge : Modified in 10.0.30 -main.repair_symlink-5543 : Modified in 10.0.30 main.show_explain : MDEV-10674 - wrong result -main.signal_demo3 : MDEV-11720 - Thread stack overrun on Solaris -main.sp : Modified in 10.0.30 main.sp_notembedded : MDEV-10607 - internal error main.sp-security : MDEV-10607 - sporadic "can't connect" -main.subselect_innodb : MDEV-10614 - sporadic wrong results -main.symlink-aria-11902 : Added in 10.0.30 -main.symlink-myisam-11902 : Added in 10.0.30 -main.table_elim : Modified in 10.0.30 -main.view : Modified in 10.0.30 +main.subselect4 : Modified in 10.0.31 +main.subselect_exists2in : Modified in 10.0.31 +main.subselect_innodb : MDEV-10614 - sporadic wrong results; modified in 10.0.31 +main.subselect_mat_cost_bugs : Modified in 10.0.31 +main.subselect_sj : Modified in 10.0.31 +main.subselect_sj_mat : Modified in 10.0.31 +main.subselect_sj2_mat : Modified in 10.0.31 +main.symlink : Modified in 10.0.31 +main.symlink-myisam-11902 : Modified in 10.0.31 +main.view : Modified in 10.0.31 main.xa : MDEV-11769 - lock wait timeout #---------------------------------------------------------------- @@ -70,15 +72,16 @@ archive.mysqlhotcopy_archive : MDEV-10995 - test hangs on debug build #---------------------------------------------------------------- binlog.binlog_commit_wait : MDEV-10150 - Error: too much time elapsed -binlog.binlog_max_binlog_stmt_cache_size : Added in 10.0.30 binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint #---------------------------------------------------------------- +connect.jdbc_new : Modified in 10.0.31 connect.tbl : MDEV-9844, MDEV-10179 - sporadic crashes, valgrind warnings, wrong results -connect.xml : Uses xsample2.xml modified in 10.0.30 -connect.xml_zip : Added in 10.0.30 -connect.zip : Added in 10.0.30 + +#---------------------------------------------------------------- + +csv.read_only : Added in 10.0.31 #---------------------------------------------------------------- @@ -86,7 +89,6 @@ engines/rr_trx.* : MDEV-10998 - tests not maintained #---------------------------------------------------------------- -federated_bug_35333 : Modified in 10.0.30 federated.federatedx : MDEV-10617 - Wrong checksum, timeouts federated.federated_innodb : MDEV-10617, MDEV-10417 - Wrong checksum, timeouts, fails on Mips federated.federated_partition : MDEV-10417 - Fails on Mips @@ -101,22 +103,19 @@ funcs_2/charset.* : MDEV-10999 - test not maintained #---------------------------------------------------------------- -innodb.alter_key_block_size-11757 : Added in 10.0.30 -innodb.binlog_consistent : MDEV-10618 - Server fails to start +innodb.autoinc_debug : Added in 10.0.31 +innodb.binlog_consistent : MDEV-10618 - Server fails to start innodb.group_commit_crash_no_optimize_thread : MDEV-11770 - checksum mismatch +innodb.innodb-alter-debug : Added in 10.0.31 +innodb.innodb-alter-nullable : Added in 10.0.31 innodb.innodb-alter-table : MDEV-10619 - Testcase timeout -innodb.innodb_blob_unrecoverable_crash : Modified in 10.0.30 -innodb.innodb_bug14676111 : Modified in 10.0.30 +innodb.innodb_bug14676111 : Modified in 10.0.31 innodb.innodb_bug30423 : MDEV-7311 - Wrong number of rows in the plan -innodb.innodb_bug59641 : Modified in 10.0.30 -innodb.innodb-get-fk : Modified in 10.0.30 +innodb.innodb-index-online-norebuild : Added in 10.0.31 +innodb.log_file_size : Modified in 10.0.31 innodb.innodb_monitor : MDEV-10939 - Testcase timeout -innodb.log_file_size : Added in 10.0.30 -innodb.read_only_recovery : Added in 10.0.30 -innodb.xa_recovery : Modified in 10.0.30 -innodb_fts.create : Added in 10.0.30 -innodb_fts.innodb_fts_stopword_charset : MDEV-12052 - Crash on shutdown +innodb_fts.innodb_fts_stopword_charset : MDEV-12052 - Crash on shutdown; modified in 10.0.31 #---------------------------------------------------------------- @@ -134,29 +133,13 @@ multi_source.multisource : MDEV-10417 - Fails on Mips multi_source.simple : MDEV-4633 - Wrong slave status output multi_source.status_vars : MDEV-4632 - failed while waiting for Slave_received_heartbeats +#---------------------------------------------------------------- + +myisam_debug : Modified in 10.0.31 #---------------------------------------------------------------- -oqgraph.regression_mdev6282 : Modified in 10.0.30 -oqgraph.regression_mdev6345 : Modified in 10.0.30 - -#---------------------------------------------------------------- - -parts.partition_bigint_innodb : Added in 10.0.30 -parts.partition_bigint_myisam : Added in 10.0.30 -parts.partition_double_innodb : Added in 10.0.30 -parts.partition_double_myisam : Added in 10.0.30 parts.partition_exch_qa_10 : MDEV-11765 - wrong result -parts.partition_float_innodb : Modified in 10.0.30 -parts.partition_float_myisam : Modified in 10.0.30 -parts.partition_int_innodb : Modified in 10.0.30 -parts.partition_int_myisam : Modified in 10.0.30 -parts.partition_mediumint_innodb : Added in 10.0.30 -parts.partition_mediumint_myisam : Added in 10.0.30 -parts.partition_smallint_innodb : Added in 10.0.30 -parts.partition_smallint_myisam : Added in 10.0.30 -parts.partition_tinyint_innodb : Added in 10.0.30 -parts.partition_tinyint_myisam : Added in 10.0.30 #---------------------------------------------------------------- @@ -165,7 +148,7 @@ perfschema.func_mutex : MDEV-5708 - fails for s390x perfschema.hostcache_ipv6_ssl : MDEV-10696 - crash on shutdown perfschema.socket_summary_by_event_name_func : MDEV-10622 - Socket summary tables do not match perfschema.stage_mdl_procedure : MDEV-11545 - Wrong result -perfschema.threads_mysql : MDEV-12177 - Wrong result +perfschema.start_server_1_digest : Added in 10.0.31 perfschema_stress.* : MDEV-10996 - tests not maintained @@ -191,13 +174,11 @@ rpl.rpl_ddl : MDEV-10417 - Fails on Mips rpl.rpl_gtid_crash : MDEV-9501 - Warning: failed registering on master rpl.rpl_gtid_stop_start : MDEV-10629 - Crash on shutdown rpl.rpl_gtid_until : MDEV-10625 - warnings in error log -rpl.rpl_heartbeat_basic : Modified in 10.0.30 rpl.rpl_innodb_bug30888 : MDEV-10417 - Fails on Mips rpl.rpl_insert : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_insert_delayed : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_invoked_features : MDEV-10417 - Fails on Mips rpl.rpl_mdev6020 : MDEV-10630, MDEV-10417 - Timeouts, fails on Mips -rpl.rpl_mdev6386 : Modified in 10.0.30 rpl.rpl_parallel : MDEV-10653 - Timeouts rpl.rpl_parallel_temptable : MDEV-10356 - Crash in close_thread_tables rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips @@ -238,31 +219,46 @@ stress.ddl_innodb : MDEV-10635 - Testcase timeout sys_vars.autocommit_func2 : MDEV-9329 - Fails on Ubuntu/s390x sys_vars.innodb_buffer_pool_dump_pct_basic : MDEV-10651 - sporadic failure on file_exists -sys_vars.innodb_force_recovery_crash_basic : Modified in 10.0.30 -sys_vars.innodb_stats_include_delete_marked_basic : Added in 10.0.30 sys_vars.innodb_status_output_basic : MDEV-12174 - Timeout -sys_vars.secure_file_priv : Modified in 10.0.30 sys_vars.thread_cache_size_func : MDEV-11775 - wrong result #---------------------------------------------------------------- +tokudb.background_job_manager : Modified in 10.0.31 +tokudb.bug-1657908 : Added in 10.0.31 +tokudb.card_auto_analyze_lots : Modified in 10.0.31 +tokudb.change_column_all_1000_10 : MDEV-12640 - Lost connection during query +tokudb.change_column_bin : MDEV-12640 - Lost connection during query +tokudb.change_column_char : MDEV-12822 - Lost connection during query tokudb.cluster_filter_unpack_varchar : MDEV-10636 - Wrong execution plan +tokudb.dir_cmd : Added in 10.0.31 tokudb.dir_per_db : MDEV-11537 - wrong result -tokudb.dir_per_db_rename_to_nonexisting_schema : Added in 10.0.30 -tokudb.gap_lock_error : Added in 10.0.30 -tokudb.locks-select-update-3 : Modified in 10.0.30 -tokudb.percona_kill_idle_trx_tokudb : Added in 10.0.30 +tokudb.dir_per_db_rename_to_nonexisting_schema : MDEV-12823 - Valgrind +tokudb.hotindex-update-1 : MDEV-12640 - Lost connection during query +tokudb.i_s_tokudb_lock_waits_timeout : Modified in 10.0.31 +tokudb.i_s_tokudb_locks : Modified in 10.0.31 +tokudb.rows-32m-rand-insert : MDEV-12640 - Lost connection during query +tokudb.rows-32m-seq-insert : MDEV-12640 - Lost connection during query tokudb_backup.* : MDEV-11001 - tests don't work + +tokudb_backup.backup_master_info : Added in 10.0.31 +tokudb_backup.backup_master_state : Added in 10.0.31 +tokudb_backup.empty_slave_info_file : Added in 10.0.31 +tokudb_backup.innodb_use_native_aio_enabled : Added in 10.0.31 +tokudb_backup.rpl_safe_slave : Added in 10.0.31 +tokudb_backup.rpl_tokudb_commit_sync : Added in 10.0.31 + tokudb_bugs.checkpoint_lock : MDEV-10637 - Wrong processlist output tokudb_bugs.checkpoint_lock_3 : MDEV-10637 - Wrong processlist output +tokudb_bugs.db233 : Modified in 10.0.31 +tokudb_bugs.frm_store2 : MDEV-12823 - Valgrind +tokudb_bugs.leak172 : Modified in 10.0.31 tokudb_bugs.xa : MDEV-11804 - Lock wait timeout tokudb_rpl.* : MDEV-11001 - tests don't work tokudb_sys_vars.* : MDEV-11001 - tests don't work -rpl-tokudb.rpl_extra_col_slave_tokudb : Result file modified in 10.0.30 - #---------------------------------------------------------------- unit.ma_test_loghandler : MDEV-10638 - record read not ok @@ -272,10 +268,5 @@ unit.pfs : MySQL:84457 - unittest pft-t failing vcol.not_supported : MDEV-10639 - Testcase timeout vcol.vcol_keys_innodb : MDEV-10639 - Testcase timeout -vcol.vcol_misc : Modified in 10.0.30 -vcol.vcol_select_myisam : Modified in 10.0.30 -vcol.vcol_trigger_sp_innodb : Include file modified in 10.0.30 -vcol.vcol_trigger_sp_myisam : Include file modified in 10.0.30 -vcol.wrong_arena : Added in 10.0.30 #---------------------------------------------------------------- From 648d86615043e76633ac536b1000ba86abbc8af1 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 18 May 2017 12:24:44 +0200 Subject: [PATCH 139/148] Fixed typo in the case operator. --- mysys/ma_dyncol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 7cd0c2b02df..85c0b947497 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -4039,6 +4039,7 @@ mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val) *dbl= strtod(str, &end); if (*end != '\0') rc= ER_DYNCOL_TRUNCATED; + break; } case DYN_COL_DECIMAL: if (decimal2double(&val->x.decimal.value, dbl) != E_DEC_OK) From b5cdf01404dd352bb9aa7b58cad76f7a500b32d2 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Thu, 18 May 2017 17:13:37 +0530 Subject: [PATCH 140/148] MDEV-11092 Assertion `!writer.checksum_len || writer.remains == 0' failed Problem:- This crash happens because logged stmt is quite big and while writing Annotate_rows_log_event it throws EFBIG error but we ignore this error and do not call cache_data->set_incident(). Solution:- When we normally write Binlog_log_event we check for error EFBIG, but we did do this for Annotate_rows_log_event. We check for this error and call cache_data->set_incident() accordingly. # Conflicts: # sql/log.cc --- mysql-test/suite/rpl/r/rpl_mdev-11092.result | 17 +++++++ mysql-test/suite/rpl/t/rpl_mdev-11092.test | 53 ++++++++++++++++++++ sql/log.cc | 7 +++ 3 files changed, 77 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_mdev-11092.result create mode 100644 mysql-test/suite/rpl/t/rpl_mdev-11092.test diff --git a/mysql-test/suite/rpl/r/rpl_mdev-11092.result b/mysql-test/suite/rpl/r/rpl_mdev-11092.result new file mode 100644 index 00000000000..b2de9e5f573 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_mdev-11092.result @@ -0,0 +1,17 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("Slave SQL: The incident LOST_EVENTS occured on the master. .*"); +SET GLOBAL max_binlog_cache_size = 4096; +SET GLOBAL binlog_cache_size = 4096; +SET GLOBAL max_binlog_stmt_cache_size = 4096; +SET GLOBAL binlog_stmt_cache_size = 4096; +CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=MYISAM; +ERROR HY000: Writing one row to the row-based binary log failed +include/wait_for_slave_sql_error_and_skip.inc [errno=1590] +SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; +SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; +SET GLOBAL max_binlog_stmt_cache_size= ORIGINAL_VALUE; +SET GLOBAL binlog_stmt_cache_size= ORIGINAL_VALUE; +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev-11092.test b/mysql-test/suite/rpl/t/rpl_mdev-11092.test new file mode 100644 index 00000000000..c8b2b7f2ad1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev-11092.test @@ -0,0 +1,53 @@ +--source include/have_innodb.inc +--source include/master-slave.inc +--source include/not_embedded.inc +--source include/not_windows.inc +--source include/have_binlog_format_row.inc + +######################################################################################## +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("Slave SQL: The incident LOST_EVENTS occured on the master. .*"); + +let $old_max_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_cache_size", Value, 1); +let $old_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_cache_size", Value, 1); +let $old_max_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_stmt_cache_size", Value, 1); +let $old_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_stmt_cache_size", Value, 1); + +SET GLOBAL max_binlog_cache_size = 4096; +SET GLOBAL binlog_cache_size = 4096; +SET GLOBAL max_binlog_stmt_cache_size = 4096; +SET GLOBAL binlog_stmt_cache_size = 4096; +disconnect master; +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); + +CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=MYISAM; + +let $data = `select concat('"', repeat('a',2000), '"')`; + +connection master; + +--disable_query_log +--error ER_BINLOG_ROW_LOGGING_FAILED +eval INSERT INTO t1 (a, data) VALUES (2, + CONCAT($data, $data, $data, $data, $data, $data)); +--enable_query_log + +# Incident event +# 1590=ER_SLAVE_INCIDENT +--let $slave_sql_errno= 1590 +--source include/wait_for_slave_sql_error_and_skip.inc + +connection master; + +--replace_result $old_max_binlog_cache_size ORIGINAL_VALUE +--eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size +--replace_result $old_binlog_cache_size ORIGINAL_VALUE +--eval SET GLOBAL binlog_cache_size= $old_binlog_cache_size +--replace_result $old_max_binlog_stmt_cache_size ORIGINAL_VALUE +--eval SET GLOBAL max_binlog_stmt_cache_size= $old_max_binlog_stmt_cache_size +--replace_result $old_binlog_stmt_cache_size ORIGINAL_VALUE +--eval SET GLOBAL binlog_stmt_cache_size= $old_binlog_stmt_cache_size + +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/sql/log.cc b/sql/log.cc index dc87c39730c..f8c256e645f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4887,13 +4887,20 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional, IO_CACHE *file= cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional)); + binlog_cache_data *cache_data= + cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional)); + if (with_annotate && *with_annotate) { Annotate_rows_log_event anno(current_thd, is_transactional, false); /* Annotate event should be written not more than once */ *with_annotate= 0; if ((error= anno.write(file))) + { + if (my_errno == EFBIG) + cache_data->set_incident(); DBUG_RETURN(error); + } } if ((error= the_event.write(file))) DBUG_RETURN(error); From 3c7af6c4904d11b324f911a7a7149f17d3f86ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 18 May 2017 15:46:31 +0300 Subject: [PATCH 141/148] Fix xtradb handler compilation post merge --- storage/xtradb/handler/ha_innodb.cc | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index da486507cfc..d0eef98f064 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -768,6 +768,31 @@ innobase_purge_changed_page_bitmaps( /*================================*/ ulonglong lsn) __attribute__((unused)); /*!< in: LSN to purge files up to */ +/** Empty free list algorithm. +Checks if buffer pool is big enough to enable backoff algorithm. +InnoDB empty free list algorithm backoff requires free pages +from LRU for the best performance. +buf_LRU_buf_pool_running_out cancels query if 1/4 of +buffer pool belongs to LRU or freelist. +At the same time buf_flush_LRU_list_batch +keeps up to BUF_LRU_MIN_LEN in LRU. +In order to avoid deadlock baclkoff requires buffer pool +to be at least 4*BUF_LRU_MIN_LEN, +but flush peformance is bad because of trashing +and additional BUF_LRU_MIN_LEN pages are requested. +@param[in] algorithm desired algorithm from srv_empty_free_list_t +@return true if it's possible to enable backoff. */ +static inline +bool +innodb_empty_free_list_algorithm_allowed( + srv_empty_free_list_t algorithm) +{ + long long buf_pool_pages = srv_buf_pool_size / srv_page_size + / srv_buf_pool_instances; + + return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) + || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF); +} /** Get the list of foreign keys referencing a specified table table. From 546a89ca58887ea0d89794f108bc864e05c2f74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 18 May 2017 16:16:18 +0300 Subject: [PATCH 142/148] Update xtradb and innodb version to 5.6.36 --- storage/innobase/include/univ.i | 2 +- storage/xtradb/include/univ.i | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index e310799b7c6..15147f87115 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 35 +#define INNODB_VERSION_BUGFIX 36 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index a82faa76eef..f554c50ff83 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 35 +#define INNODB_VERSION_BUGFIX 36 #ifndef PERCONA_INNODB_VERSION #define PERCONA_INNODB_VERSION 82.0 From 4a846e018d2e31a7c78e45fb40b865246b5abb11 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 18 May 2017 19:31:44 +0200 Subject: [PATCH 143/148] Make IF clear. --- storage/maria/ma_loghandler.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index bf2205f5a4c..16cd0a09af5 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -7814,8 +7814,24 @@ void translog_flush_buffers(TRANSLOG_ADDRESS *lsn, translog_force_current_buffer_to_finish(); translog_buffer_unlock(buffer); } - else if (log_descriptor.bc.buffer->prev_last_lsn != LSN_IMPOSSIBLE) + else { + if (log_descriptor.bc.buffer->last_lsn == LSN_IMPOSSIBLE) + { + /* + In this case both last_lsn & prev_last_lsn are LSN_IMPOSSIBLE + otherwise it will go in the first IF because LSN_IMPOSSIBLE less + then any real LSN and cmp_translog_addr(*lsn, + log_descriptor.bc.buffer->prev_last_lsn) will be TRUE + */ + DBUG_ASSERT(log_descriptor.bc.buffer->prev_last_lsn == + LSN_IMPOSSIBLE); + DBUG_PRINT("info", ("There is no LSNs yet generated => do nothing")); + translog_unlock(); + DBUG_VOID_RETURN; + } + + DBUG_ASSERT(log_descriptor.bc.buffer->prev_last_lsn != LSN_IMPOSSIBLE); /* fix lsn if it was horizon */ *lsn= log_descriptor.bc.buffer->prev_last_lsn; DBUG_PRINT("info", ("LSN to flush fixed to prev last lsn: (%lu,0x%lx)", @@ -7824,13 +7840,6 @@ void translog_flush_buffers(TRANSLOG_ADDRESS *lsn, TRANSLOG_BUFFERS_NO); translog_unlock(); } - else if (log_descriptor.bc.buffer->last_lsn == LSN_IMPOSSIBLE) - { - DBUG_PRINT("info", ("There is no LSNs yet generated => do nothing")); - translog_unlock(); - DBUG_VOID_RETURN; - } - /* flush buffers */ *sent_to_disk= translog_get_sent_to_disk(); if (cmp_translog_addr(*lsn, *sent_to_disk) > 0) From 335c4ab790254462753ba4ed8b074c5847b2708f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 19 May 2017 09:51:44 +0300 Subject: [PATCH 144/148] Remove dead code added in merge commit d8b45b0c004edc0b91029b232d7cc9aad02cc822 In a merge conflict resolution, callers of the added function rec_field_len_in_chars() were removed, but the function itself was not. --- storage/xtradb/row/row0sel.cc | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index 17920c91743..b0c6565ab2e 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -3646,30 +3646,6 @@ row_search_idx_cond_check( return(result); } - -/** Return the record field length in characters. -@param[in] col table column of the field -@param[in] field_no field number -@param[in] rec physical record -@param[in] offsets field offsets in the physical record - -@return field length in characters */ -static -size_t -rec_field_len_in_chars(const dict_col_t &col, - const ulint field_no, - const rec_t *rec, - const ulint *offsets) -{ - const ulint cset = dtype_get_charset_coll(col.prtype); - const CHARSET_INFO* cs = all_charsets[cset]; - ulint rec_field_len; - const char* rec_field = reinterpret_cast( - rec_get_nth_field( - rec, offsets, field_no, &rec_field_len)); - return(cs->cset->numchars(cs, rec_field, rec_field + rec_field_len)); -} - /********************************************************************//** Searches for rows in the database. This is used in the interface to MySQL. This function opens a cursor, and also implements fetch next From 7d57ba6e28f8dd5f6ab48b0b99d110c2363b576d Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Fri, 19 May 2017 13:02:45 +0530 Subject: [PATCH 145/148] MDEV-11092 :- Fix Previous commit of MDEV-11092 --- mysql-test/suite/rpl/t/rpl_mdev-11092.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 mysql-test/suite/rpl/t/rpl_mdev-11092.opt diff --git a/mysql-test/suite/rpl/t/rpl_mdev-11092.opt b/mysql-test/suite/rpl/t/rpl_mdev-11092.opt new file mode 100644 index 00000000000..7f1d270d29f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev-11092.opt @@ -0,0 +1 @@ +--binlog_checksum=1 --binlog-annotate-row-events=1 From 7c03edf2fe66855a8ce8f2575c3aaf66af975377 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 17 May 2017 15:16:24 +0200 Subject: [PATCH 146/148] MDEV-6262 analyze the coverity report on mariadb uploaded 10.0, analyzed everything with the Impact=High (and a couple of Medium) --- client/mysql.cc | 1 - client/mysql_upgrade.c | 4 ++-- client/mysqladmin.cc | 19 ++++++++++++------- client/mysqlbinlog.cc | 2 +- client/mysqldump.c | 5 +++-- client/mysqltest.cc | 5 ++--- mysys/lf_hash.c | 3 +++ mysys/ma_dyncol.c | 1 + mysys/waiting_threads.c | 2 +- plugin/auth_pam/auth_pam.c | 1 + plugin/feedback/sender_thread.cc | 2 +- plugin/server_audit/server_audit.c | 5 +++++ sql-common/client_plugin.c | 11 ++++++----- sql/discover.cc | 3 +-- sql/filesort.cc | 1 + sql/mysqld.cc | 2 +- sql/opt_range.cc | 7 ++++--- sql/records.cc | 2 +- sql/sql_prepare.cc | 2 +- sql/sql_repl.cc | 6 +++--- sql/sql_show.cc | 2 +- sql/sys_vars.cc | 3 +++ storage/csv/ha_tina.cc | 15 ++++++++------- storage/maria/ma_check.c | 1 + storage/maria/ma_loghandler.c | 28 +++++++++++++++++----------- storage/maria/ma_packrec.c | 2 +- storage/maria/ma_recovery.c | 3 +-- storage/myisam/ha_myisam.cc | 2 +- storage/myisam/mi_open.c | 2 +- storage/xtradb/buf/buf0dump.cc | 1 + storage/xtradb/dict/dict0mem.cc | 4 ++-- storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/log/log0online.cc | 1 + storage/xtradb/srv/srv0srv.cc | 3 ++- strings/ctype.c | 2 +- tests/mysql_client_test.c | 1 + unittest/mysys/ma_dyncol-t.c | 3 +++ 37 files changed, 96 insertions(+), 63 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index a9310a87d8e..3461f8bbc75 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3061,7 +3061,6 @@ static int com_server_help(String *buffer __attribute__((unused)), { unsigned int num_fields= mysql_num_fields(result); my_ulonglong num_rows= mysql_num_rows(result); - mysql_fetch_fields(result); if (num_fields==3 && num_rows==1) { if (!(cur= mysql_fetch_row(result))) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index f2d94871f07..397a252cdc0 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1042,7 +1042,7 @@ static int check_version_match(void) int main(int argc, char **argv) { - char self_name[FN_REFLEN]; + char self_name[FN_REFLEN + 1]; MY_INIT(argv[0]); @@ -1050,7 +1050,7 @@ int main(int argc, char **argv) if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0) #endif { - strncpy(self_name, argv[0], FN_REFLEN); + strmake_buf(self_name, argv[0]); } if (init_dynamic_string(&ds_args, "", 512, 256) || diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index bab94d6e5ee..e85d306c834 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -614,6 +614,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) static int execute_commands(MYSQL *mysql,int argc, char **argv) { + int ret = 0; const char *status; /* MySQL documentation relies on the fact that mysqladmin will @@ -1107,7 +1108,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) if (strcmp(typed_password, verified) != 0) { my_printf_error(0,"Passwords don't match",MYF(ME_BELL)); - return -1; + ret = -1; + goto password_done; } } else @@ -1134,7 +1136,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) { my_printf_error(0, "Could not determine old_passwords setting from server; error: '%s'", error_flags, mysql_error(mysql)); - return -1; + ret = -1; + goto password_done; } else { @@ -1145,7 +1148,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) "Could not get old_passwords setting from " "server; error: '%s'", error_flags, mysql_error(mysql)); - return -1; + ret = -1; + goto password_done; } if (!mysql_num_rows(res)) old= 1; @@ -1170,15 +1174,15 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) { my_printf_error(0, "Can't turn off logging; error: '%s'", error_flags, mysql_error(mysql)); - return -1; + ret = -1; } + else if (mysql_query(mysql,buff)) { if (mysql_errno(mysql)!=1290) { my_printf_error(0,"unable to change password; error: '%s'", error_flags, mysql_error(mysql)); - return -1; } else { @@ -1192,9 +1196,10 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) " --skip-grant-tables).\n" "Use: \"mysqladmin flush-privileges password '*'\"" " instead", error_flags); - return -1; } + ret = -1; } +password_done: /* free up memory from prompted password */ if (typed_password != argv[1]) { @@ -1296,7 +1301,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) return 1; } } - return 0; + return ret; } /** diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 29355d013c7..804c6314ef9 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1976,7 +1976,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags); size_t tlen = strlen(logname); - if (tlen > UINT_MAX) + if (tlen > sizeof(buf) - 10) { error("Log name too long."); DBUG_RETURN(ERROR_STOP); diff --git a/client/mysqldump.c b/client/mysqldump.c index 245f24dd508..6877a5cee3b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2818,6 +2818,8 @@ static uint get_table_structure(char *table, char *db, char *table_type, my_free(scv_buff); + if (path) + my_fclose(sql_file, MYF(MY_WME)); DBUG_RETURN(0); } else @@ -5827,8 +5829,7 @@ static my_bool get_view_structure(char *table, char* db) dynstr_free(&ds_view); } - if (switch_character_set_results(mysql, default_charset)) - DBUG_RETURN(1); + switch_character_set_results(mysql, default_charset); /* If a separate .sql file was opened, close it now */ if (sql_file != md_result_file) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index d903484bd4d..f9715bfbfdb 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1721,13 +1721,12 @@ void log_msg(const char *fmt, ...) int cat_file(DYNAMIC_STRING* ds, const char* filename) { int fd; - size_t len; + int len; char buff[16384]; if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0) return 1; - while((len= my_read(fd, (uchar*)&buff, - sizeof(buff)-1, MYF(0))) > 0) + while((len= (int)my_read(fd, (uchar*)&buff, sizeof(buff)-1, MYF(0))) > 0) { char *p= buff, *start= buff,*end=buff+len; while (p < end) diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c index 0699f5d49fe..7edf5e3a03d 100644 --- a/mysys/lf_hash.c +++ b/mysys/lf_hash.c @@ -485,7 +485,10 @@ static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node, return -1; if (*el == NULL && bucket && unlikely(initialize_bucket(hash, el, parent, pins))) + { + my_free(dummy); return -1; + } dummy->hashnr= my_reverse_bits(bucket) | 0; /* dummy node */ dummy->key= dummy_key; dummy->keylen= 0; diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 85c0b947497..d0d6254d11c 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -4039,6 +4039,7 @@ mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val) *dbl= strtod(str, &end); if (*end != '\0') rc= ER_DYNCOL_TRUNCATED; + free(str); break; } case DYN_COL_DECIMAL: diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index 1fe6a0f9a1c..f2b1bbb5993 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -561,7 +561,7 @@ my_bool wt_resource_id_memcmp(const void *a, const void *b) { /* we use the fact that there's no padding in the middle of WT_RESOURCE_ID */ compile_time_assert(offsetof(WT_RESOURCE_ID, type) == sizeof(ulonglong)); - return memcmp(a, b, sizeof_WT_RESOURCE_ID); + return MY_TEST(memcmp(a, b, sizeof_WT_RESOURCE_ID)); } /** diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index fbca8bf9e93..a4d1deb8ada 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -141,6 +141,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) if (new_username && strcmp(new_username, info->user_name)) strncpy(info->authenticated_as, new_username, sizeof(info->authenticated_as)); + info->authenticated_as[sizeof(info->authenticated_as)-1]= 0; end: pam_end(pamh, status); diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 9417dc85b7d..4a7da3000ca 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -204,7 +204,7 @@ static void send_report(const char *when) /* otherwise, prepare the THD and TABLE_LIST, create and fill the temporary table with data just like - SELECT * FROM IFROEMATION_SCHEMA.feedback is doing, + SELECT * FROM INFORMATION_SCHEMA.FEEDBACK is doing, read and concatenate table data into a String. */ if (!(thd= new THD())) diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index de0b7bfae8e..c4b6fa361a3 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -1041,6 +1041,7 @@ static int start_logging() error_header(); fprintf(stderr, "logging started to the file %s.\n", alt_fname); strncpy(current_log_buf, alt_fname, sizeof(current_log_buf)); + current_log_buf[sizeof(current_log_buf)-1]= 0; } else if (output_type == OUTPUT_SYSLOG) { @@ -2570,6 +2571,7 @@ static void update_file_path(MYSQL_THD thd, } strncpy(path_buffer, new_name, sizeof(path_buffer)); + path_buffer[sizeof(path_buffer)-1]= 0; file_path= path_buffer; exit_func: internal_stop_logging= 0; @@ -2622,6 +2624,7 @@ static void update_incl_users(MYSQL_THD thd, flogger_mutex_lock(&lock_operations); mark_always_logged(thd); strncpy(incl_user_buffer, new_users, sizeof(incl_user_buffer)); + incl_user_buffer[sizeof(incl_user_buffer)-1]= 0; incl_users= incl_user_buffer; user_coll_fill(&incl_user_coll, incl_users, &excl_user_coll, 1); error_header(); @@ -2640,6 +2643,7 @@ static void update_excl_users(MYSQL_THD thd __attribute__((unused)), flogger_mutex_lock(&lock_operations); mark_always_logged(thd); strncpy(excl_user_buffer, new_users, sizeof(excl_user_buffer)); + excl_user_buffer[sizeof(excl_user_buffer)-1]= 0; excl_users= excl_user_buffer; user_coll_fill(&excl_user_coll, excl_users, &incl_user_coll, 0); error_header(); @@ -2771,6 +2775,7 @@ static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)), { char *new_ident= (*(char **) save) ? *(char **) save : empty_str; strncpy(syslog_ident_buffer, new_ident, sizeof(syslog_ident_buffer)); + syslog_ident_buffer[sizeof(syslog_ident_buffer)-1]= 0; syslog_ident= syslog_ident_buffer; error_header(); fprintf(stderr, "SYSYLOG ident was changed to '%s'\n", syslog_ident); diff --git a/sql-common/client_plugin.c b/sql-common/client_plugin.c index dd87b01d932..f93e50125c5 100644 --- a/sql-common/client_plugin.c +++ b/sql-common/client_plugin.c @@ -375,8 +375,7 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type, if (!(sym= dlsym(dlhandle, plugin_declarations_sym))) { errmsg= "not a plugin"; - (void)dlclose(dlhandle); - goto err; + goto errc; } plugin= (struct st_mysql_client_plugin*)sym; @@ -384,19 +383,19 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type, if (type >=0 && type != plugin->type) { errmsg= "type mismatch"; - goto err; + goto errc; } if (strcmp(name, plugin->name)) { errmsg= "name mismatch"; - goto err; + goto errc; } if (type < 0 && find_plugin(name, plugin->type)) { errmsg= "it is already loaded"; - goto err; + goto errc; } plugin= add_plugin(mysql, plugin, dlhandle, argc, args); @@ -406,6 +405,8 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type, DBUG_PRINT ("leave", ("plugin loaded ok")); DBUG_RETURN (plugin); +errc: + dlclose(dlhandle); err: mysql_mutex_unlock(&LOCK_load_client_plugin); DBUG_PRINT ("leave", ("plugin load error : %s", errmsg)); diff --git a/sql/discover.cc b/sql/discover.cc index d8ed718fc58..d8bf6ca79c5 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -89,8 +89,7 @@ int readfrm(const char *name, const uchar **frmdata, size_t *len) error= 0; err: - if (file > 0) - (void) mysql_file_close(file, MYF(MY_WME)); + (void) mysql_file_close(file, MYF(MY_WME)); err_end: /* Here when no file */ DBUG_RETURN (error); diff --git a/sql/filesort.cc b/sql/filesort.cc index 73a6c89e53f..8a7d5610dc2 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -914,6 +914,7 @@ write_keys(Sort_param *param, Filesort_info *fs_info, uint count, /* check we won't have more buffpeks than we can possibly keep in memory */ if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (ulonglong)UINT_MAX) goto err; + bzero(&buffpek, sizeof(buffpek)); buffpek.file_pos= my_b_tell(tempfile); if ((ha_rows) count > param->max_rows) count=(uint) param->max_rows; /* purecov: inspected */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0aa917cb7fe..32cdda9debc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7702,7 +7702,7 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff) { struct st_data { KEY_CACHE_STATISTICS stats; - SHOW_VAR var[8]; + SHOW_VAR var[9]; } *data; SHOW_VAR *v; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 8f9d5abfa4d..481d8445fa8 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7549,7 +7549,10 @@ QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param, { if (!(quick= (*scan)->make_quick(param, FALSE, &quick_roru->alloc)) || quick_roru->push_quick_back(quick)) + { + delete quick_roru; DBUG_RETURN(NULL); + } } quick_roru->records= records; quick_roru->read_time= read_cost; @@ -11194,9 +11197,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, */ thd->mem_root= old_root; - if (!quick || create_err) - return 0; /* no ranges found */ - if (quick->init()) + if (!quick || create_err || quick->init()) goto err; quick->records= records; diff --git a/sql/records.cc b/sql/records.cc index a37f7a18c11..940fd97d123 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -69,7 +69,7 @@ static int rr_index_desc(READ_RECORD *info); bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse) { - int error; + int error= 0; DBUG_ENTER("init_read_record_idx"); empty_record(table); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index a88e6d776c7..1a02a2ae84c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3022,7 +3022,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) { stmt->state= Query_arena::STMT_ERROR; stmt->last_errno= thd->get_stmt_da()->sql_errno(); - strncpy(stmt->last_error, thd->get_stmt_da()->message(), MYSQL_ERRMSG_SIZE); + strmake_buf(stmt->last_error, thd->get_stmt_da()->message()); } thd->set_stmt_da(save_stmt_da); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 560b7ede183..ebe89e2b4a0 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -3685,9 +3685,6 @@ bool mysql_show_binlog_events(THD* thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - Format_description_log_event *description_event= new - Format_description_log_event(3); /* MySQL 4.0 by default */ - DBUG_ASSERT(thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS || thd->lex->sql_command == SQLCOM_SHOW_RELAYLOG_EVENTS); @@ -3713,6 +3710,9 @@ bool mysql_show_binlog_events(THD* thd) binary_log= &(mi->rli.relay_log); } + Format_description_log_event *description_event= new + Format_description_log_event(3); /* MySQL 4.0 by default */ + if (binary_log->is_open()) { LEX_MASTER_INFO *lex_mi= &thd->lex->mi; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ae074eee556..3f161fb8aec 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3016,7 +3016,7 @@ static bool show_status_array(THD *thd, const char *wild, for (; variables->name; variables++) { - bool wild_checked; + bool wild_checked= 0; strnmov(prefix_end, variables->name, len); name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ if (ucase_names) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5ff79a2f235..99248457bb8 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1660,7 +1660,10 @@ Sys_var_gtid_binlog_state::do_check(THD *thd, set_var *var) return true; } if (res->length() == 0) + { list= NULL; + list_len= 0; + } else if (!(list= gtid_parse_string_to_list(res->ptr(), res->length(), &list_len))) { diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 35596a59c86..a8ae617a588 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -1484,13 +1484,13 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt) /* Don't assert in field::val() functions */ table->use_all_columns(); - if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME)))) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* position buffer to the start of the file */ if (init_data_file()) DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR); + if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME)))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* Local_saved_data_file_length is initialized during the lock phase. Sometimes this is not getting executed before ::repair (e.g. for @@ -1574,9 +1574,9 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt) DBUG_RETURN(my_errno ? my_errno : -1); share->tina_write_opened= FALSE; } - if (mysql_file_close(data_file, MYF(0)) || - mysql_file_close(repair_file, MYF(0)) || - mysql_file_rename(csv_key_file_data, + mysql_file_close(data_file, MYF(0)); + mysql_file_close(repair_file, MYF(0)); + if (mysql_file_rename(csv_key_file_data, repaired_fname, share->data_file_name, MYF(0))) DBUG_RETURN(-1); @@ -1698,13 +1698,14 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt) DBUG_ENTER("ha_tina::check"); old_proc_info= thd_proc_info(thd, "Checking table"); - if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME)))) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* position buffer to the start of the file */ if (init_data_file()) DBUG_RETURN(HA_ERR_CRASHED); + if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME)))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + /* Local_saved_data_file_length is initialized during the lock phase. Check does not use store_lock in certain cases. So, we set it diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index bd5c67c0409..851f21888d8 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -4215,6 +4215,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, printf("Data records: %s\n", llstr(start_records, llbuff)); } + bzero(&new_data_cache, sizeof(new_data_cache)); if (initialize_variables_for_repair(param, &sort_info, &tmp_sort_param, info, rep_quick, &backup_share)) goto err; diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 86a8970d7a7..096d14f2d57 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -953,6 +953,7 @@ static File create_logfile_by_number_no_cache(uint32 file_no) { DBUG_PRINT("error", ("Error %d during syncing directory '%s'", errno, log_descriptor.directory)); + mysql_file_close(file, MYF(0)); translog_stop_writing(); DBUG_RETURN(-1); } @@ -1454,17 +1455,16 @@ LSN translog_get_file_max_lsn_stored(uint32 file) if (translog_read_file_header(&info, fd)) { DBUG_PRINT("error", ("Can't read file header")); - DBUG_RETURN(LSN_ERROR); + info.max_lsn= LSN_ERROR; } if (mysql_file_close(fd, MYF(MY_WME))) { DBUG_PRINT("error", ("Can't close file")); - DBUG_RETURN(LSN_ERROR); + info.max_lsn= LSN_ERROR; } - DBUG_PRINT("info", ("Max lsn: (%lu,0x%lx)", - LSN_IN_PARTS(info.max_lsn))); + DBUG_PRINT("info", ("Max lsn: (%lu,0x%lx)", LSN_IN_PARTS(info.max_lsn))); DBUG_RETURN(info.max_lsn); } } @@ -1638,13 +1638,15 @@ static my_bool translog_create_new_file() if (allocate_dynamic(&log_descriptor.open_files, log_descriptor.max_file - log_descriptor.min_file + 2)) goto error_lock; - if ((file->handler.file= - create_logfile_by_number_no_cache(file_no)) == -1) + + /* this call just expand the array */ + if (insert_dynamic(&log_descriptor.open_files, (uchar*)&file)) + goto error_lock; + + if ((file->handler.file= create_logfile_by_number_no_cache(file_no)) == -1) goto error_lock; translog_file_init(file, file_no, 0); - /* this call just expand the array */ - insert_dynamic(&log_descriptor.open_files, (uchar*)&file); log_descriptor.max_file++; { char *start= (char*) dynamic_element(&log_descriptor.open_files, 0, @@ -1678,6 +1680,7 @@ error_lock: mysql_rwlock_unlock(&log_descriptor.open_files_lock); error: translog_stop_writing(); + my_free(file); DBUG_RETURN(1); } @@ -3985,11 +3988,14 @@ my_bool translog_init_with_table(const char *directory, /* Start new log system from scratch */ log_descriptor.horizon= MAKE_LSN(start_file_num, TRANSLOG_PAGE_SIZE); /* header page */ - if ((file->handler.file= - create_logfile_by_number_no_cache(start_file_num)) == -1) - goto err; translog_file_init(file, start_file_num, 0); if (insert_dynamic(&log_descriptor.open_files, (uchar*)&file)) + { + my_free(file); + goto err; + } + if ((file->handler.file= + create_logfile_by_number_no_cache(start_file_num)) == -1) goto err; log_descriptor.min_file= log_descriptor.max_file= start_file_num; if (translog_write_file_header()) diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c index 6a4e7ea99cf..4127c4f5fcf 100644 --- a/storage/maria/ma_packrec.c +++ b/storage/maria/ma_packrec.c @@ -1445,7 +1445,7 @@ uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BIT_BUFF *bit_buff, maria->blob_length=info->blob_len; } info->filepos=filepos+head_length; - if (file > 0) + if (file >= 0) { info->offset=MY_MIN(info->rec_len, ref_length - head_length); memcpy(*rec_buff_p, header + head_length, info->offset); diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index a09662544a2..5a36c9db8ca 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -1988,7 +1988,7 @@ prototype_redo_exec_hook(UNDO_KEY_INSERT) const HA_KEYSEG *keyseg= info->s->keyinfo[keynr].seg; ulonglong value; char llbuf[22]; - uchar *to; + uchar reversed[MARIA_MAX_KEY_BUFF], *to; tprint(tracef, " state older than record\n"); /* we read the record to find the auto_increment value */ enlarge_buffer(rec); @@ -2005,7 +2005,6 @@ prototype_redo_exec_hook(UNDO_KEY_INSERT) if (keyseg->flag & HA_SWAP_KEY) { /* We put key from log record to "data record" packing format... */ - uchar reversed[MARIA_MAX_KEY_BUFF]; uchar *key_ptr= to; uchar *key_end= key_ptr + keyseg->length; to= reversed + keyseg->length; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 2cfaa5ebdcc..8ec3c3681e9 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1248,6 +1248,7 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) { KEY_CACHE *new_key_cache= check_opt->key_cache; const char *errmsg= 0; + char buf[STRING_BUFFER_USUAL_SIZE]; int error= HA_ADMIN_OK; ulonglong map; TABLE_LIST *table_list= table->pos_in_table_list; @@ -1264,7 +1265,6 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) if ((error= mi_assign_to_key_cache(file, map, new_key_cache))) { - char buf[STRING_BUFFER_USUAL_SIZE]; my_snprintf(buf, sizeof(buf), "Failed to flush to index file (errno: %d)", error); errmsg= buf; diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index bdb2fdf8447..7e846fc262c 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -151,7 +151,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) } share->mode=open_mode; errpos=1; - if (mysql_file_read(kfile, share->state.header.file_version, head_length, + if (mysql_file_read(kfile, (uchar*)&share->state.header, head_length, MYF(MY_NABP))) { my_errno= HA_ERR_NOT_A_TABLE; diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc index 5f83d401f98..51c41cc1b78 100644 --- a/storage/xtradb/buf/buf0dump.cc +++ b/storage/xtradb/buf/buf0dump.cc @@ -604,6 +604,7 @@ buf_load() if (dump_n == 0) { ut_free(dump); + ut_free(dump_tmp); ut_sprintf_timestamp(now); buf_load_status(STATUS_NOTICE, "Buffer pool(s) load completed at %s " diff --git a/storage/xtradb/dict/dict0mem.cc b/storage/xtradb/dict/dict0mem.cc index ee6de30cd40..0f48c7c69e3 100644 --- a/storage/xtradb/dict/dict0mem.cc +++ b/storage/xtradb/dict/dict0mem.cc @@ -321,8 +321,8 @@ dict_mem_table_col_rename_low( ut_ad(from_len <= NAME_LEN); ut_ad(to_len <= NAME_LEN); - char from[NAME_LEN]; - strncpy(from, s, NAME_LEN); + char from[NAME_LEN + 1]; + strncpy(from, s, NAME_LEN + 1); if (from_len == to_len) { /* The easy case: simply replace the column name in diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index d0eef98f064..7d1ed3da5fd 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -3219,13 +3219,13 @@ innobase_convert_identifier( ibool file_id)/*!< in: TRUE=id is a table or database name; FALSE=id is an UTF-8 string */ { + char nz2[MAX_TABLE_NAME_LEN + 1]; const char* s = id; int q; if (file_id) { char nz[MAX_TABLE_NAME_LEN + 1]; - char nz2[MAX_TABLE_NAME_LEN + 1]; /* Decode the table name. The MySQL function expects a NUL-terminated string. The input and output strings diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 3cd1412098d..ee5136376fa 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -1453,6 +1453,7 @@ log_online_setup_bitmap_file_range( if (UNIV_UNLIKELY(array_pos >= bitmap_files->count)) { log_online_diagnose_inconsistent_dir(bitmap_files); + os_file_closedir(bitmap_dir); return FALSE; } diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 22d7312643b..bd1bc2c7131 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -2483,7 +2483,8 @@ purge_archived_logs( if (dirnamelen + strlen(fileinfo.name) + 2 > OS_FILE_MAX_PATH) continue; - snprintf(archived_log_filename + dirnamelen, OS_FILE_MAX_PATH, + snprintf(archived_log_filename + dirnamelen, + OS_FILE_MAX_PATH - dirnamelen - 1, "%s", fileinfo.name); if (before_no) { diff --git a/strings/ctype.c b/strings/ctype.c index d8a1dd7502b..25fc2e29877 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -750,7 +750,7 @@ static int cs_value(MY_XML_PARSER *st,const char *attr, size_t len) /* Rules: Context */ case _CS_CONTEXT: - if (len < sizeof(i->context) + 1) + if (len < sizeof(i->context)) { memcpy(i->context, attr, len); i->context[len]= '\0'; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 4e4768559d4..4978faafb67 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -1033,6 +1033,7 @@ static void test_wl4435_2() \ rs_metadata= mysql_stmt_result_metadata(ps); \ fields= mysql_fetch_fields(rs_metadata); \ + mysql_free_result(rs_metadata); \ \ rc= mysql_stmt_bind_result(ps, &psp); \ check_execute(ps, rc); \ diff --git a/unittest/mysys/ma_dyncol-t.c b/unittest/mysys/ma_dyncol-t.c index b3fff638b65..3b43c10a6a8 100644 --- a/unittest/mysys/ma_dyncol-t.c +++ b/unittest/mysys/ma_dyncol-t.c @@ -687,6 +687,9 @@ void test_update_many(uint *column_numbers, uint *column_values, err: ok(rc, "%s", "update_many"); /* cleanup */ + free(val); + free(upd); + free(res); mariadb_dyncol_free(&str1); mariadb_dyncol_free(&str2); } From 6dcc378964a1a35c0c95b6963b73224e52cf4cad Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 18 May 2017 15:22:45 +0200 Subject: [PATCH 147/148] MDEV-10788 Not able to compile source with -DBUILD_CONFIG=mysql_release -DCMAKE_BUILD_TYPE=Debug fix incorrect merge, 831b531895 was not fully merged into 10.0 --- config.h.cmake | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/config.h.cmake b/config.h.cmake index 8618d9e6d02..ae81349b566 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -663,21 +663,4 @@ #define __STDC_FORMAT_MACROS #endif -/* - stat structure (from ) is conditionally defined - to have different layout and size depending on the defined macros. - The correct macro is defined in my_config.h, which means it MUST be - included first (or at least before - so, practically, - before including any system headers). - - Check the include order by looking at __GLIBC__ (defined in ) - - But we cannot force all third-party clients/connectors to include - my_config.h first. So, their crashes are their responsibility, - we enable this check only for MariaDB sources (SAFE_MUTEX check). -*/ -#if defined(__GLIBC__) && defined(SAFE_MUTEX) -#error MUST be included first! -#endif - #endif From eb30230359309de8972d771cbf282097b1175a09 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 19 May 2017 22:27:26 +0200 Subject: [PATCH 148/148] compilation warnings in Connect --- storage/connect/array.cpp | 10 +++++----- storage/connect/array.h | 4 ++-- storage/connect/blkfil.cpp | 8 ++++---- storage/connect/blkfil.h | 8 ++++---- storage/connect/block.h | 4 ++-- storage/connect/colblk.cpp | 4 ++-- storage/connect/colblk.h | 4 ++-- storage/connect/csort.h | 4 ++-- storage/connect/filamvct.cpp | 1 - storage/connect/filter.cpp | 10 +++++----- storage/connect/filter.h | 4 ++-- storage/connect/ha_connect.cc | 2 +- storage/connect/plgdbutl.cpp | 2 +- storage/connect/tabcol.cpp | 8 ++++---- storage/connect/tabcol.h | 8 ++++---- storage/connect/tabdos.cpp | 4 ++-- storage/connect/tabdos.h | 4 ++-- storage/connect/tabjdbc.h | 2 +- storage/connect/table.cpp | 6 +++--- storage/connect/tabodbc.h | 2 +- storage/connect/tabsys.h | 4 ++-- storage/connect/tabxml.h | 2 +- storage/connect/value.cpp | 8 ++++---- storage/connect/value.h | 6 +++--- storage/connect/xindex.cpp | 4 ++-- storage/connect/xindex.h | 4 ++-- storage/connect/xobject.cpp | 8 ++++---- storage/connect/xobject.h | 4 ++-- storage/connect/xtable.h | 4 ++-- 29 files changed, 71 insertions(+), 72 deletions(-) diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index 5cf15c5ac18..6e0da312ca3 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -986,7 +986,7 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) for (i = 0; i < Nval; i++) { Value->SetValue_pvblk(Vblp, i); - Value->Print(g, tp, z); + Value->Prints(g, tp, z); len += strlen(tp); } // enfor i @@ -998,7 +998,7 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) for (i = 0; i < Nval;) { Value->SetValue_pvblk(Vblp, i); - Value->Print(g, tp, z); + Value->Prints(g, tp, z); strcat(p, tp); strcat(p, (++i == Nval) ? ")" : ","); } // enfor i @@ -1012,7 +1012,7 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) /***********************************************************************/ /* Make file output of ARRAY contents. */ /***********************************************************************/ -void ARRAY::Print(PGLOBAL g, FILE *f, uint n) +void ARRAY::Printf(PGLOBAL g, FILE *f, uint n) { char m[64]; int lim = MY_MIN(Nval,10); @@ -1029,7 +1029,7 @@ void ARRAY::Print(PGLOBAL g, FILE *f, uint n) if (Vblp) for (int i = 0; i < lim; i++) { Value->SetValue_pvblk(Vblp, i); - Value->Print(g, f, n+4); + Value->Printf(g, f, n+4); } // endfor i } else @@ -1040,7 +1040,7 @@ void ARRAY::Print(PGLOBAL g, FILE *f, uint n) /***********************************************************************/ /* Make string output of ARRAY contents. */ /***********************************************************************/ -void ARRAY::Print(PGLOBAL, char *ps, uint z) +void ARRAY::Prints(PGLOBAL, char *ps, uint z) { if (z < 16) return; diff --git a/storage/connect/array.h b/storage/connect/array.h index dfc3638de8a..bd38344de06 100644 --- a/storage/connect/array.h +++ b/storage/connect/array.h @@ -56,8 +56,8 @@ class DllExport ARRAY : public XOBJECT, public CSORT { // Array descblock virtual bool Compare(PXOB) {assert(false); return false;} virtual bool SetFormat(PGLOBAL, FORMAT&) {assert(false); return false;} //virtual int CheckSpcCol(PTDB, int) {return 0;} - virtual void Print(PGLOBAL g, FILE *f, uint n); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Printf(PGLOBAL g, FILE *f, uint n); + virtual void Prints(PGLOBAL g, char *ps, uint z); // void Empty(void); void SetPrecision(PGLOBAL g, int p); bool AddValue(PGLOBAL g, PSZ sp); diff --git a/storage/connect/blkfil.cpp b/storage/connect/blkfil.cpp index e438e185e5d..77a46260934 100644 --- a/storage/connect/blkfil.cpp +++ b/storage/connect/blkfil.cpp @@ -56,7 +56,7 @@ BLOCKFILTER::BLOCKFILTER(PTDBDOS tdbp, int op) /***********************************************************************/ /* Make file output of BLOCKFILTER contents. */ /***********************************************************************/ -void BLOCKFILTER::Print(PGLOBAL, FILE *f, uint n) +void BLOCKFILTER::Printf(PGLOBAL, FILE *f, uint n) { char m[64]; @@ -70,7 +70,7 @@ void BLOCKFILTER::Print(PGLOBAL, FILE *f, uint n) /***********************************************************************/ /* Make string output of BLOCKFILTER contents. */ /***********************************************************************/ -void BLOCKFILTER::Print(PGLOBAL, char *ps, uint z) +void BLOCKFILTER::Prints(PGLOBAL, char *ps, uint z) { strncat(ps, "BlockFilter(s)", z); } // end of Print @@ -995,7 +995,7 @@ int BLOCKINDEX::BlockEval(PGLOBAL g) /***********************************************************************/ /* Make file output of BLOCKINDEX contents. */ /***********************************************************************/ -void BLOCKINDEX::Print(PGLOBAL g, FILE *f, UINT n) +void BLOCKINDEX::Printf(PGLOBAL g, FILE *f, UINT n) { char m[64]; @@ -1013,7 +1013,7 @@ void BLOCKINDEX::Print(PGLOBAL g, FILE *f, UINT n) /***********************************************************************/ /* Make string output of BLOCKINDEX contents. */ /***********************************************************************/ -void BLOCKINDEX::Print(PGLOBAL g, char *ps, UINT z) +void BLOCKINDEX::Prints(PGLOBAL g, char *ps, UINT z) { strncat(ps, "BlockIndex(es)", z); } // end of Print diff --git a/storage/connect/blkfil.h b/storage/connect/blkfil.h index 00b00139042..61b02c53c14 100644 --- a/storage/connect/blkfil.h +++ b/storage/connect/blkfil.h @@ -27,8 +27,8 @@ class DllExport BLOCKFILTER : public BLOCK { /* Block Filter */ // Methods virtual void Reset(PGLOBAL) = 0; virtual int BlockEval(PGLOBAL) = 0; - virtual void Print(PGLOBAL g, FILE *f, uint n); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Printf(PGLOBAL g, FILE *f, uint n); + virtual void Prints(PGLOBAL g, char *ps, uint z); protected: BLOCKFILTER(void) {} // Standard constructor not to be used @@ -234,8 +234,8 @@ class DllExport BLOCKINDEX : public BLOCK { /* Indexing Test Block */ // Methods void Reset(void); virtual int BlockEval(PGLOBAL); - virtual void Print(PGLOBAL g, FILE *f, UINT n); - virtual void Print(PGLOBAL g, char *ps, UINT z); + virtual void Printf(PGLOBAL g, FILE *f, UINT n); + virtual void Prints(PGLOBAL g, char *ps, UINT z); protected: BLOCKINDEX(void) {} // Standard constructor not to be used diff --git a/storage/connect/block.h b/storage/connect/block.h index aa4edde5ec9..8ac7be80988 100644 --- a/storage/connect/block.h +++ b/storage/connect/block.h @@ -44,8 +44,8 @@ class DllExport BLOCK { return (PlugSubAlloc(g, p, size)); } // end of new - virtual void Print(PGLOBAL, FILE *, uint) {} // Produce file desc - virtual void Print(PGLOBAL, char *, uint) {} // Produce string desc + virtual void Printf(PGLOBAL, FILE *, uint) {} // Produce file desc + virtual void Prints(PGLOBAL, char *, uint) {} // Produce string desc #if !defined(__BORLANDC__) // Avoid warning C4291 by defining a matching dummy delete operator diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp index fa205b493a2..324d59ab40e 100644 --- a/storage/connect/colblk.cpp +++ b/storage/connect/colblk.cpp @@ -214,7 +214,7 @@ void COLBLK::WriteColumn(PGLOBAL g) /***********************************************************************/ /* Make file output of a column descriptor block. */ /***********************************************************************/ -void COLBLK::Print(PGLOBAL, FILE *f, uint n) +void COLBLK::Printf(PGLOBAL, FILE *f, uint n) { char m[64]; int i; @@ -237,7 +237,7 @@ void COLBLK::Print(PGLOBAL, FILE *f, uint n) /***********************************************************************/ /* Make string output of a column descriptor block. */ /***********************************************************************/ -void COLBLK::Print(PGLOBAL, char *ps, uint) +void COLBLK::Prints(PGLOBAL, char *ps, uint) { sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name); } // end of Print diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h index 02c4f2361b7..608aa040787 100644 --- a/storage/connect/colblk.h +++ b/storage/connect/colblk.h @@ -72,8 +72,8 @@ class DllExport COLBLK : public XOBJECT { virtual void SetTo_Val(PVAL) {} virtual void ReadColumn(PGLOBAL g); virtual void WriteColumn(PGLOBAL g); - virtual void Print(PGLOBAL g, FILE *, uint); - virtual void Print(PGLOBAL g, char *, uint); + virtual void Printf(PGLOBAL g, FILE *, uint); + virtual void Prints(PGLOBAL g, char *, uint); virtual bool VarSize(void) {return false;} bool InitValue(PGLOBAL g); diff --git a/storage/connect/csort.h b/storage/connect/csort.h index 55ff6268a4b..6e700059881 100644 --- a/storage/connect/csort.h +++ b/storage/connect/csort.h @@ -49,8 +49,8 @@ class DllExport CSORT { public: // Methods int Qsort(PGLOBAL g, int n); /* Sort calling routine */ -//virtual void Print(PGLOBAL g, FILE *f, uint n); -//virtual void Print(PGLOBAL g, char *ps, uint z); +//virtual void Printf(PGLOBAL g, FILE *f, uint n); +//virtual void Prints(PGLOBAL g, char *ps, uint z); #ifdef DEBTRACE int GetNcmp(void) {return num_comp;} #endif diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp index f8a7f2600f3..537f77d01ac 100755 --- a/storage/connect/filamvct.cpp +++ b/storage/connect/filamvct.cpp @@ -569,7 +569,6 @@ bool VCTFAM::InitInsert(PGLOBAL g) CurNum = 0; AddBlock = !MaxBlk; } else { - int rc; PVCTCOL cp = (PVCTCOL)Tdbp->GetColumns(); // The starting point must be at the end of file as for append. diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp index 863c9ca6571..da44b129ccb 100644 --- a/storage/connect/filter.cpp +++ b/storage/connect/filter.cpp @@ -1409,7 +1409,7 @@ PFIL FILTER::Copy(PTABS t) /*********************************************************************/ /* Make file output of FILTER contents. */ /*********************************************************************/ -void FILTER::Print(PGLOBAL g, FILE *f, uint n) +void FILTER::Printf(PGLOBAL g, FILE *f, uint n) { char m[64]; @@ -1431,7 +1431,7 @@ void FILTER::Print(PGLOBAL g, FILE *f, uint n) if (lin && fp->GetArgType(i) == TYPE_FILTER) fprintf(f, "%s Filter at %p\n", m, fp->Arg(i)); else - fp->Arg(i)->Print(g, f, n + 2); + fp->Arg(i)->Printf(g, f, n + 2); } // endfor i @@ -1442,7 +1442,7 @@ void FILTER::Print(PGLOBAL g, FILE *f, uint n) /***********************************************************************/ /* Make string output of TABLE contents (z should be checked). */ /***********************************************************************/ -void FILTER::Print(PGLOBAL g, char *ps, uint z) +void FILTER::Prints(PGLOBAL g, char *ps, uint z) { #define FLEN 100 @@ -1470,7 +1470,7 @@ void FILTER::Print(PGLOBAL g, char *ps, uint z) bcp = bxp; p = bcp->Cold; n = FLEN; - fp->Arg(0)->Print(g, p, n); + fp->Arg(0)->Prints(g, p, n); n = FLEN - strlen(p); switch (fp->Opc) { @@ -1516,7 +1516,7 @@ void FILTER::Print(PGLOBAL g, char *ps, uint z) n = FLEN - strlen(p); p += strlen(p); - fp->Arg(1)->Print(g, p, n); + fp->Arg(1)->Prints(g, p, n); } else if (!bcp) { strncat(ps, "???", z); diff --git a/storage/connect/filter.h b/storage/connect/filter.h index f4835d23a7c..22d1e4ed4be 100644 --- a/storage/connect/filter.h +++ b/storage/connect/filter.h @@ -61,8 +61,8 @@ class DllExport FILTER : public XOBJECT { /* Filter description block */ //virtual PXOB CheckSubQuery(PGLOBAL, PSQL); //virtual bool CheckLocal(PTDB); //virtual int CheckSpcCol(PTDB tdbp, int n); - virtual void Print(PGLOBAL g, FILE *f, uint n); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Printf(PGLOBAL g, FILE *f, uint n); + virtual void Prints(PGLOBAL g, char *ps, uint z); // PFIL Linearize(bool nosep); // PFIL Link(PGLOBAL g, PFIL fil2); // PFIL RemoveLastSep(void); diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 68b01e3c7f2..c30ab9adf4e 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1034,7 +1034,7 @@ PCSZ GetListOption(PGLOBAL g, PCSZ opname, PCSZ oplist, PCSZ def) pv= strchr(pk, '='); if (pv && (!pn || pv < pn)) { - n= MY_MIN(pv - pk, sizeof(key) - 1); + n= MY_MIN(pv - pk, (int)sizeof(key) - 1); memcpy(key, pk, n); key[n]= 0; pv++; diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index d990f082e5b..b6f59bac8cf 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -1492,7 +1492,7 @@ void PlugPutOut(PGLOBAL g, FILE *f, short t, void *v, uint n) case TYPE_TABLE: case TYPE_TDB: case TYPE_XOBJECT: - ((PBLOCK)v)->Print(g, f, n-2); + ((PBLOCK)v)->Printf(g, f, n-2); break; default: diff --git a/storage/connect/tabcol.cpp b/storage/connect/tabcol.cpp index fde1baa6317..2740864a69b 100644 --- a/storage/connect/tabcol.cpp +++ b/storage/connect/tabcol.cpp @@ -73,7 +73,7 @@ PTABLE XTAB::Link(PTABLE tab2) /***********************************************************************/ /* Make file output of XTAB contents. */ /***********************************************************************/ -void XTAB::Print(PGLOBAL g, FILE *f, uint n) +void XTAB::Printf(PGLOBAL g, FILE *f, uint n) { char m[64]; @@ -91,7 +91,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n) /***********************************************************************/ /* Make string output of XTAB contents. */ /***********************************************************************/ -void XTAB::Print(PGLOBAL, char *ps, uint z) +void XTAB::Prints(PGLOBAL, char *ps, uint z) { char buf[128]; int i, n = (int)z - 1; @@ -134,7 +134,7 @@ bool COLUMN::SetFormat(PGLOBAL g, FORMAT&) /***********************************************************************/ /* Make file output of COLUMN contents. */ /***********************************************************************/ -void COLUMN::Print(PGLOBAL g, FILE *f, uint n) +void COLUMN::Printf(PGLOBAL g, FILE *f, uint n) { char m[64]; @@ -154,7 +154,7 @@ void COLUMN::Print(PGLOBAL g, FILE *f, uint n) /***********************************************************************/ /* Make string output of COLUMN contents. */ /***********************************************************************/ -void COLUMN::Print(PGLOBAL, char *ps, uint z) +void COLUMN::Prints(PGLOBAL, char *ps, uint z) { char buf[80]; diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h index 3bfc37e69c1..e4657e2f261 100644 --- a/storage/connect/tabcol.h +++ b/storage/connect/tabcol.h @@ -38,8 +38,8 @@ class DllExport XTAB: public BLOCK { // Table Name-Schema-Srcdef block. // Methods PTABLE Link(PTABLE); - void Print(PGLOBAL g, FILE *f, uint n); - void Print(PGLOBAL g, char *ps, uint z); + void Printf(PGLOBAL g, FILE *f, uint n); + void Prints(PGLOBAL g, char *ps, uint z); protected: // Members @@ -78,8 +78,8 @@ class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block. void SetTo_Col(PCOL colp) {To_Col = colp;} // Methods - virtual void Print(PGLOBAL g, FILE *f, uint n); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Printf(PGLOBAL g, FILE *f, uint n); + virtual void Prints(PGLOBAL g, char *ps, uint z); // All methods below should never be used for COLUMN's virtual void Reset(void) {assert(false);} virtual bool Compare(PXOB) {assert(false); return false;} diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 21b64a41684..468966e79d9 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -2871,9 +2871,9 @@ bool DOSCOL::AddDistinctValue(PGLOBAL g) /***********************************************************************/ /* Make file output of a Dos column descriptor block. */ /***********************************************************************/ -void DOSCOL::Print(PGLOBAL g, FILE *f, uint n) +void DOSCOL::Printf(PGLOBAL g, FILE *f, uint n) { - COLBLK::Print(g, f, n); + COLBLK::Printf(g, f, n); } // end of Print /* ------------------------------------------------------------------- */ diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h index d175cc2da4d..9722cd3777d 100644 --- a/storage/connect/tabdos.h +++ b/storage/connect/tabdos.h @@ -232,12 +232,12 @@ class DllExport DOSCOL : public COLBLK { virtual PVBLK GetDval(void) {return Dval;} // Methods - using COLBLK::Print; + //using COLBLK::Print; virtual bool VarSize(void); virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); virtual void ReadColumn(PGLOBAL g); virtual void WriteColumn(PGLOBAL g); - virtual void Print(PGLOBAL g, FILE *, uint); + virtual void Printf(PGLOBAL g, FILE *, uint); protected: virtual bool SetMinMax(PGLOBAL g); diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index 7c14783285f..d8ec65d02d8 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -173,7 +173,7 @@ public: // Methods virtual void ReadColumn(PGLOBAL g); virtual void WriteColumn(PGLOBAL g); - // void Print(PGLOBAL g, FILE *, uint); + // void Printf(PGLOBAL g, FILE *, uint); protected: // Members diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp index 22fb09dbb86..d39837a7b5a 100644 --- a/storage/connect/table.cpp +++ b/storage/connect/table.cpp @@ -299,7 +299,7 @@ bool TDB::SetRecpos(PGLOBAL g, int) return true; } // end of SetRecpos -void TDB::Print(PGLOBAL g, FILE *f, uint n) +void TDB::Printf(PGLOBAL g, FILE *f, uint n) { PCOL cp; char m[64]; @@ -315,13 +315,13 @@ void TDB::Print(PGLOBAL g, FILE *f, uint n) fprintf(f, "%s Columns (deg=%d):\n", m, tp->Degree); for (cp = tp->Columns; cp; cp = cp->GetNext()) - cp->Print(g, f, n); + cp->Printf(g, f, n); } /* endfor tp */ } // end of Print -void TDB::Print(PGLOBAL, char *ps, uint) +void TDB::Prints(PGLOBAL, char *ps, uint) { sprintf(ps, "R%d.%s", Tdb_No, Name); } // end of Print diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h index 487a5073559..0ca88b60858 100644 --- a/storage/connect/tabodbc.h +++ b/storage/connect/tabodbc.h @@ -187,7 +187,7 @@ class XSRCCOL : public ODBCCOL { // Methods virtual void ReadColumn(PGLOBAL g); virtual void WriteColumn(PGLOBAL g); -// void Print(PGLOBAL g, FILE *, uint); +// void Printf(PGLOBAL g, FILE *, uint); protected: // Members diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h index 44b5a137a70..0c6017af177 100644 --- a/storage/connect/tabsys.h +++ b/storage/connect/tabsys.h @@ -62,7 +62,7 @@ class TDBINI : public TDBASE { virtual int GetProgCur(void) {return N;} //virtual int GetAffectedRows(void) {return 0;} virtual PCSZ GetFile(PGLOBAL g) {return Ifile;} - virtual void SetFile(PGLOBAL g, PSZ fn) {Ifile = fn;} + virtual void SetFile(PGLOBAL g, PCSZ fn) {Ifile = fn;} virtual void ResetDB(void) {Seclist = Section = NULL; N = 0;} virtual void ResetSize(void) {MaxSize = -1; Seclist = NULL;} virtual int RowNumber(PGLOBAL g, bool b = false) {return N;} @@ -80,7 +80,7 @@ class TDBINI : public TDBASE { protected: // Members - char *Ifile; // The INI file + PCSZ Ifile; // The INI file char *Seclist; // The section list char *Section; // The current section int Seclen; // Length of seclist buffer diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h index 6b18eb645f0..813f62dde52 100644 --- a/storage/connect/tabxml.h +++ b/storage/connect/tabxml.h @@ -75,7 +75,7 @@ class DllExport TDBXML : public TDBASE { virtual int GetRecpos(void); virtual int GetProgCur(void) {return N;} virtual PCSZ GetFile(PGLOBAL g) {return Xfile;} - virtual void SetFile(PGLOBAL g, PSZ fn) {Xfile = fn;} + virtual void SetFile(PGLOBAL g, PCSZ fn) {Xfile = fn;} virtual void ResetDB(void) {N = 0;} virtual void ResetSize(void) {MaxSize = -1;} virtual int RowNumber(PGLOBAL g, bool b = false); diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 429593f07d9..b6c63bdadd3 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -561,7 +561,7 @@ bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL) /***********************************************************************/ /* Make file output of an object value. */ /***********************************************************************/ -void VALUE::Print(PGLOBAL g, FILE *f, uint n) +void VALUE::Printf(PGLOBAL g, FILE *f, uint n) { char m[64], buf[64]; @@ -571,14 +571,14 @@ void VALUE::Print(PGLOBAL g, FILE *f, uint n) if (Null) fprintf(f, "%s\n", m); else - fprintf(f, strcat(strcat(GetCharString(buf), "\n"), m)); + fprintf(f, "%s%s%s", GetCharString(buf), "\n", m); } /* end of Print */ /***********************************************************************/ /* Make string output of an object value. */ /***********************************************************************/ -void VALUE::Print(PGLOBAL g, char *ps, uint z) +void VALUE::Prints(PGLOBAL g, char *ps, uint z) { char *p, buf[64]; @@ -1712,7 +1712,7 @@ bool TYPVAL::SetConstFormat(PGLOBAL, FORMAT& fmt) /***********************************************************************/ /* Make string output of an object value. */ /***********************************************************************/ -void TYPVAL::Print(PGLOBAL g, char *ps, uint z) +void TYPVAL::Prints(PGLOBAL g, char *ps, uint z) { if (Null) strncpy(ps, "null", z); diff --git a/storage/connect/value.h b/storage/connect/value.h index cf6682f56f2..2754c761815 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -122,8 +122,8 @@ class DllExport VALUE : public BLOCK { virtual bool IsEqual(PVAL vp, bool chktype) = 0; virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); virtual bool FormatValue(PVAL vp, PCSZ fmt) = 0; - virtual void Print(PGLOBAL g, FILE *, uint); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Printf(PGLOBAL g, FILE *, uint); + virtual void Prints(PGLOBAL g, char *ps, uint z); /** Set value from a non-aligned in-memory value in the machine byte order. @@ -308,7 +308,7 @@ class DllExport TYPVAL: public VALUE { virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); virtual bool FormatValue(PVAL vp, PCSZ fmt); virtual bool SetConstFormat(PGLOBAL, FORMAT&); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Prints(PGLOBAL g, char *ps, uint z); protected: // Members diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index a34d2e1c847..3e4db8080ae 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -181,7 +181,7 @@ XXBASE::XXBASE(PTDBDOS tbxp, bool b) : CSORT(b), /***********************************************************************/ /* Make file output of XINDEX contents. */ /***********************************************************************/ -void XXBASE::Print(PGLOBAL, FILE *f, uint n) +void XXBASE::Printf(PGLOBAL, FILE *f, uint n) { char m[64]; @@ -193,7 +193,7 @@ void XXBASE::Print(PGLOBAL, FILE *f, uint n) /***********************************************************************/ /* Make string output of XINDEX contents. */ /***********************************************************************/ -void XXBASE::Print(PGLOBAL, char *ps, uint z) +void XXBASE::Prints(PGLOBAL, char *ps, uint z) { *ps = '\0'; strncat(ps, "Xindex", z); diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h index 2d10d72722e..339d7e68b75 100644 --- a/storage/connect/xindex.h +++ b/storage/connect/xindex.h @@ -200,8 +200,8 @@ class DllExport XXBASE : public CSORT, public BLOCK { void FreeIndex(void) {PlgDBfree(Index);} // Methods - virtual void Print(PGLOBAL g, FILE *f, uint n); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Printf(PGLOBAL g, FILE *f, uint n); + virtual void Prints(PGLOBAL g, char *ps, uint z); virtual bool Init(PGLOBAL g) = 0; virtual bool Make(PGLOBAL g, PIXDEF sxp) = 0; #if defined(XMAP) diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp index 8f0b76d2ddc..205edc12d0c 100644 --- a/storage/connect/xobject.cpp +++ b/storage/connect/xobject.cpp @@ -173,17 +173,17 @@ bool CONSTANT::Rephrase(PGLOBAL g, PSZ work) /***********************************************************************/ /* Make file output of a constant object. */ /***********************************************************************/ -void CONSTANT::Print(PGLOBAL g, FILE *f, uint n) +void CONSTANT::Printf(PGLOBAL g, FILE *f, uint n) { - Value->Print(g, f, n); + Value->Printf(g, f, n); } /* end of Print */ /***********************************************************************/ /* Make string output of a constant object. */ /***********************************************************************/ -void CONSTANT::Print(PGLOBAL g, char *ps, uint z) +void CONSTANT::Prints(PGLOBAL g, char *ps, uint z) { - Value->Print(g, ps, z); + Value->Prints(g, ps, z); } /* end of Print */ /* -------------------------- Class STRING --------------------------- */ diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h index 204144182c8..bc5912d3054 100644 --- a/storage/connect/xobject.h +++ b/storage/connect/xobject.h @@ -112,8 +112,8 @@ class DllExport CONSTANT : public XOBJECT { {return Value->SetConstFormat(g, fmt);} void Convert(PGLOBAL g, int newtype); void SetValue(PVAL vp) {Value = vp;} - virtual void Print(PGLOBAL g, FILE *, uint); - virtual void Print(PGLOBAL g, char *, uint); + virtual void Printf(PGLOBAL g, FILE *, uint); + virtual void Prints(PGLOBAL g, char *, uint); }; // end of class CONSTANT /***********************************************************************/ diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h index 3da0c17bdfe..ebef7a2549a 100644 --- a/storage/connect/xtable.h +++ b/storage/connect/xtable.h @@ -109,8 +109,8 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. virtual PTDB Copy(PTABS t); virtual void PrintAM(FILE *f, char *m) {fprintf(f, "%s AM(%d)\n", m, GetAmType());} - virtual void Print(PGLOBAL g, FILE *f, uint n); - virtual void Print(PGLOBAL g, char *ps, uint z); + virtual void Printf(PGLOBAL g, FILE *f, uint n); + virtual void Prints(PGLOBAL g, char *ps, uint z); virtual PCSZ GetServer(void) = 0; virtual int GetBadLines(void) {return 0;} virtual CHARSET_INFO *data_charset(void);