diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f5e7dbc7037f5f05483850a6d168c7a3ba924cf..67bb3d20aeac4521f13f965f411a104aecee5ac0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,7 @@ if(EXISTS ${CMAKE_SOURCE_DIR}/contrib/dolphin) install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin.control DESTINATION share/postgresql/extension/ ) - install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin--3.0.sql + install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin--4.0.sql DESTINATION share/postgresql/extension/ ) install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin--1.0--1.1.sql @@ -132,6 +132,12 @@ if(EXISTS ${CMAKE_SOURCE_DIR}/contrib/dolphin) install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin--3.0--2.0.sql DESTINATION share/postgresql/extension/ ) + install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin--3.0--4.0.sql + DESTINATION share/postgresql/extension/ + ) + install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin--4.0--3.0.sql + DESTINATION share/postgresql/extension/ + ) install(FILES ${CMAKE_SOURCE_DIR}/contrib/dolphin/dolphin--2.0--2.0.1.sql DESTINATION share/postgresql/extension/ ) diff --git a/GNUmakefile.in b/GNUmakefile.in index 6ca1ad54a959abe06c7a83dadc0d3ef6fb0194d9..fa61a14ede802479e7fe25751a1b584cb64c4c88 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -98,7 +98,8 @@ install: @if test -d contrib/spq_plugin; then $(MAKE) -C contrib/spq_plugin $@; fi @if test -d contrib/dolphin; then $(MAKE) -C contrib/dolphin $@; fi @if test -d contrib/age; then $(MAKE) -C contrib/age $@; fi - @if test -d contrib/pgvector; then $(MAKE) -C contrib/pgvector $@; fi + @if test -d contrib/datavec; then $(MAKE) -C contrib/datavec $@; fi + @if test -d contrib/gms_profiler; then $(MAKE) -C contrib/gms_profiler $@; fi +@echo "openGauss installation complete." endif endif diff --git a/build.sh b/build.sh index a8ad3f1b49e4a08805c48b951d01355c927f2ae0..4de8acaea7fd52e52573041789ef203277e5c834 100755 --- a/build.sh +++ b/build.sh @@ -31,6 +31,7 @@ function print_help() -T|--tassl build with tassl -pm|--product_mode this values of paramenter is opengauss or lite or finance, the default value is opengauss. -nls|--enable_nls enable Native Language Support + --relocation generate gaussdb.map with relocation(GCC >=10.3). " } @@ -82,7 +83,11 @@ while [ $# -gt 0 ]; do shift 1 ;; -nls|--enable_nls) - extra_config_opt="--config_opt --enable-nls=zh_CN " + extra_config_opt="$extra_config_opt --config_opt --enable-nls=zh_CN " + shift 1 + ;; + --relocation) + extra_config_opt="$extra_config_opt --config_opt --enable-relocation " shift 1 ;; *) diff --git a/build/script/aarch64_finance_list b/build/script/aarch64_finance_list index 4c76d937b58a71da29ad308b3dbf3c85330f5f6c..f8353c9a28b3fa11c8f4dec3054cabbf48eedc9d 100644 --- a/build/script/aarch64_finance_list +++ b/build/script/aarch64_finance_list @@ -75,13 +75,15 @@ ./share/postgresql/extension/spqplugin.control ./share/postgresql/extension/spqplugin--1.0.sql ./share/postgresql/extension/dolphin.control -./share/postgresql/extension/dolphin--3.0.sql +./share/postgresql/extension/dolphin--4.0.sql ./share/postgresql/extension/dolphin--1.0--1.1.sql ./share/postgresql/extension/dolphin--1.1--1.0.sql ./share/postgresql/extension/dolphin--1.1--2.0.sql ./share/postgresql/extension/dolphin--2.0--1.1.sql ./share/postgresql/extension/dolphin--2.0--3.0.sql ./share/postgresql/extension/dolphin--3.0--2.0.sql +./share/postgresql/extension/dolphin--3.0--4.0.sql +./share/postgresql/extension/dolphin--4.0--3.0.sql ./share/postgresql/extension/dolphin--2.0--2.0.1.sql ./share/postgresql/extension/dolphin--2.0.1--2.0.sql ./share/postgresql/extension/whale.control diff --git a/build/script/aarch64_lite_list b/build/script/aarch64_lite_list index 2a76568942ecb2fef4a2fb9ab0e0639a51fab67e..856c122f439c89a094c7d34f0ee38fbab4ca29b2 100644 --- a/build/script/aarch64_lite_list +++ b/build/script/aarch64_lite_list @@ -34,13 +34,15 @@ ./share/postgresql/extension/security_plugin.control ./share/postgresql/extension/security_plugin--1.0.sql ./share/postgresql/extension/dolphin.control -./share/postgresql/extension/dolphin--3.0.sql +./share/postgresql/extension/dolphin--4.0.sql ./share/postgresql/extension/dolphin--1.0--1.1.sql ./share/postgresql/extension/dolphin--1.1--1.0.sql ./share/postgresql/extension/dolphin--1.1--2.0.sql ./share/postgresql/extension/dolphin--2.0--1.1.sql ./share/postgresql/extension/dolphin--2.0--3.0.sql ./share/postgresql/extension/dolphin--3.0--2.0.sql +./share/postgresql/extension/dolphin--3.0--4.0.sql +./share/postgresql/extension/dolphin--4.0--3.0.sql ./share/postgresql/extension/dolphin--2.0--2.0.1.sql ./share/postgresql/extension/dolphin--2.0.1--2.0.sql ./share/postgresql/extension/openGauss_expr_dolphin.ir diff --git a/build/script/aarch64_opengauss_list b/build/script/aarch64_opengauss_list index e060a9893e147483ca397049f431ba44b5d4638b..7d66c8903ab158fcf4173ce7439d499511f26959 100644 --- a/build/script/aarch64_opengauss_list +++ b/build/script/aarch64_opengauss_list @@ -76,20 +76,22 @@ ./share/postgresql/extension/spqplugin.control ./share/postgresql/extension/spqplugin--1.0.sql ./share/postgresql/extension/dolphin.control -./share/postgresql/extension/dolphin--3.0.sql +./share/postgresql/extension/dolphin--4.0.sql ./share/postgresql/extension/dolphin--1.0--1.1.sql ./share/postgresql/extension/dolphin--1.1--1.0.sql ./share/postgresql/extension/dolphin--1.1--2.0.sql ./share/postgresql/extension/dolphin--2.0--1.1.sql ./share/postgresql/extension/dolphin--2.0--3.0.sql ./share/postgresql/extension/dolphin--3.0--2.0.sql +./share/postgresql/extension/dolphin--3.0--4.0.sql +./share/postgresql/extension/dolphin--4.0--3.0.sql ./share/postgresql/extension/dolphin--2.0--2.0.1.sql ./share/postgresql/extension/dolphin--2.0.1--2.0.sql ./share/postgresql/extension/openGauss_expr_dolphin.ir ./share/postgresql/extension/age--1.0.0.sql ./share/postgresql/extension/age.control -./share/postgresql/extension/vector--0.4.4.sql -./share/postgresql/extension/vector.control +./share/postgresql/extension/datavec--0.4.4.sql +./share/postgresql/extension/datavec.control ./share/postgresql/extension/assessment--1.0.sql ./share/postgresql/extension/assessment.control ./share/postgresql/extension/file_fdw--1.0.sql @@ -110,6 +112,8 @@ ./share/postgresql/extension/dblink--1.0.sql ./share/postgresql/extension/dblink--unpackaged--1.0.sql ./share/postgresql/extension/dblink.control +./share/postgresql/extension/gms_profiler--1.0.sql +./share/postgresql/extension/gms_profiler.control ./share/postgresql/timezone/GB-Eire ./share/postgresql/timezone/Turkey ./share/postgresql/timezone/Kwajalein @@ -797,13 +801,14 @@ ./lib/postgresql/security_plugin.so ./lib/postgresql/dolphin.so ./lib/postgresql/age.so -./lib/postgresql/vector.so +./lib/postgresql/datavec.so ./lib/postgresql/pg_upgrade_support.so ./lib/postgresql/java/pljava.jar ./lib/postgresql/postgres_fdw.so ./lib/postgresql/dblink.so ./lib/postgresql/pgoutput.so ./lib/postgresql/assessment.so +./lib/postgresql/gms_profiler.so ./lib/libpljava.so ./lib/libpq.a ./lib/libpq.so @@ -812,10 +817,18 @@ ./lib/libpq_ce.so ./lib/libpq_ce.so.5 ./lib/libpq_ce.so.5.5 +./lib/libecpg.so +./lib/libecpg.so.6 ./lib/libecpg.so.6.4 +./lib/libecpg_compat.so +./lib/libecpg_compat.so.3 ./lib/libecpg_compat.so.3.4 ./lib/libecpg.a ./lib/libecpg_compat.a +./lib/libpgtypes.a +./lib/libpgtypes.so +./lib/libpgtypes.so.3 +./lib/libpgtypes.so.3.4 ./lib/libgauss_cl_jni.so ./lib/libnuma.so ./lib/libnuma.so.1 @@ -1040,11 +1053,25 @@ ./include/postgresql/server/gstrace/gstrace_infra.h ./include/postgresql/server/extension_dependency.h ./include/postgresql/server/libpq/libpq-fe.h +./include/postgresql/server/ecpg/datetime.h +./include/postgresql/server/ecpg/decimal.h ./include/postgresql/server/ecpg/ecpgerrno.h -./include/postgresql/server/ecpg/ecpglib.h -./include/postgresql/server/ecpg/ecpgtype.h ./include/postgresql/server/ecpg/ecpg_informix.h ./include/postgresql/server/ecpg/ecpg_config.h +./include/postgresql/server/ecpg/ecpglib.h +./include/postgresql/server/ecpg/ecpg-pthread-win32.h +./include/postgresql/server/ecpg/ecpgtype.h +./include/postgresql/server/ecpg/pgtypes_date.h +./include/postgresql/server/ecpg/pgtypes_error.h +./include/postgresql/server/ecpg/pgtypes_interval.h +./include/postgresql/server/ecpg/pgtypes_numeric.h +./include/postgresql/server/ecpg/pgtypes_timestamp.h +./include/postgresql/server/ecpg/sql3types.h +./include/postgresql/server/ecpg/sqlca.h +./include/postgresql/server/ecpg/sqlda-compat.h +./include/postgresql/server/ecpg/sqlda.h +./include/postgresql/server/ecpg/sqlda-native.h +./include/postgresql/server/ecpg/sqltypes.h ./include/postgresql/server/access/clog.h ./include/postgresql/server/storage/proc.h ./include/postgresql/server/access/xlog.h diff --git a/build/script/build_opengauss.sh b/build/script/build_opengauss.sh index ad33de8ef689d618ce82148fde03def95934dd35..7f6fb18a76ad43e1112d1038534839bb7abe1a70 100755 --- a/build/script/build_opengauss.sh +++ b/build/script/build_opengauss.sh @@ -109,7 +109,7 @@ while [ $# -gt 0 ]; do echo "no extra configure options provided" exit 1 fi - extra_cmake_opt=$2 + extra_cmake_opt=" $2 $extra_cmake_opt " shift 2 ;; --config_opt) @@ -117,7 +117,7 @@ while [ $# -gt 0 ]; do echo "no extra configure options provided" exit 1 fi - extra_config_opt=$2 + extra_config_opt=" $2 $extra_config_opt " shift 2 ;; -T|--tassl) diff --git a/build/script/cmake_package_mini.sh b/build/script/cmake_package_mini.sh index 8c8e2e449cb262baa8fd098020b595e780bbc63d..a1b83182e9b85687ee73ca39ff8b01434934d9e6 100644 --- a/build/script/cmake_package_mini.sh +++ b/build/script/cmake_package_mini.sh @@ -809,5 +809,6 @@ echo "[makemppdb] $(date +%y-%m-%d' '%T): remove ${BUILD_DIR}" >>"$LOG_FILE" 2>& mkdir ${ROOT_DIR}/output mv ${ROOT_DIR}/build/script/*.tar.gz ${ROOT_DIR}/output/ +test -e ${ROOT_DIR}/build/script/gaussdb.map && mv ${ROOT_DIR}/build/script/gaussdb.map ${ROOT_DIR}/output/ echo "now, all packages has finished!" exit 0 \ No newline at end of file diff --git a/build/script/opengauss_release_list_ubuntu_single b/build/script/opengauss_release_list_ubuntu_single index 6c12184650a6b24b1218a12d8f68ca4f26f8430e..6911a2989fbbc2f50aa6e31c9bbc5cdc4b119c2b 100644 --- a/build/script/opengauss_release_list_ubuntu_single +++ b/build/script/opengauss_release_list_ubuntu_single @@ -62,20 +62,22 @@ ./share/postgresql/extension/security_plugin.control ./share/postgresql/extension/security_plugin--1.0.sql ./share/postgresql/extension/dolphin.control -./share/postgresql/extension/dolphin--3.0.sql +./share/postgresql/extension/dolphin--4.0.sql ./share/postgresql/extension/dolphin--1.0--1.1.sql ./share/postgresql/extension/dolphin--1.1--1.0.sql ./share/postgresql/extension/dolphin--1.1--2.0.sql ./share/postgresql/extension/dolphin--2.0--1.1.sql ./share/postgresql/extension/dolphin--2.0--3.0.sql ./share/postgresql/extension/dolphin--3.0--2.0.sql +./share/postgresql/extension/dolphin--3.0--4.0.sql +./share/postgresql/extension/dolphin--4.0--3.0.sql ./share/postgresql/extension/dolphin--2.0--2.0.1.sql ./share/postgresql/extension/dolphin--2.0.1--2.0.sql ./share/postgresql/extension/openGauss_expr_dolphin.ir ./share/postgresql/extension/age--1.0.0.sql ./share/postgresql/extension/age.control -./share/postgresql/extension/vector--0.4.4.sql -./share/postgresql/extension/vector.control +./share/postgresql/extension/datavec--0.4.4.sql +./share/postgresql/extension/datavec.control ./share/postgresql/extension/file_fdw--1.0.sql ./share/postgresql/extension/plpgsql.control ./share/postgresql/extension/dist_fdw.control @@ -99,6 +101,8 @@ ./share/postgresql/extension/dblink--1.0.sql ./share/postgresql/extension/dblink--unpackaged--1.0.sql ./share/postgresql/extension/dblink.control +./share/postgresql/extension/gms_profiler--1.0.sql +./share/postgresql/extension/gms_profiler.control ./share/postgresql/timezone/GB-Eire ./share/postgresql/timezone/Turkey ./share/postgresql/timezone/Kwajalein @@ -770,11 +774,12 @@ ./lib/postgresql/security_plugin.so ./lib/postgresql/dolphin.so ./lib/postgresql/age.so -./lib/postgresql/vector.so +./lib/postgresql/datavec.so ./lib/postgresql/pg_upgrade_support.so ./lib/postgresql/java/pljava.jar ./lib/postgresql/postgres_fdw.so ./lib/postgresql/dblink.so +./lib/postgresql/gms_profiler.so ./lib/libpljava.so ./lib/libpq.a ./lib/libpq.so diff --git a/build/script/separate_debug_information.sh b/build/script/separate_debug_information.sh index 3d15ad91024a5386f5eedc67bb7afb4b6ddbb408..54be94a7d6e80d84371d0b90d482a94202dc4dff 100644 --- a/build/script/separate_debug_information.sh +++ b/build/script/separate_debug_information.sh @@ -104,7 +104,7 @@ separate_symbol() ;; esac if [ -x "$x" ]; then - if [ "$x" != "install-sh" ]; then + if [ "$x" != "install-sh" ] && [ "$x" != "gaussdb.map" ]; then objcopy --only-keep-debug "$x" "$INSTALL_DIR/${symbol_name}.symbol" > /dev/null 2>&1 objcopy --strip-all "$x" "$x"_release rm "$x" @@ -191,3 +191,4 @@ cd $SYMBOLS_DIR/../ tar -zcf $PACKAGE_DIR/symbols.tar.gz symbols chmod 755 $PACKAGE_DIR/symbols.tar.gz cp $PACKAGE_DIR/symbols.tar.gz $DEPTH +mv "$BIN_DIR/gaussdb.map" $DEPTH diff --git a/build/script/utils/internal_packages.sh b/build/script/utils/internal_packages.sh index f33ab4198e9e9eea4adb47d8f61cebc9f5b8bb33..a920d15cbac7c2b10ad79edfc8c5891495d67771 100644 --- a/build/script/utils/internal_packages.sh +++ b/build/script/utils/internal_packages.sh @@ -181,6 +181,12 @@ function make_package_upgrade_sql() echo "Successfully packaged upgrade_sql files." } +function move_gaussdb_map() +{ + cd $SCRIPT_DIR + deploy_pkgs gaussdb.map +} + function make_package_libpq() { cd $SCRIPT_DIR @@ -236,5 +242,6 @@ function gaussdb_pkg() make_package_libpq make_package_tools make_package_upgrade_sql + move_gaussdb_map echo "End package opengauss." } diff --git a/build/script/x86_64_finance_list b/build/script/x86_64_finance_list index 4a3357316a171932db423b996cb18d30fae586c3..b12b4ff5889ca2b813385c5726a46b9458877d0f 100644 --- a/build/script/x86_64_finance_list +++ b/build/script/x86_64_finance_list @@ -75,13 +75,15 @@ ./share/postgresql/extension/spqplugin.control ./share/postgresql/extension/spqplugin--1.0.sql ./share/postgresql/extension/dolphin.control -./share/postgresql/extension/dolphin--3.0.sql +./share/postgresql/extension/dolphin--4.0.sql ./share/postgresql/extension/dolphin--1.0--1.1.sql ./share/postgresql/extension/dolphin--1.1--1.0.sql ./share/postgresql/extension/dolphin--1.1--2.0.sql ./share/postgresql/extension/dolphin--2.0--1.1.sql ./share/postgresql/extension/dolphin--2.0--3.0.sql ./share/postgresql/extension/dolphin--3.0--2.0.sql +./share/postgresql/extension/dolphin--3.0--4.0.sql +./share/postgresql/extension/dolphin--4.0--3.0.sql ./share/postgresql/extension/dolphin--2.0--2.0.1.sql ./share/postgresql/extension/dolphin--2.0.1--2.0.sql ./share/postgresql/extension/whale.control diff --git a/build/script/x86_64_lite_list b/build/script/x86_64_lite_list index 31e242d5b3f991517e26fb6f031b82f5e690f691..2143d2aa767c954c2e4ef90f27767459c735e3a3 100644 --- a/build/script/x86_64_lite_list +++ b/build/script/x86_64_lite_list @@ -34,13 +34,15 @@ ./share/postgresql/extension/security_plugin.control ./share/postgresql/extension/security_plugin--1.0.sql ./share/postgresql/extension/dolphin.control -./share/postgresql/extension/dolphin--3.0.sql +./share/postgresql/extension/dolphin--4.0.sql ./share/postgresql/extension/dolphin--1.0--1.1.sql ./share/postgresql/extension/dolphin--1.1--1.0.sql ./share/postgresql/extension/dolphin--1.1--2.0.sql ./share/postgresql/extension/dolphin--2.0--1.1.sql ./share/postgresql/extension/dolphin--2.0--3.0.sql ./share/postgresql/extension/dolphin--3.0--2.0.sql +./share/postgresql/extension/dolphin--3.0--4.0.sql +./share/postgresql/extension/dolphin--4.0--3.0.sql ./share/postgresql/extension/dolphin--2.0--2.0.1.sql ./share/postgresql/extension/dolphin--2.0.1--2.0.sql ./share/postgresql/extension/openGauss_expr_dolphin.ir diff --git a/build/script/x86_64_opengauss_list b/build/script/x86_64_opengauss_list index d24a0fc29a53937cba3445f6fafb13b74f3448a6..e407e109bc482fd1c6f3ef0849b9b2628b1ec708 100644 --- a/build/script/x86_64_opengauss_list +++ b/build/script/x86_64_opengauss_list @@ -76,20 +76,22 @@ ./share/postgresql/extension/spqplugin.control ./share/postgresql/extension/spqplugin--1.0.sql ./share/postgresql/extension/dolphin.control -./share/postgresql/extension/dolphin--3.0.sql +./share/postgresql/extension/dolphin--4.0.sql ./share/postgresql/extension/dolphin--1.0--1.1.sql ./share/postgresql/extension/dolphin--1.1--1.0.sql ./share/postgresql/extension/dolphin--1.1--2.0.sql ./share/postgresql/extension/dolphin--2.0--1.1.sql ./share/postgresql/extension/dolphin--2.0--3.0.sql ./share/postgresql/extension/dolphin--3.0--2.0.sql +./share/postgresql/extension/dolphin--3.0--4.0.sql +./share/postgresql/extension/dolphin--4.0--3.0.sql ./share/postgresql/extension/dolphin--2.0--2.0.1.sql ./share/postgresql/extension/dolphin--2.0.1--2.0.sql ./share/postgresql/extension/openGauss_expr_dolphin.ir ./share/postgresql/extension/age--1.0.0.sql ./share/postgresql/extension/age.control -./share/postgresql/extension/vector--0.4.4.sql -./share/postgresql/extension/vector.control +./share/postgresql/extension/datavec--0.4.4.sql +./share/postgresql/extension/datavec.control ./share/postgresql/extension/assessment--1.0.sql ./share/postgresql/extension/assessment.control ./share/postgresql/extension/file_fdw--1.0.sql @@ -110,6 +112,8 @@ ./share/postgresql/extension/dblink--1.0.sql ./share/postgresql/extension/dblink--unpackaged--1.0.sql ./share/postgresql/extension/dblink.control +./share/postgresql/extension/gms_profiler--1.0.sql +./share/postgresql/extension/gms_profiler.control ./share/postgresql/timezone/GB-Eire ./share/postgresql/timezone/Turkey ./share/postgresql/timezone/Kwajalein @@ -797,13 +801,14 @@ ./lib/postgresql/security_plugin.so ./lib/postgresql/dolphin.so ./lib/postgresql/age.so -./lib/postgresql/vector.so +./lib/postgresql/datavec.so ./lib/postgresql/pg_upgrade_support.so ./lib/postgresql/java/pljava.jar ./lib/postgresql/postgres_fdw.so ./lib/postgresql/dblink.so ./lib/postgresql/pgoutput.so ./lib/postgresql/assessment.so +./lib/postgresql/gms_profiler.so ./lib/libpljava.so ./lib/libpq.a ./lib/libpq.so @@ -812,10 +817,18 @@ ./lib/libpq_ce.so ./lib/libpq_ce.so.5 ./lib/libpq_ce.so.5.5 +./lib/libecpg.so +./lib/libecpg.so.6 ./lib/libecpg.so.6.4 +./lib/libecpg_compat.so +./lib/libecpg_compat.so.3 ./lib/libecpg_compat.so.3.4 ./lib/libecpg.a ./lib/libecpg_compat.a +./lib/libpgtypes.a +./lib/libpgtypes.so +./lib/libpgtypes.so.3 +./lib/libpgtypes.so.3.4 ./lib/libgauss_cl_jni.so ./lib/libcgroup.so* ./lib/libcom_err_gauss.so* @@ -1037,11 +1050,25 @@ ./include/postgresql/server/gstrace/gstrace_infra.h ./include/postgresql/server/extension_dependency.h ./include/postgresql/server/libpq/libpq-fe.h +./include/postgresql/server/ecpg/datetime.h +./include/postgresql/server/ecpg/decimal.h ./include/postgresql/server/ecpg/ecpgerrno.h -./include/postgresql/server/ecpg/ecpglib.h -./include/postgresql/server/ecpg/ecpgtype.h ./include/postgresql/server/ecpg/ecpg_informix.h ./include/postgresql/server/ecpg/ecpg_config.h +./include/postgresql/server/ecpg/ecpglib.h +./include/postgresql/server/ecpg/ecpg-pthread-win32.h +./include/postgresql/server/ecpg/ecpgtype.h +./include/postgresql/server/ecpg/pgtypes_date.h +./include/postgresql/server/ecpg/pgtypes_error.h +./include/postgresql/server/ecpg/pgtypes_interval.h +./include/postgresql/server/ecpg/pgtypes_numeric.h +./include/postgresql/server/ecpg/pgtypes_timestamp.h +./include/postgresql/server/ecpg/sql3types.h +./include/postgresql/server/ecpg/sqlca.h +./include/postgresql/server/ecpg/sqlda-compat.h +./include/postgresql/server/ecpg/sqlda.h +./include/postgresql/server/ecpg/sqlda-native.h +./include/postgresql/server/ecpg/sqltypes.h ./include/postgresql/server/access/clog.h ./include/postgresql/server/storage/proc.h ./include/postgresql/server/access/xlog.h diff --git a/configure b/configure index 8f8621c02f640d67f584faf735af0fa59b605a38..726648bd9d0b1ca9b6eba9665130c2aed174d02c 100755 --- a/configure +++ b/configure @@ -754,6 +754,7 @@ enable_jemalloc_debug enable_privategauss enable_multiple_nodes enable_lite_mode +enable_relocation enable_finance_mode enable_mot enable_bbox @@ -842,6 +843,7 @@ enable_jemalloc_debug enable_privategauss enable_multiple_nodes enable_lite_mode +enable_relocation enable_finance_mode enable_mot enable_bbox @@ -3234,7 +3236,21 @@ $as_echo "$as_me: error: no argument expected for --enable-finance-mode option" else enable_finance_mode=no +fi + +# Check whether --enable-relocation was given. +if test "$enable_relocation" = yes; then + major_version=$(echo "$gcc_version" | cut -d'.' -f1) + minor_version=$(echo "$gcc_version" | cut -d'.' -f2) + if (( major_version < 10 )) || (( major_version >= 10 && minor_version < 3 )); then + { { $as_echo "$as_me:$LINENO: error: --enable-relocation is not supported where GCC compiler version is less than 10.3." >&5 + $as_echo "$as_me: error: -enable-relocation is not supported where GCC compiler version is less than 10.3." >&2;} + { (exit 1); exit 1; }; } + fi + enable_relocation=yes +else + enable_relocation=no fi if test "$enable_lite_nodes" = yes; then diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 8f8db20bf3b81ba42c920e3d7809f6dfdb33f7ef..a7917aa1ccd3d7774b0f29d00133b96ab8bd8c16 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -24,6 +24,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gc_fdw ${CMAKE_CURRENT_SOURCE_DIR}/ndpplugin ${CMAKE_CURRENT_SOURCE_DIR}/spq_plugin + ${CMAKE_CURRENT_SOURCE_DIR}/gms_profiler ) add_subdirectory(hstore) @@ -48,3 +49,4 @@ add_subdirectory(ndpplugin) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/spq_plugin) add_subdirectory(spq_plugin) endif() +add_subdirectory(gms_profiler) diff --git a/contrib/Makefile b/contrib/Makefile index f1f57913cec569757fcbd81c44faf40f724563e3..91eda6c9a5507ba47752d85fd857a8556f815689 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -56,7 +56,8 @@ SUBDIRS = \ unaccent \ vacuumlo \ security_plugin \ - ndpplugin + ndpplugin \ + gms_profiler ifeq ($(with_openssl),yes) SUBDIRS += sslinfo diff --git a/contrib/gms_profiler/CMakeLists.txt b/contrib/gms_profiler/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c3b72cc11b750fc4409a99cc871d34923979c326 --- /dev/null +++ b/contrib/gms_profiler/CMakeLists.txt @@ -0,0 +1,24 @@ +#This is the main CMAKE for build all gms_profiler. +# gms_profiler.so + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} TGT_gms_profiler_SRC) + +SET(TGT_gms_profiler_INC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +set(gms_profiler_DEF_OPTIONS ${MACRO_OPTIONS} -DNDP_CLIENT -DGlobalCache) +set(gms_profiler_COMPILE_OPTIONS ${OPTIMIZE_OPTIONS} ${OS_OPTIONS} ${PROTECT_OPTIONS} ${WARNING_OPTIONS} ${LIB_SECURE_OPTIONS} ${CHECK_OPTIONS}) +set(gms_profiler_LINK_OPTIONS ${LIB_LINK_OPTIONS}) + +add_shared_libtarget(gms_profiler TGT_gms_profiler_SRC TGT_gms_profiler_INC "${gms_profiler_DEF_OPTIONS}" "${gms_profiler_COMPILE_OPTIONS}" "${gms_profiler_LINK_OPTIONS}") +set_target_properties(gms_profiler PROPERTIES PREFIX "") + +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gms_profiler.control + DESTINATION share/postgresql/extension/ +) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gms_profiler--1.0.sql + DESTINATION share/postgresql/extension/ +) + +install(TARGETS gms_profiler DESTINATION lib/postgresql) diff --git a/contrib/gms_profiler/Makefile b/contrib/gms_profiler/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dffec66d9863358ab39f3afd2052f3d331e7805c --- /dev/null +++ b/contrib/gms_profiler/Makefile @@ -0,0 +1,27 @@ +# contrib/gms_profiler/Makefile + +MODULE_big = gms_profiler +OBJS = gms_profiler.o + +EXTENSION = gms_profiler +DATA = gms_profiler--1.0.sql + +exclude_option = -fPIE +override CPPFLAGS := $(filter-out $(exclude_option),$(CPPFLAGS)) + +REGRESS = gms_profiler + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/gms_profiler +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +regress_home = $(top_builddir)/src/test/regress +REGRESS_OPTS = -c 0 -d 1 -r 1 -p 25632 --single_node -w --keep_last_data=false \ + --regconf=$(regress_home)/regress.conf \ + --temp-config=$(regress_home)/make_fastcheck_postgresql.conf +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/gms_profiler/data/dummy.txt b/contrib/gms_profiler/data/dummy.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e09a4f6cc37c0cf3bff8aee1477338865e35462 --- /dev/null +++ b/contrib/gms_profiler/data/dummy.txt @@ -0,0 +1 @@ +The openGauss regression needs this file to run. diff --git a/contrib/gms_profiler/expected/gms_profiler.out b/contrib/gms_profiler/expected/gms_profiler.out new file mode 100644 index 0000000000000000000000000000000000000000..550b8746a7db41bc4f3fce71869217fddc051d15 --- /dev/null +++ b/contrib/gms_profiler/expected/gms_profiler.out @@ -0,0 +1,266 @@ +SET client_min_messages = WARNING; +\set VERBOSITY terse +\set ECHO all +drop procedure if exists do_something; +drop procedure if exists do_wrapper; +drop procedure if exists test_profiler_start; +drop procedure if exists test_profiler_flush; +drop procedure if exists test_profiler_version; +drop procedure if exists test_profiler_pause; +drop procedure if exists test_profiler_resume; +drop procedure if exists test_profiler_resume2; +drop procedure if exists test_profiler_version_check; +drop procedure if exists test_profiler_start_ext; +create extension gms_profiler; +create or replace procedure do_something (p_times in number) as + l_dummy number; +begin +for i in 1 .. p_times loop +select l_dummy +1 +into l_dummy; +end loop; +end; +/ +create or replace procedure do_wrapper (p_times in number) as +begin +for i in 1 .. p_times loop + do_something(p_times); +end loop; +end; +/ +create or replace procedure test_profiler_start () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler', 'simple'); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ +create or replace procedure test_profiler_flush () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler_flush', 'flush'); + do_wrapper(p_times => 2); + l_result := gms_profiler.flush_data(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ +create or replace procedure test_profiler_version () as +declare +major_v binary_integer; + minor_v binary_integer; +begin +select major, minor into major_v, minor_v from gms_profiler.get_version(); +end; +/ +create or replace procedure test_profiler_pause () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler_pause', 'pause'); + do_wrapper(p_times => 2); + l_result := gms_profiler.pause_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ +create or replace procedure test_profiler_resume () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler_resume', 'resume1'); + do_wrapper(p_times => 2); + l_result := gms_profiler.pause_profiler(); + l_result := gms_profiler.resume_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ +create or replace procedure test_profiler_resume2 () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.resume_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.start_profiler('test_profiler_resume2', 'resume2'); + l_result := gms_profiler.pause_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.pause_profiler(); + l_result := gms_profiler.resume_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ +create or replace procedure test_profiler_version_check () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.internal_version_check(); +end; +/ +create or replace procedure test_profiler_start_ext () as +declare +l_result binary_integer; + runid binary_integer; +begin +select run_number, run_result into runid, l_result from gms_profiler.start_profiler_ext('start_profiler_ext'); +do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ +call test_profiler_start(); + test_profiler_start +--------------------- + +(1 row) + +call test_profiler_flush(); + test_profiler_flush +--------------------- + +(1 row) + +call test_profiler_version(); + test_profiler_version +----------------------- + +(1 row) + +call test_profiler_pause(); + test_profiler_pause +--------------------- + +(1 row) + +call test_profiler_resume(); + test_profiler_resume +---------------------- + +(1 row) + +call test_profiler_resume2(); + test_profiler_resume2 +----------------------- + +(1 row) + +call test_profiler_version_check(); + test_profiler_version_check +----------------------------- + +(1 row) + +call test_profiler_start_ext(); + test_profiler_start_ext +------------------------- + +(1 row) + +select runid, run_comment, run_comment1 from gms_profiler.plsql_profiler_runs order by runid; + runid | run_comment | run_comment1 +-------+-----------------------+-------------- + 1 | test_profiler | simple + 2 | test_profiler_flush | flush + 3 | test_profiler_pause | pause + 4 | test_profiler_resume | resume1 + 5 | test_profiler_resume2 | resume2 + 6 | start_profiler_ext | +(6 rows) + +select runid, unit_number, unit_type, unit_name from gms_profiler.plsql_profiler_units order by runid, unit_number; + runid | unit_number | unit_type | unit_name +-------+-------------+-----------------+-------------- + 1 | 1 | ANONYMOUS BLOCK | + 1 | 2 | PROCEDURE | do_wrapper + 1 | 3 | PROCEDURE | do_something + 2 | 1 | ANONYMOUS BLOCK | + 2 | 2 | PROCEDURE | do_wrapper + 2 | 3 | PROCEDURE | do_something + 3 | 1 | ANONYMOUS BLOCK | + 3 | 2 | PROCEDURE | do_wrapper + 3 | 3 | PROCEDURE | do_something + 4 | 1 | ANONYMOUS BLOCK | + 4 | 2 | PROCEDURE | do_wrapper + 4 | 3 | PROCEDURE | do_something + 5 | 1 | ANONYMOUS BLOCK | + 5 | 2 | PROCEDURE | do_wrapper + 5 | 3 | PROCEDURE | do_something + 6 | 1 | ANONYMOUS BLOCK | + 6 | 2 | PROCEDURE | do_wrapper + 6 | 3 | PROCEDURE | do_something +(18 rows) + +select runid, unit_number, line#, total_occur from gms_profiler.plsql_profiler_data order by runid, unit_number, line#; + runid | unit_number | line# | total_occur +-------+-------------+-------+------------- + 1 | 1 | 5 | 1 + 1 | 1 | 6 | 1 + 1 | 2 | 0 | 1 + 1 | 2 | 2 | 1 + 1 | 2 | 3 | 2 + 1 | 3 | 0 | 2 + 1 | 3 | 3 | 2 + 1 | 3 | 4 | 4 + 2 | 1 | 5 | 1 + 2 | 1 | 6 | 1 + 2 | 1 | 7 | 1 + 2 | 1 | 8 | 1 + 2 | 2 | 0 | 2 + 2 | 2 | 2 | 2 + 2 | 2 | 3 | 4 + 2 | 3 | 0 | 4 + 2 | 3 | 3 | 4 + 2 | 3 | 4 | 8 + 3 | 1 | 5 | 1 + 3 | 1 | 6 | 1 + 3 | 2 | 0 | 1 + 3 | 2 | 2 | 1 + 3 | 2 | 3 | 2 + 3 | 3 | 0 | 2 + 3 | 3 | 3 | 2 + 3 | 3 | 4 | 4 + 4 | 1 | 5 | 1 + 4 | 1 | 6 | 1 + 4 | 1 | 7 | 1 + 4 | 1 | 8 | 1 + 4 | 1 | 9 | 1 + 4 | 2 | 0 | 2 + 4 | 2 | 2 | 2 + 4 | 2 | 3 | 4 + 4 | 3 | 0 | 4 + 4 | 3 | 3 | 4 + 4 | 3 | 4 | 8 + 5 | 1 | 7 | 1 + 5 | 1 | 10 | 1 + 5 | 1 | 11 | 1 + 5 | 1 | 12 | 1 + 5 | 2 | 0 | 1 + 5 | 2 | 2 | 1 + 5 | 2 | 3 | 2 + 5 | 3 | 0 | 2 + 5 | 3 | 3 | 2 + 5 | 3 | 4 | 4 + 6 | 1 | 6 | 1 + 6 | 1 | 7 | 1 + 6 | 2 | 0 | 1 + 6 | 2 | 2 | 1 + 6 | 2 | 3 | 2 + 6 | 3 | 0 | 2 + 6 | 3 | 3 | 2 + 6 | 3 | 4 | 4 +(55 rows) + +drop procedure if exists do_something; +drop procedure if exists do_wrapper; +drop procedure if exists test_profiler_start; +drop procedure if exists test_profiler_flush; +drop procedure if exists test_profiler_version; +drop procedure if exists test_profiler_pause; +drop procedure if exists test_profiler_resume; +drop procedure if exists test_profiler_resume2; +drop procedure if exists test_profiler_version_check; +drop procedure if exists test_profiler_start_ext; +reset client_min_messages; diff --git a/contrib/gms_profiler/gms_profiler--1.0.sql b/contrib/gms_profiler/gms_profiler--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..ec91f3b0d66a84c4fbe04bc92a8fd03c005c8249 --- /dev/null +++ b/contrib/gms_profiler/gms_profiler--1.0.sql @@ -0,0 +1,127 @@ +/* contrib/gms_profiler/gms_profiler--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION gms_profiler" to load this file. \quit + +CREATE SCHEMA gms_profiler; + +CREATE or REPLACE FUNCTION gms_profiler.start_profiler(IN run_comment varchar2 DEFAULT '', IN run_comment1 varchar2 DEFAULT '', OUT run_result binary_integer) +AS 'MODULE_PATHNAME', 'start_profiler' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE or REPLACE FUNCTION gms_profiler.start_profiler_1(IN run_comment varchar2 DEFAULT '', IN run_comment1 varchar2 DEFAULT '') +returns void +AS 'MODULE_PATHNAME', 'start_profiler_1' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE or REPLACE FUNCTION gms_profiler.start_profiler_ext(IN run_comment varchar2 DEFAULT '' , +IN run_comment1 varchar2 DEFAULT '', OUT run_number binary_integer, OUT run_result binary_integer) +AS 'MODULE_PATHNAME', 'start_profiler_ext' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE or REPLACE FUNCTION gms_profiler.start_profiler_ext_1(IN run_comment varchar2 DEFAULT '' , +IN run_comment1 varchar2 DEFAULT '', OUT run_number binary_integer) +AS 'MODULE_PATHNAME', 'start_profiler_ext_1' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE or REPLACE FUNCTION gms_profiler.stop_profiler() +returns binary_integer +AS 'MODULE_PATHNAME', 'stop_profiler' +LANGUAGE C VOLATILE STRICT NOT FENCED; + +CREATE or REPLACE FUNCTION gms_profiler.flush_data() +returns binary_integer +AS 'MODULE_PATHNAME', 'flush_data' +LANGUAGE C VOLATILE STRICT NOT FENCED; + +CREATE or REPLACE PROCEDURE gms_profiler.get_version(OUT major binary_integer, OUT minor binary_integer) +AS +BEGIN + major := 1; + minor := 0; +END; + +CREATE or REPLACE FUNCTION gms_profiler.internal_version_check() +returns binary_integer as $$ +begin + return 0; +end; +$$ LANGUAGE plpgsql IMMUTABLE; + +CREATE or REPLACE FUNCTION gms_profiler.pause_profiler() +returns binary_integer +AS 'MODULE_PATHNAME', 'pause_profiler' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE or REPLACE FUNCTION gms_profiler.resume_profiler() +returns binary_integer +AS 'MODULE_PATHNAME', 'resume_profiler' +LANGUAGE C VOLATILE NOT FENCED; + +CREATE UNLOGGED TABLE gms_profiler.plsql_profiler_runs +( + runid number primary key, -- unique run identifier, + -- from plsql_profiler_runnumber + related_run number, -- runid of related run (for client/ + -- server correlation) + run_owner varchar2(32), -- user who started run + run_date date, -- start time of run + run_comment varchar2(2047), -- user provided comment for this run + run_total_time number, -- elapsed time for this run + run_system_info varchar2(2047), -- currently unused + run_comment1 varchar2(2047), -- additional comment + spare1 varchar2(256) -- unused +); + +COMMENT ON TABLE gms_profiler.plsql_profiler_runs is + 'Run-specific information for the PL/SQL profiler'; + + + +CREATE UNLOGGED TABLE gms_profiler.plsql_profiler_units +( + runid number references gms_profiler.plsql_profiler_runs, + unit_number number, -- internally generated library unit # + unit_type varchar2(32), -- library unit type + unit_owner varchar2(32), -- library unit owner name + unit_name varchar2(32), -- library unit name + -- timestamp on library unit, can be used to detect changes to + -- unit between runs + unit_timestamp date, + total_time number DEFAULT 0 NOT NULL, + spare1 number, -- unused + spare2 number, -- unused + -- + primary key (runid, unit_number) +); + +COMMENT ON TABLE gms_profiler.plsql_profiler_units is + 'Information about each library unit in a run'; + +CREATE UNLOGGED TABLE gms_profiler.plsql_profiler_data +( + runid number, -- unique (generated) run identifier + unit_number number, -- internally generated library unit # + line# number not null, -- line number in unit + total_occur number, -- number of times line was executed + total_time number, -- total time spent executing line + min_time number, -- minimum execution time for this line + max_time number, -- maximum execution time for this line + spare1 number, -- unused + spare2 number, -- unused + spare3 number, -- unused + spare4 number, -- unused + -- + primary key (runid, unit_number, line#), + foreign key (runid, unit_number) references gms_profiler.plsql_profiler_units +); + +COMMENT ON TABLE gms_profiler.plsql_profiler_data is + 'Accumulated data from all profiler runs'; + +CREATE SEQUENCE gms_profiler.plsql_profiler_runnumber start with 1 cache 1; + +GRANT USAGE ON SCHEMA gms_profiler TO public; +GRANT SELECT ON ALL tables IN SCHEMA gms_profiler TO public; +REVOKE EXECUTE ON ALL functions IN SCHEMA gms_profiler FROM public; +REVOKE USAGE ON SEQUENCE gms_profiler.plsql_profiler_runnumber FROM public; diff --git a/contrib/gms_profiler/gms_profiler.control b/contrib/gms_profiler/gms_profiler.control new file mode 100644 index 0000000000000000000000000000000000000000..04d7f81d60a345efa4ad7857e37dfc31824ba2c8 --- /dev/null +++ b/contrib/gms_profiler/gms_profiler.control @@ -0,0 +1,5 @@ +# gms_profiler extension +comment = 'collection of profiler data for PL/SQL applications' +default_version = '1.0' +module_pathname = '$libdir/gms_profiler' +relocatable = true diff --git a/contrib/gms_profiler/gms_profiler.cpp b/contrib/gms_profiler/gms_profiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c03dd34a84f1074aca7927c6ee6354eda897bdbc --- /dev/null +++ b/contrib/gms_profiler/gms_profiler.cpp @@ -0,0 +1,1281 @@ +/* + * gms_profiler.cpp + * + * IDENTIFICATION + * contrib/gms_profiler/gms_profiler.cpp + * + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "knl/knl_variable.h" +#include "utils/plpgsql.h" +#include "access/hash.h" +#include "utils/numeric.h" + +#include +#include +#include +#include "catalog/pg_authid.h" +#include "funcapi.h" +#include "catalog/pg_proc.h" +#include "commands/extension.h" +#include "utils/lsyscache.h" +#include "gms_profiler.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(start_profiler); +PG_FUNCTION_INFO_V1(start_profiler_1); +PG_FUNCTION_INFO_V1(start_profiler_ext); +PG_FUNCTION_INFO_V1(start_profiler_ext_1); +PG_FUNCTION_INFO_V1(stop_profiler); +PG_FUNCTION_INFO_V1(flush_data); +PG_FUNCTION_INFO_V1(pause_profiler); +PG_FUNCTION_INFO_V1(resume_profiler); + +static uint32 profiler_index; + +static void plpgsql_cb_func_beg(PLpgSQL_execstate *estate, PLpgSQL_function *func); +static void plpgsql_cb_func_end(PLpgSQL_execstate *estate, PLpgSQL_function *func); +static void plpgsql_cb_stmt_beg(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt); +static void plpgsql_cb_stmt_end(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt); + +static PLpgSQL_plugin plugin_funcs = { + NULL, + plpgsql_cb_func_beg, + plpgsql_cb_func_end, + plpgsql_cb_stmt_beg, + plpgsql_cb_stmt_end, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void set_extension_index(uint32 index) +{ + profiler_index = index; +} + +void init_session_vars(void) +{ + RepallocSessionVarsArrayIfNecessary(); + + ProfilerContext* psc = + (ProfilerContext*)MemoryContextAllocZero(u_sess->self_mem_cxt, sizeof(ProfilerContext)); + u_sess->attr.attr_common.extension_session_vars_array[profiler_index] = psc; + + psc->mem_cxt = u_sess->self_mem_cxt; + psc->state = PROFILER_INACTIVE; + + u_sess->plsql_cxt.plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin"); + *u_sess->plsql_cxt.plugin_ptr = &plugin_funcs; +} + +ProfilerContext* get_session_context() +{ + if (u_sess->attr.attr_common.extension_session_vars_array[profiler_index] == NULL) { + init_session_vars(); + } + return (ProfilerContext*)u_sess->attr.attr_common.extension_session_vars_array[profiler_index]; +} + +static bool check_profiler_table_exists(void) +{ + Oid profiler_table_oid = InvalidOid; + + Oid namespaceId = LookupExplicitNamespace("gms_profiler", true); + if (namespaceId == InvalidOid) + return false; + + profiler_table_oid = get_relname_relid("plsql_profiler_runnumber", namespaceId); + if (profiler_table_oid == InvalidOid) + return false; + + profiler_table_oid = get_relname_relid("plsql_profiler_runs", namespaceId); + if (profiler_table_oid == InvalidOid) + return false; + + profiler_table_oid = get_relname_relid("plsql_profiler_units", namespaceId); + if (profiler_table_oid == InvalidOid) + return false; + + profiler_table_oid = get_relname_relid("plsql_profiler_data", namespaceId); + if (profiler_table_oid == InvalidOid) + return false; + + return true; +} + +static uint32 get_runid_from_profiler_sequence(bool curr_val) +{ + StringInfoData buf; + int ret; + uint32 runid = 0; + + if (SPI_connect() < 0) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("SPI_connect failed"))); + + initStringInfo(&buf); + if (curr_val) + appendStringInfo(&buf, "select currval('gms_profiler.plsql_profiler_runnumber');"); + else + appendStringInfo(&buf, "select nextval('gms_profiler.plsql_profiler_runnumber');"); + + ret = SPI_exec(buf.data, 0, NULL); + pfree(buf.data); + + if ((ret == SPI_OK_SELECT) && (SPI_processed == 1)) { + char *value = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); + char *end; + runid = strtoul(value, &end, 10); + } + SPI_finish(); + + elog(DEBUG1, "get_runid_from_profiler_sequence get runid %u", runid); + + if (!runid) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("can not get runid from plsql_profiler_runnumber"))); + + return runid; +} + +static void update_profiler_unit_entry(ProfilerUnitHashEntry *unit_entry, SPIPlanPtr plan) +{ + ProfilerContext *profiler_cxt = get_session_context(); + Datum values[3]; + char nulls[3] = {' ', ' ', ' '}; + StringInfoData buf; + int ret; + + /* values 0 total_time */ + initStringInfo(&buf); + appendStringInfo(&buf, "%ld", unit_entry->total_time); + values[0] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 1 runid */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", profiler_cxt->runid); + values[1] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 2: unit_number */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", unit_entry->unit_number); + values[2] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + pfree(buf.data); + + ret = SPI_execute_plan(plan, values, nulls, false, 1); + if (ret != SPI_OK_UPDATE) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("can't update total_time of plsql_profiler_units"))); + +} + +static void insert_profiler_unit_entry(ProfilerUnitHashEntry *unit_entry, SPIPlanPtr plan) +{ + HeapTuple proc_tup; + HeapTuple auth_tp; + bool is_null; + Datum kind_datum; + char proc_type; + StringInfoData buf; + Form_pg_proc proc_struct; + Form_pg_authid authid_struct; + char *unit_name; + char *usename; + ProfilerContext *profiler_cxt = get_session_context(); + Datum values[7]; + char nulls[7] = {' ', ' ', ' ', ' ', ' ', ' ', ' '}; + Oid proc_owner; + int ret; + + /* values 0: runid */ + initStringInfo(&buf); + appendStringInfo(&buf, "%u", profiler_cxt->runid); + values[0] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 1: unit_number */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", unit_entry->unit_number); + values[1] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + if (unit_entry->unit_oid == InvalidOid) { + /* values 2: unit_type when unit_oid is 0, unit_number must be 1, + * regard it as an anonymous block */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", "ANONYMOUS BLOCK"); + values[2] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + + /* values 3: unit_owner anonymous*/ + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", ""); + values[3] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + + /* values 4: unit_name anonymous*/ + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", ""); + values[4] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + + } else { + /* values 2: unit_type PROCEDURE or FUNCTION + * should get prokind attr from pg_proc */ + proc_tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(unit_entry->unit_oid)); + if (!HeapTupleIsValid(proc_tup)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("cache lookup failed for function %u", unit_entry->unit_oid))); + } + + kind_datum = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_prokind, &is_null); + proc_type = DatumGetChar(kind_datum); + + resetStringInfo(&buf); + + if (proc_type == 'f') { + appendStringInfo(&buf, "%s", "FUNCTION"); + } else if (proc_type == 'p') { + appendStringInfo(&buf, "%s", "PROCEDURE"); + } else { + appendStringInfo(&buf, "%s", "UNKNOWN"); + } + + values[2] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + + /* values 4: unit_name + * unit_name is in the pg_proc system table, + * so get it before unit_owner */ + + proc_struct = (Form_pg_proc) GETSTRUCT(proc_tup); + unit_name = NameStr(proc_struct->proname); + + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", unit_name); + values[4] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + + /* get proc_owner oid before release cache */ + proc_owner = proc_struct->proowner; + ReleaseSysCache(proc_tup); + + /* values 3: unit_owner */ + auth_tp = SearchSysCache1(AUTHOID, ObjectIdGetDatum(proc_owner)); + if (!HeapTupleIsValid(auth_tp)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("cache lookup failed for proc owner %u", proc_owner))); + } + + authid_struct = (Form_pg_authid) GETSTRUCT(auth_tp); + usename = NameStr(authid_struct->rolname); + + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", usename); + values[3] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + ReleaseSysCache(auth_tp); + } + + /* unit5 unit_timestamp */ + Datum timestamp; + Datum timestamp_scaled; + timestamp = DirectFunctionCall1(timestamptz_timestamp, unit_entry->unit_timestamp); + timestamp_scaled = DirectFunctionCall2(timestamp_scale, timestamp, Int32GetDatum(0)); + values[5] = timestamp_scaled; + + /* unit6 total_time */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%ld", unit_entry->total_time); + values[6] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + pfree(buf.data); + + ret = SPI_execute_plan(plan, values, nulls, false, 1); + if (ret != SPI_OK_INSERT) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("can't insert data into plsql_profiler_units"))); + +} + +static void flush_profiler_units(void) +{ + SPIPlanPtr insert_plan = NULL; + SPIPlanPtr update_plan = NULL; + Oid insert_argtypes[] = {NUMERICOID, NUMERICOID, VARCHAROID, VARCHAROID, VARCHAROID, TIMESTAMPOID, NUMERICOID}; + Oid update_argtypes[] = {NUMERICOID, NUMERICOID, NUMERICOID}; + ProfilerContext *profiler_cxt = get_session_context(); + HASH_SEQ_STATUS scan; + ProfilerUnitHashEntry *unit_entry; + + insert_plan = SPI_prepare("insert into gms_profiler.plsql_profiler_units (runid, unit_number, " + "unit_type, unit_owner, unit_name, unit_timestamp, total_time) " + "values ($1, $2, $3, $4, $5, $6, $7)", 7, insert_argtypes); + if (insert_plan == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("SPI_prepare insert into plsql_profiler_units failed"))); + + update_plan = SPI_prepare("update gms_profiler.plsql_profiler_units set total_time = $1 " + "where runid = $2 and unit_number = $3", + 3, update_argtypes); + if (update_plan == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("SPI_prepare update plsql_profiler_units failed"))); + + hash_seq_init(&scan, profiler_cxt->unit_hash); + while ((unit_entry = (ProfilerUnitHashEntry *)hash_seq_search(&scan))) { + if (unit_entry->unit_flushed) { + elog(DEBUG1, "update_profiler_unit_entry %u %u ", profiler_cxt->runid, unit_entry->unit_number); + update_profiler_unit_entry(unit_entry, update_plan); + } else { + elog(DEBUG1, "insert_profiler_unit_entry %u %u ", profiler_cxt->runid, unit_entry->unit_number); + insert_profiler_unit_entry(unit_entry, insert_plan); + unit_entry->unit_flushed = true; + } + } +} + +static void insert_profiler_data_entry(ProfilerDataHashEntry *data_entry, SPIPlanPtr plan) +{ + StringInfoData buf; + ProfilerContext *profiler_cxt = get_session_context(); + Datum values[7]; + char nulls[7] = {' ', ' ', ' ', ' ', ' ', ' ', ' '}; + int ret; + + /* values 0: runid */ + initStringInfo(&buf); + appendStringInfo(&buf, "%u", profiler_cxt->runid); + values[0] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 1: unit_number */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", data_entry->unit_number); + values[1] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 2: lineno */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", data_entry->lineno); + values[2] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 3: total occur */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", data_entry->total_occur); + values[3] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 4: total time */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%ld", data_entry->total_time); + values[4] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 5: min time */ + resetStringInfo(&buf); + if (data_entry->min_time == INT64_MAX) + appendStringInfo(&buf, "%d", 0); + else + appendStringInfo(&buf, "%ld", data_entry->min_time); + values[5] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 6: max time */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%ld", data_entry->max_time); + values[6] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + pfree(buf.data); + + ret = SPI_execute_plan(plan, values, nulls, false, 1); + if (ret != SPI_OK_INSERT) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("can't insert data into plsql_profiler_data"))); +} + +static void update_profiler_data_entry(ProfilerDataHashEntry *data_entry, SPIPlanPtr plan) +{ + StringInfoData buf; + ProfilerContext *profiler_cxt = get_session_context(); + Datum values[7]; + char nulls[7] = {' ', ' ', ' ', ' ', ' ', ' ', ' '}; + int ret; + + /* values 0: total occur */ + initStringInfo(&buf); + appendStringInfo(&buf, "%u", data_entry->total_occur); + values[0] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 1: total time */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%ld", data_entry->total_time); + values[1] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 2: min time */ + resetStringInfo(&buf); + if (data_entry->min_time == INT64_MAX) + appendStringInfo(&buf, "%d", 0); + else + appendStringInfo(&buf, "%ld", data_entry->min_time); + values[2] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 3: max time */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%ld", data_entry->max_time); + values[3] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 4: runid */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", profiler_cxt->runid); + values[4] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 5: unit_number */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", data_entry->unit_number); + values[5] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 6: lineno */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", data_entry->lineno); + values[6] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + pfree(buf.data); + + ret = SPI_execute_plan(plan, values, nulls, false, 1); + if (ret != SPI_OK_UPDATE) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("can't update plsql_profiler_data data"))); +} + +static void flush_profiler_data(void) +{ + SPIPlanPtr insert_plan = NULL; + SPIPlanPtr update_plan = NULL; + Oid argtypes[] = {NUMERICOID, NUMERICOID, NUMERICOID, NUMERICOID, NUMERICOID, NUMERICOID, NUMERICOID}; + ProfilerContext *profiler_cxt = get_session_context(); + HASH_SEQ_STATUS scan; + ProfilerDataHashEntry *data_entry; + + insert_plan = SPI_prepare("insert into gms_profiler.plsql_profiler_data (runid, unit_number, " + "line#, total_occur, total_time, min_time, max_time) " + "values ($1, $2, $3, $4, $5, $6, $7)", 7, argtypes); + if (insert_plan == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("SPI_prepare insert into plsql_profiler_data failed"))); + + update_plan = SPI_prepare("update gms_profiler.plsql_profiler_data set total_occur = $1, " + "total_time = $2, min_time = $3, max_time = $4 where runid = $5" + " and unit_number = $6 and line# = $7", 7, argtypes); + if (update_plan == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("SPI_prepare update plsql_profiler_data failed"))); + + hash_seq_init(&scan, profiler_cxt->data_hash); + while ((data_entry = (ProfilerDataHashEntry *)hash_seq_search(&scan))) { + if (data_entry->data_flushed) { + elog(DEBUG1, "update data %u %u %u", profiler_cxt->runid, data_entry->unit_number, data_entry->lineno); + update_profiler_data_entry(data_entry, update_plan); + } else { + elog(DEBUG1, "insert data %u %u %u", profiler_cxt->runid, data_entry->unit_number, data_entry->lineno); + insert_profiler_data_entry(data_entry, insert_plan); + data_entry->data_flushed = true; + } + } +} + +static void update_profiler_runs() +{ + StringInfoData buf; + int ret; + ProfilerContext *profiler_cxt = get_session_context(); + SPIPlanPtr plan = NULL; + Datum values[2]; + char nulls[2] = {' ', ' '}; + Oid argtypes[2] = {NUMERICOID, NUMERICOID}; + + plan = SPI_prepare("update gms_profiler.plsql_profiler_runs set run_total_time = $1 where runid = $2", 2, argtypes); + if (plan == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("SPI_prepare update plsql_profiler_runs failed"))); + + /* values 0: run_total_time */ + initStringInfo(&buf); + appendStringInfo(&buf, "%lu", profiler_cxt->run_total_time); + values[0] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 1: runid */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%u", profiler_cxt->runid); + values[1] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + pfree(buf.data); + + ret = SPI_execute_plan(plan, values, nulls, false, 1); + if (ret != SPI_OK_UPDATE) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("can't update run_total_time of plsql_profiler_runs"))); +} + +static void insert_profiler_runs(void) +{ + StringInfoData buf; + int ret; + ProfilerContext *profiler_cxt = get_session_context(); + HeapTuple auth_tp; + Form_pg_authid authid_struct; + SPIPlanPtr plan = NULL; + Datum values[6]; + char nulls[6] = {' ', ' ', ' ', ' ', ' ', ' '}; + Oid argtypes[] = {NUMERICOID, VARCHAROID, TIMESTAMPOID, VARCHAROID, NUMERICOID, VARCHAROID}; + + plan = SPI_prepare("insert into gms_profiler.plsql_profiler_runs (runid, run_owner, " + "run_date, run_comment, run_total_time, run_comment1) " + "values ($1, $2, $3, $4, $5, $6)", 6, argtypes); + if (plan == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("SPI_prepare insert into plsql_profiler_runs failed"))); + + /* values 0: runid */ + initStringInfo(&buf); + appendStringInfo(&buf, "%u", profiler_cxt->runid); + values[0] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 1: run_owner */ + if (profiler_cxt->run_owner != InvalidOid) { + auth_tp = SearchSysCache1(AUTHOID, ObjectIdGetDatum(profiler_cxt->run_owner)); + if (!HeapTupleIsValid(auth_tp)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("cache lookup failed for proc owner %u", profiler_cxt->run_owner))); + } + + authid_struct = (Form_pg_authid) GETSTRUCT(auth_tp); + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", NameStr(authid_struct->rolname)); + values[1] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + ReleaseSysCache(auth_tp); + } else { + nulls[1] = 'n'; + } + + /* values 2: run_date */ + Datum timestamp; + Datum timestamp_scaled; + timestamp = DirectFunctionCall1(timestamptz_timestamp, profiler_cxt->run_timestamp); + timestamp_scaled = DirectFunctionCall2(timestamp_scale, timestamp, Int32GetDatum(0)); + values[2] = timestamp_scaled; + + /* values 3: run_comment */ + if (profiler_cxt->run_comment) { + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", profiler_cxt->run_comment); + values[3] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + } else { + nulls[3] = 'n'; + } + + /* values 4: run_total_time */ + resetStringInfo(&buf); + appendStringInfo(&buf, "%lu", profiler_cxt->run_total_time); + values[4] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf.data), + ObjectIdGetDatum(0), Int32GetDatum(-1)); + + /* values 5: run_comment1 */ + if (profiler_cxt->run_comment1) { + resetStringInfo(&buf); + appendStringInfo(&buf, "%s", profiler_cxt->run_comment1); + values[5] = DirectFunctionCall1(varcharin, CStringGetDatum(buf.data)); + } else { + nulls[5] = 'n'; + } + + pfree(buf.data); + + ret = SPI_execute_plan(plan, values, nulls, false, 1); + if (ret != SPI_OK_INSERT) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("can't insert data into plsql_profiler_runs"))); + +} + +static void flush_profiler_runs() { + ProfilerContext *profiler_cxt = get_session_context(); + + if (profiler_cxt->runinfo_flushed) { + elog(DEBUG1, "update_profiler_runs %u", profiler_cxt->runid); + update_profiler_runs(); + } else { + elog(DEBUG1, "insert_profiler_runs %u ", profiler_cxt->runid); + insert_profiler_runs(); + profiler_cxt->runinfo_flushed = true; + } +} + +static void flush_profiler_to_table(void) +{ + if (SPI_connect() < 0) + ereport(ERROR,(errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed"))); + + flush_profiler_runs(); + flush_profiler_units(); + flush_profiler_data(); + + SPI_finish(); +} + +static int start_profiler_internal(FunctionCallInfo fcinfo, uint32 *runid) +{ + char *run_comment = NULL; + char *run_comment1 = NULL; + HASHCTL unit_hash_ctl; + HASHCTL data_hash_ctl; + ProfilerUnitHashKey unit_key; + ProfilerUnitHashEntry *unit_entry; + bool found; + errno_t rc; + int32 result = PROFILER_ERROR_OK; + ProfilerContext *profiler_cxt = get_session_context(); + + if (RecoveryInProgress()) + elog(ERROR, "Standby do not support gms_profiler, please do it in primary!"); + + if ((!u_sess->plsql_cxt.inited) || (!profiler_cxt)) + return PROFILER_ERROR_PARAM; + + /* start_profiler can not thow any exception */ + PG_TRY(); + { + if ((PG_NARGS() >= 1) && (!PG_ARGISNULL(0))) + run_comment = text_to_cstring(PG_GETARG_VARCHAR_PP(0)); + else { + Datum timestamp; + Datum timestamp_scaled; + timestamp = DirectFunctionCall1(timestamptz_timestamp, GetCurrentTimestamp()); + timestamp_scaled = DirectFunctionCall2(timestamp_scale, timestamp, Int32GetDatum(0)); + run_comment = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp_scaled)); + } + + if ((PG_NARGS() >= 2) && (!PG_ARGISNULL(1))) + run_comment1 = text_to_cstring(PG_GETARG_VARCHAR_PP(1)); + + + /* If call start_profiler twice without call stop profiler, do not get new runnid */ + if ((profiler_cxt->state == PROFILER_ACTIVE) || (profiler_cxt->state == PROFILER_PAUSED)) + profiler_cxt->runid = get_runid_from_profiler_sequence(true); + else + profiler_cxt->runid = get_runid_from_profiler_sequence(false); + + profiler_cxt->state = PROFILER_ACTIVE; + profiler_cxt->current_unit_number = 1; + profiler_cxt->max_unit_number = 1; + profiler_cxt->run_owner = GetUserId(); + profiler_cxt->run_timestamp = GetCurrentTimestamp(); + profiler_cxt->run_comment = MemoryContextStrdup(profiler_cxt->mem_cxt, run_comment); + profiler_cxt->run_comment1 = MemoryContextStrdup(profiler_cxt->mem_cxt, run_comment1); + profiler_cxt->runinfo_flushed = false; + profiler_cxt->in_stmt = 0; + + if (profiler_cxt->unit_stack) + pfree_ext(profiler_cxt->unit_stack); + + profiler_cxt->unit_stack = (uint32 *) MemoryContextAllocZero(profiler_cxt->mem_cxt, + sizeof(uint32) * PROFILER_UNIT_STACK_SIZE); + /* Push first unit number */ + profiler_cxt->unit_stack[0] = profiler_cxt->current_unit_number; + profiler_cxt->unit_stack_top = 1; + + if (profiler_cxt->unit_hash) + hash_destroy(profiler_cxt->unit_hash); + + profiler_cxt->unit_hash = NULL; + + rc = memset_s(&unit_hash_ctl, sizeof(unit_hash_ctl), 0, sizeof(unit_hash_ctl)); + securec_check(rc, "\0", "\0"); + + unit_hash_ctl.keysize = sizeof(ProfilerUnitHashKey); + unit_hash_ctl.entrysize = sizeof(ProfilerUnitHashEntry); + unit_hash_ctl.hash = tag_hash; + unit_hash_ctl.hcxt = profiler_cxt->mem_cxt; + profiler_cxt->unit_hash = hash_create("dmbs profiler unit hash", PROFILER_UNIT_HASH_NUMBER, + &unit_hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + + if (profiler_cxt->data_hash) + hash_destroy(profiler_cxt->data_hash); + + profiler_cxt->data_hash = NULL; + + rc = memset_s(&data_hash_ctl, sizeof(data_hash_ctl), 0, sizeof(data_hash_ctl)); + securec_check(rc, "\0", "\0"); + + data_hash_ctl.keysize = sizeof(ProfilerDataHashKey); + data_hash_ctl.entrysize = sizeof(ProfilerDataHashEntry); + data_hash_ctl.hash = tag_hash; + data_hash_ctl.hcxt = profiler_cxt->mem_cxt; + profiler_cxt->data_hash = hash_create("dmbs profiler data hash", PROFILER_DATA_HASH_NUMBER, + &data_hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + + /* unit_number 1 is anonymous block */ + unit_key.unit_oid = 0; + unit_entry = (ProfilerUnitHashEntry *) hash_search(profiler_cxt->unit_hash, (void *) &unit_key, + HASH_ENTER, &found); + Assert(unit_entry); + unit_entry->unit_oid = 0; + unit_entry->unit_number = profiler_cxt->current_unit_number; + unit_entry->unit_timestamp = GetCurrentTimestamp(); + unit_entry->total_time = 0; + unit_entry->unit_flushed = false; + + elog(DEBUG1, "start_profiler state %d runid %d current_unit_number %u max_unit_number %u", + profiler_cxt->state, profiler_cxt->runid, + profiler_cxt->current_unit_number, + profiler_cxt->max_unit_number); + + *runid = profiler_cxt->runid; + } + PG_CATCH(); + { + pfree_ext(profiler_cxt->unit_stack); + + hash_destroy(profiler_cxt->data_hash); + profiler_cxt->data_hash = NULL; + + hash_destroy(profiler_cxt->data_hash); + profiler_cxt->data_hash = NULL; + + pfree_ext(profiler_cxt->run_comment); + pfree_ext(profiler_cxt->run_comment1); + + FlushErrorState(); + result = PROFILER_ERROR_IO; + } + PG_END_TRY(); + return result; +} + +static Datum make_profiler_result(uint32 runid, int32 result) +{ + TupleDesc tupdesc; + Datum values[2]; + bool nulls[2]; + HeapTuple htup; + + tupdesc = CreateTemplateTupleDesc(2, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "run_number", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "result", + INT4OID, -1, 0); + tupdesc = BlessTupleDesc(tupdesc); + + values[0] = UInt32GetDatum(runid); + values[1] = Int32GetDatum(result); + nulls[0] = false; + nulls[1] = false; + + htup = heap_form_tuple(tupdesc, values, nulls); + + return HeapTupleGetDatum(htup); +} + +/* + * begin_profile_block + * At the begining of execute plpgsql procedure block + * call this function to generate new unit number if this block is not called before + * get it's unit number from unit_hash if block is called. + * + */ +static void begin_profile_block(Oid block_oid) +{ + bool is_null; + char *proc_name; + char proc_type; + Oid proc_owner; + Form_pg_proc proc_struct; + Form_pg_authid authid_struct; + char *usename; + ProfilerContext *profiler_cxt = get_session_context(); + ProfilerUnitHashKey unit_key; + ProfilerUnitHashEntry *unit_entry; + bool found; + + if ((!u_sess->plsql_cxt.inited) || !check_profiler_table_exists() || (!profiler_cxt) + || (profiler_cxt->state != PROFILER_ACTIVE)) + return; + + unit_key.unit_oid = block_oid; + unit_entry = (ProfilerUnitHashEntry*)hash_search(profiler_cxt->unit_hash, (void*)&unit_key, HASH_ENTER, &found); + Assert(unit_entry); + if (!found) { + unit_entry->unit_oid = block_oid; + profiler_cxt->max_unit_number += 1; + profiler_cxt->current_unit_number = profiler_cxt->max_unit_number; + unit_entry->unit_number = profiler_cxt->current_unit_number; + unit_entry->unit_timestamp = GetCurrentTimestamp(); + unit_entry->total_time = 0; + unit_entry->unit_flushed = false; + } else { + profiler_cxt->current_unit_number = unit_entry->unit_number; + unit_entry->unit_timestamp = GetCurrentTimestamp(); + } + + if (profiler_cxt->unit_stack_top >= PROFILER_UNIT_STACK_SIZE) { + ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("procedure stack depth is too much"))); + } + + profiler_cxt->unit_stack[profiler_cxt->unit_stack_top++] = profiler_cxt->current_unit_number; + + HeapTuple tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(block_oid)); + if (!HeapTupleIsValid(tp)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("cache lookup failed for function %u", block_oid))); + } + + proc_struct = (Form_pg_proc)GETSTRUCT(tp); + proc_name = NameStr(proc_struct->proname); + proc_owner = proc_struct->proowner; + + Datum kind_datum = SysCacheGetAttr(PROCOID, tp, Anum_pg_proc_prokind, &is_null); + proc_type = DatumGetChar(kind_datum); + ReleaseSysCache(tp); + + tp = SearchSysCache1(AUTHOID, ObjectIdGetDatum(proc_owner)); + if (!HeapTupleIsValid(tp)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("cache lookup failed for function %u", proc_owner))); + } + + authid_struct = (Form_pg_authid)GETSTRUCT(tp); + usename = NameStr(authid_struct->rolname); + ReleaseSysCache(tp); + + elog(DEBUG1, "block begin oid %u unit_number %u, proc_name %s proc_type %c", + block_oid, + profiler_cxt->current_unit_number, + proc_name, + proc_type); +} + +/* + * end_profile_block + * At the end of execute plpgsql procedure block + * call this function to record this block execute time + * + */ +static void end_profile_block(Oid block_oid) +{ + TimestampTz current_timestamp; + ProfilerContext *profiler_cxt = get_session_context(); + ProfilerUnitHashKey unit_key; + ProfilerUnitHashEntry *unit_entry; + bool found; + + if ((!u_sess->plsql_cxt.inited) || !check_profiler_table_exists() || (!profiler_cxt) + || (profiler_cxt->state != PROFILER_ACTIVE)) + return; + + unit_key.unit_oid = block_oid; + + unit_entry = (ProfilerUnitHashEntry*)hash_search(profiler_cxt->unit_hash, + (void*)&unit_key, HASH_ENTER, &found); + if (!found) { + elog(ERROR, "can not find unit oid %u", block_oid); + } else { + current_timestamp = GetCurrentTimestamp(); + unit_entry->total_time += current_timestamp - unit_entry->unit_timestamp; + } + + /* pop unit number from unit stack */ + profiler_cxt->unit_stack_top--; + + /* restore previous unit number */ + if (profiler_cxt->unit_stack_top >= 1) { + profiler_cxt->current_unit_number = profiler_cxt->unit_stack[profiler_cxt->unit_stack_top-1]; + } + + if (profiler_cxt->current_unit_number < 1 || + profiler_cxt->current_unit_number > profiler_cxt->max_unit_number) { + elog(DEBUG1, "Wrong unit_number %u", profiler_cxt->current_unit_number); + return; + } + + elog(DEBUG1, "block end oid %u current_unit_number %u", + block_oid, + profiler_cxt->current_unit_number); +} + +/* + * begin_profile_stmt + * At the begining of execute plpgsql statement + * call this function to record statement start timestamp + * and occures + */ +static void begin_profile_stmt(int lineno) +{ + ProfilerContext *profiler_cxt = get_session_context(); + ProfilerDataHashKey line_key; + ProfilerDataHashEntry *line_entry; + bool found; + + if ((!u_sess->plsql_cxt.inited) || !check_profiler_table_exists() || (!profiler_cxt) + || (profiler_cxt->state != PROFILER_ACTIVE)) + return; + + /* use in_stmt to assure begin_profile_stmt is called + * before end_profile_stmt is called */ + profiler_cxt->in_stmt += 1; + + line_key.unit_number = profiler_cxt->current_unit_number; + line_key.lineno = lineno; + line_entry = (ProfilerDataHashEntry*)hash_search(profiler_cxt->data_hash, + (void*)&line_key, HASH_ENTER, &found); + Assert(line_entry); + if (!found) { + line_entry->unit_number = profiler_cxt->current_unit_number; + line_entry->lineno = lineno; + line_entry->stmt_timestamp = GetCurrentTimestamp(); + line_entry->total_occur = 1; + line_entry->total_time = 0; + line_entry->min_time = INT64_MAX; + line_entry->max_time = 0; + line_entry->data_flushed = false; + } else { + line_entry->stmt_timestamp = GetCurrentTimestamp(); + line_entry->total_occur += 1; + } + + elog(DEBUG1, "stmt begin runid %u unit_number %u lineno %d " + "stmt_timestamp %ld total_occur %u total_time %ld min_time %ld max_time %ld", + profiler_cxt->runid, profiler_cxt->current_unit_number, lineno, + line_entry->stmt_timestamp, line_entry->total_occur, line_entry->total_time, + line_entry->min_time, line_entry->max_time); +} + +/* + * end_profile_stmt + * At the end of execute plpgsql statement + * call this function to record statement exuecte time + */ +static void end_profile_stmt(int lineno) +{ + ProfilerContext *profiler_cxt = get_session_context(); + ProfilerDataHashKey line_key; + ProfilerDataHashEntry *line_entry; + bool found; + int64 stmt_time; + + if ((!u_sess->plsql_cxt.inited) || !check_profiler_table_exists() || (!profiler_cxt) + || (profiler_cxt->state != PROFILER_ACTIVE)) + return; + + /* if in_stmt < 1 means begin_profile_stmt is not called before */ + if (profiler_cxt->in_stmt < 1) + return; + + profiler_cxt->in_stmt -= 1; + + line_key.unit_number = profiler_cxt->current_unit_number; + line_key.lineno = lineno; + line_entry = (ProfilerDataHashEntry*)hash_search(profiler_cxt->data_hash, (void*)&line_key, HASH_ENTER, &found); + Assert(line_entry); + if (!found) { + line_entry->unit_number = profiler_cxt->current_unit_number; + line_entry->lineno = lineno; + line_entry->stmt_timestamp = GetCurrentTimestamp(); + line_entry->total_occur = 1; + line_entry->total_time = 0; + line_entry->min_time = INT64_MAX; + line_entry->max_time = 0; + line_entry->data_flushed = false; + } else { + stmt_time = GetCurrentTimestamp() - line_entry->stmt_timestamp; + line_entry->total_time += stmt_time; + + if (stmt_time < line_entry->min_time) + line_entry->min_time = stmt_time; + + if (stmt_time > line_entry->max_time) + line_entry->max_time = stmt_time; + } + + elog(DEBUG1, "stmt end runid %u unit_number %u lineno %d " + "stmt_timestamp %ld total_occur %u total_time %ld min_time %ld max_time %ld", + profiler_cxt->runid, profiler_cxt->current_unit_number, lineno, + line_entry->stmt_timestamp, line_entry->total_occur, line_entry->total_time, + line_entry->min_time, line_entry->max_time); +} + +/* + * profile_stmt_once + * For loop/while/for statement, only record statement occures + * do not record statement execute time. + */ +static void profile_stmt_once(int lineno) +{ + ProfilerContext *profiler_cxt = get_session_context(); + ProfilerDataHashKey line_key; + ProfilerDataHashEntry *line_entry; + bool found; + + if ((!u_sess->plsql_cxt.inited) || !check_profiler_table_exists() || (!profiler_cxt) + || (profiler_cxt->state != PROFILER_ACTIVE)) + return; + + line_key.unit_number = profiler_cxt->current_unit_number; + line_key.lineno = lineno; + line_entry = (ProfilerDataHashEntry*)hash_search(profiler_cxt->data_hash, (void*)&line_key, HASH_ENTER, &found); + Assert(line_entry); + if (!found) { + line_entry->unit_number = profiler_cxt->current_unit_number; + line_entry->lineno = lineno; + line_entry->stmt_timestamp = GetCurrentTimestamp(); + line_entry->total_occur = 1; + line_entry->total_time = 0; + line_entry->min_time = INT64_MAX; + line_entry->max_time = 0; + line_entry->data_flushed = false; + } else { + line_entry->total_occur += 1; + } + + elog(DEBUG1, "stmt once runid %u unit_number %u lineno %d", + profiler_cxt->runid, profiler_cxt->current_unit_number, lineno); +} + +static bool cmdtype_is_loop(int cmdtype) +{ + if ((cmdtype == PLPGSQL_STMT_LOOP) || (cmdtype == PLPGSQL_STMT_WHILE) || (cmdtype == PLPGSQL_STMT_FORI) + || (cmdtype == PLPGSQL_STMT_FORS) || (cmdtype == PLPGSQL_STMT_FORC) || (cmdtype == PLPGSQL_STMT_FOREACH_A)) + return true; + else + return false; + +} + +static void plpgsql_cb_func_beg(PLpgSQL_execstate *estate, PLpgSQL_function *func) +{ + //elog(NOTICE, "function begin: \"%s\"", func->fn_signature); + begin_profile_block(func->fn_oid); +} +static void plpgsql_cb_func_end(PLpgSQL_execstate *estate, PLpgSQL_function *func) +{ + //elog(NOTICE, "function end: \"%s\"", func->fn_signature); + end_profile_block(func->fn_oid); +} + +static void plpgsql_cb_stmt_beg(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt) +{ + //elog(NOTICE, "statement [%20s] begin - [ln: %d]", plpgsql_stmt_typename(stmt), stmt->lineno); + if (!cmdtype_is_loop((enum PLpgSQL_stmt_types)stmt->cmd_type)) { + begin_profile_stmt(stmt->lineno); + } else { + profile_stmt_once(stmt->lineno); + } +} + +static void plpgsql_cb_stmt_end(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt) +{ + //elog(NOTICE, "statement [%20s] end - [ln: %d]", plpgsql_stmt_typename(stmt), stmt->lineno); + if (!cmdtype_is_loop((enum PLpgSQL_stmt_types)stmt->cmd_type)) { + end_profile_stmt(stmt->lineno); + } +} + +Datum start_profiler(PG_FUNCTION_ARGS) +{ + uint32 runid = 0; + int result; + + result = start_profiler_internal(fcinfo, &runid); + + PG_RETURN_INT32(result); +} + +Datum start_profiler_1(PG_FUNCTION_ARGS) +{ + uint32 runid = 0; + int result; + + result = start_profiler_internal(fcinfo, &runid); + + PG_RETURN_VOID(); +} + +Datum start_profiler_ext(PG_FUNCTION_ARGS) +{ + uint32 runid = 0; + int result; + + result = start_profiler_internal(fcinfo, &runid); + + if (result == PROFILER_ERROR_OK) + return make_profiler_result(runid, result); + else + return make_profiler_result(0, result); +} + +Datum start_profiler_ext_1(PG_FUNCTION_ARGS) +{ + uint32 runid = 0; + int result; + + result = start_profiler_internal(fcinfo, &runid); + + if (result == PROFILER_ERROR_OK) + PG_RETURN_INT32(runid); + else + PG_RETURN_INT32(0); +} + +Datum stop_profiler(PG_FUNCTION_ARGS) +{ + ProfilerContext *profiler_cxt = get_session_context(); + int32 result = PROFILER_ERROR_OK; + + if (RecoveryInProgress()) + elog(ERROR, "Standby do not support gms_profiler, please do it in primary!"); + + if ((!u_sess->plsql_cxt.inited) || (!profiler_cxt)) + PG_RETURN_INT32(PROFILER_ERROR_PARAM); + + elog(DEBUG1, "stop_profiler state %d runid %d current_unit_number %u max_unit_number %u", + profiler_cxt->state, profiler_cxt->runid, profiler_cxt->current_unit_number, profiler_cxt->max_unit_number); + + /* If not call start_profiler before, do nothing! */ + if (profiler_cxt->state == PROFILER_INACTIVE) + PG_RETURN_INT32(PROFILER_ERROR_OK); + + profiler_cxt->state = PROFILER_INACTIVE; + profiler_cxt->run_total_time = GetCurrentTimestamp() - profiler_cxt->run_timestamp; + + PG_TRY(); + { + flush_profiler_to_table(); + } + PG_CATCH(); + { + result = PROFILER_ERROR_IO; + FlushErrorState(); + } + PG_END_TRY(); + + /* clean memory when stop profiler */ + pfree_ext(profiler_cxt->unit_stack); + profiler_cxt->unit_stack_top = 0; + + hash_destroy(profiler_cxt->unit_hash); + profiler_cxt->unit_hash = NULL; + + hash_destroy(profiler_cxt->data_hash); + profiler_cxt->data_hash = NULL; + + pfree_ext(profiler_cxt->run_comment); + pfree_ext(profiler_cxt->run_comment1); + + profiler_cxt->runinfo_flushed = false; + profiler_cxt->in_stmt = 0; + + PG_RETURN_INT32(result); +} + +Datum flush_data(PG_FUNCTION_ARGS) +{ + ProfilerContext *profiler_cxt = get_session_context(); + int32 result = PROFILER_ERROR_OK; + + if (RecoveryInProgress()) + elog(ERROR, "Standby do not support gms_profiler, please do it in primary!"); + + if ((!u_sess->plsql_cxt.inited) || (!profiler_cxt)) + PG_RETURN_INT32(PROFILER_ERROR_PARAM); + + elog(DEBUG1, "flush_data state %d runid %d current_unit_number %u max_unit_number %u", + profiler_cxt->state, profiler_cxt->runid, profiler_cxt->current_unit_number, profiler_cxt->max_unit_number); + + PG_TRY(); + { + flush_profiler_to_table(); + } + PG_CATCH(); + { + result = PROFILER_ERROR_IO; + FlushErrorState(); + } + PG_END_TRY(); + + PG_RETURN_INT32(result); +} + +Datum pause_profiler(PG_FUNCTION_ARGS) +{ + ProfilerContext *profiler_cxt = get_session_context(); + + if (RecoveryInProgress()) + elog(ERROR, "Standby do not support gms_profiler, please do it in primary!"); + + if ((!u_sess->plsql_cxt.inited) || (!profiler_cxt)) + PG_RETURN_INT32(PROFILER_ERROR_PARAM); + + elog(DEBUG1, "pause_profiler state %d runid %d current_unit_number %u max_unit_number %u", + profiler_cxt->state, profiler_cxt->runid, profiler_cxt->current_unit_number, profiler_cxt->max_unit_number); + + + /* PROFILER_INACTIVE state can not become PROFILER_PAUSED state */ + if (profiler_cxt->state == PROFILER_ACTIVE) + profiler_cxt->state = PROFILER_PAUSED; + + PG_RETURN_INT32(PROFILER_ERROR_OK); +} + +Datum resume_profiler(PG_FUNCTION_ARGS) +{ + ProfilerContext *profiler_cxt = get_session_context(); + + if (RecoveryInProgress()) + elog(ERROR, "Standby do not support gms_profiler, please do it in primary!"); + + if ((!u_sess->plsql_cxt.inited) || (!profiler_cxt)) + PG_RETURN_INT32(PROFILER_ERROR_PARAM); + + elog(DEBUG1, "resume_profiler state %d runid %d current_unit_number %u max_unit_number %u", + profiler_cxt->state, profiler_cxt->runid, profiler_cxt->current_unit_number, profiler_cxt->max_unit_number); + + /* PROFILER_INACTIVE state can not become PROFILER_ACTIVE state */ + if (profiler_cxt->state == PROFILER_PAUSED) + profiler_cxt->state = PROFILER_ACTIVE; + + PG_RETURN_INT32(PROFILER_ERROR_OK); +} + diff --git a/contrib/gms_profiler/gms_profiler.h b/contrib/gms_profiler/gms_profiler.h new file mode 100644 index 0000000000000000000000000000000000000000..03db2817ccee78dd17cf22fcc086c1adad2c3f90 --- /dev/null +++ b/contrib/gms_profiler/gms_profiler.h @@ -0,0 +1,98 @@ +/* + * + * gms_profiler.h + * Definition about gms_profiler package. + * + * + * IDENTIFICATION + * contrib/gms_profiler/gms_profiler.h + * + * --------------------------------------------------------------------------------------- + */ +#ifndef GMS_PROFILER_H +#define GMS_PROFILER_H + +#define PROFILER_UNIT_HASH_NUMBER 128 +#define PROFILER_DATA_HASH_NUMBER 1024 +#define PROFILER_UNIT_STACK_SIZE 1024 + +#define PROFILER_ERROR_OK 0 +#define PROFILER_ERROR_PARAM 1 +#define PROFILER_ERROR_IO 2 +#define PROFILER_ERROR_VERSION -1 + +typedef enum +{ + PROFILER_INACTIVE = 0, + PROFILER_ACTIVE = 1, + PROFILER_PAUSED = 2 +}ProfilerState; + +typedef struct ProfilerContext +{ + MemoryContext mem_cxt; + ProfilerState state; + // run info + uint32 runid; + Oid run_owner; + TimestampTz run_timestamp; + char *run_comment; + char *run_comment1; + int64 run_total_time; + bool runinfo_flushed; + // unit info + uint32 current_unit_number; + uint32 max_unit_number; + uint32 *unit_stack; + uint32 unit_stack_top; + uint32 in_stmt; + HTAB *unit_hash; + HTAB *data_hash; +}ProfilerContext; + +typedef struct ProfilerDataHashKey +{ + uint32 unit_number; + uint32 lineno; +}ProfilerDataHashKey; + +typedef struct ProfilerDataHashEntry +{ + uint32 unit_number; + uint32 lineno; + TimestampTz stmt_timestamp; + uint32 total_occur; + int64 total_time; + int64 min_time; + int64 max_time; + bool data_flushed; +}ProfilerDataHashEntry; + +typedef struct ProfilerUnitHashKey +{ + uint32 unit_oid; +}ProfilerUnitHashKey; + +typedef struct ProfilerUnitHashEntry +{ + uint32 unit_oid; + uint32 unit_number; + TimestampTz unit_timestamp; + int64 total_time; + bool unit_flushed; +}ProfilerUnitHashEntry; + +/* + * External declarations + */ +extern "C" Datum start_profiler(PG_FUNCTION_ARGS); +extern "C" Datum start_profiler_1(PG_FUNCTION_ARGS); +extern "C" Datum start_profiler_ext(PG_FUNCTION_ARGS); +extern "C" Datum start_profiler_ext_1(PG_FUNCTION_ARGS); +extern "C" Datum stop_profiler(PG_FUNCTION_ARGS); +extern "C" Datum flush_data(PG_FUNCTION_ARGS); +extern "C" Datum pause_profiler(PG_FUNCTION_ARGS); +extern "C" Datum resume_profiler(PG_FUNCTION_ARGS); +extern "C" void set_extension_index(uint32 index); +extern "C" void init_session_vars(void); +#endif diff --git a/contrib/gms_profiler/sql/gms_profiler.sql b/contrib/gms_profiler/sql/gms_profiler.sql new file mode 100644 index 0000000000000000000000000000000000000000..7c1738271485f987edc1892ebeb80982f5ee98cd --- /dev/null +++ b/contrib/gms_profiler/sql/gms_profiler.sql @@ -0,0 +1,151 @@ +SET client_min_messages = WARNING; +\set VERBOSITY terse +\set ECHO all + +drop procedure if exists do_something; +drop procedure if exists do_wrapper; +drop procedure if exists test_profiler_start; +drop procedure if exists test_profiler_flush; +drop procedure if exists test_profiler_version; +drop procedure if exists test_profiler_pause; +drop procedure if exists test_profiler_resume; +drop procedure if exists test_profiler_resume2; +drop procedure if exists test_profiler_version_check; +drop procedure if exists test_profiler_start_ext; + +create extension gms_profiler; + +create or replace procedure do_something (p_times in number) as + l_dummy number; +begin +for i in 1 .. p_times loop +select l_dummy +1 +into l_dummy; +end loop; +end; +/ + +create or replace procedure do_wrapper (p_times in number) as +begin +for i in 1 .. p_times loop + do_something(p_times); +end loop; +end; +/ + +create or replace procedure test_profiler_start () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler', 'simple'); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ + +create or replace procedure test_profiler_flush () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler_flush', 'flush'); + do_wrapper(p_times => 2); + l_result := gms_profiler.flush_data(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ + +create or replace procedure test_profiler_version () as +declare +major_v binary_integer; + minor_v binary_integer; +begin +select major, minor into major_v, minor_v from gms_profiler.get_version(); +end; +/ + +create or replace procedure test_profiler_pause () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler_pause', 'pause'); + do_wrapper(p_times => 2); + l_result := gms_profiler.pause_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ + +create or replace procedure test_profiler_resume () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.start_profiler('test_profiler_resume', 'resume1'); + do_wrapper(p_times => 2); + l_result := gms_profiler.pause_profiler(); + l_result := gms_profiler.resume_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ + +create or replace procedure test_profiler_resume2 () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.resume_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.start_profiler('test_profiler_resume2', 'resume2'); + l_result := gms_profiler.pause_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.pause_profiler(); + l_result := gms_profiler.resume_profiler(); + do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ + +create or replace procedure test_profiler_version_check () as +declare +l_result binary_integer; +begin + l_result := gms_profiler.internal_version_check(); +end; +/ + +create or replace procedure test_profiler_start_ext () as +declare +l_result binary_integer; + runid binary_integer; +begin +select run_number, run_result into runid, l_result from gms_profiler.start_profiler_ext('start_profiler_ext'); +do_wrapper(p_times => 2); + l_result := gms_profiler.stop_profiler(); +end; +/ + +call test_profiler_start(); +call test_profiler_flush(); +call test_profiler_version(); +call test_profiler_pause(); +call test_profiler_resume(); +call test_profiler_resume2(); +call test_profiler_version_check(); +call test_profiler_start_ext(); + +select runid, run_comment, run_comment1 from gms_profiler.plsql_profiler_runs order by runid; +select runid, unit_number, unit_type, unit_name from gms_profiler.plsql_profiler_units order by runid, unit_number; +select runid, unit_number, line#, total_occur from gms_profiler.plsql_profiler_data order by runid, unit_number, line#; + +drop procedure if exists do_something; +drop procedure if exists do_wrapper; +drop procedure if exists test_profiler_start; +drop procedure if exists test_profiler_flush; +drop procedure if exists test_profiler_version; +drop procedure if exists test_profiler_pause; +drop procedure if exists test_profiler_resume; +drop procedure if exists test_profiler_resume2; +drop procedure if exists test_profiler_version_check; +drop procedure if exists test_profiler_start_ext; + +reset client_min_messages; diff --git a/contrib/mppdb_decoding/mppdb_decoding.cpp b/contrib/mppdb_decoding/mppdb_decoding.cpp index 621a8cfc59f0298bc4c3328279b92ba8bce57656..bb685c909de80ae0c5cc438d582b664b5007e9ac 100644 --- a/contrib/mppdb_decoding/mppdb_decoding.cpp +++ b/contrib/mppdb_decoding/mppdb_decoding.cpp @@ -37,6 +37,7 @@ #include "replication/output_plugin.h" #include "replication/logical.h" +#include "tcop/ddldeparse.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -66,6 +67,11 @@ static void pg_decode_prepare_txn(LogicalDecodingContext* ctx, ReorderBufferTXN* static void pg_decode_change( LogicalDecodingContext* ctx, ReorderBufferTXN* txn, Relation rel, ReorderBufferChange* change); static bool pg_decode_filter(LogicalDecodingContext* ctx, RepOriginId origin_id); +static void pg_decode_ddl(LogicalDecodingContext *ctx, + ReorderBufferTXN *txn, XLogRecPtr message_lsn, + const char *prefix, Oid relid, + DeparsedCommandType cmdtype, + Size sz, const char *message); void _PG_init(void) { @@ -85,6 +91,7 @@ void _PG_output_plugin_init(OutputPluginCallbacks* cb) cb->prepare_cb = pg_decode_prepare_txn; cb->filter_by_origin_cb = pg_decode_filter; cb->shutdown_cb = pg_decode_shutdown; + cb->ddl_cb = pg_decode_ddl; } /* initialize this plugin */ @@ -424,3 +431,61 @@ static void pg_decode_change( MemoryContextReset(data->context); OutputPluginWrite(ctx, true); } + +static char *mppdb_deparse_command_type(DeparsedCommandType cmdtype) +{ + switch (cmdtype) { + case DCT_SimpleCmd: + return "Simple"; + case DCT_TableDropStart: + return "Drop table"; + case DCT_TableDropEnd: + return "Drop Table End"; + default: + Assert(false); + } + return NULL; +} + +static void pg_decode_ddl(LogicalDecodingContext *ctx, + ReorderBufferTXN *txn, XLogRecPtr message_lsn, + const char *prefix, Oid relid, + DeparsedCommandType cmdtype, + Size sz, const char *message) +{ + PluginTestDecodingData *data = NULL; + MemoryContext old; + + data = (PluginTestDecodingData *)ctx->output_plugin_private; + + /* Output BEGIN if we haven't yet */ + if (data->skip_empty_xacts && !data->xact_wrote_changes) { + pg_output_begin(ctx, data, txn, false); + } + data->xact_wrote_changes = true; + + /* Avoid leaking memory by using and resetting our own context */ + old = MemoryContextSwitchTo(data->context); + OutputPluginPrepareWrite(ctx, true); + + appendStringInfo(ctx->out, "prefix: %s, lsn: %llu, relid %u, cmdtype: %s, size: %lu, content: %s", + prefix, + message_lsn, + relid, + mppdb_deparse_command_type(cmdtype), + sz, + message); + + if (cmdtype != DCT_TableDropStart) { + char *tmp = pstrdup(message); + char *owner = NULL; + char *decodestring = deparse_ddl_json_to_string(tmp, &owner); + appendStringInfo(ctx->out, "\ndecode to: %s, [owner %s]", decodestring, owner ? owner : "none"); + pfree(tmp); + } + + MemoryContextSwitchTo(old); + MemoryContextReset(data->context); + + OutputPluginWrite(ctx, true); +} \ No newline at end of file diff --git a/contrib/pageinspect/rawpage.cpp b/contrib/pageinspect/rawpage.cpp index 1abcbf763059542f936aa2d751580bbaa67eeb9d..ee1be05907a6938d9468b4469351b0594444e186 100644 --- a/contrib/pageinspect/rawpage.cpp +++ b/contrib/pageinspect/rawpage.cpp @@ -144,11 +144,24 @@ static bytea* get_raw_page_internal(text* relname, ForkNumber forknum, BlockNumb if (blkno >= RelationGetNumberOfBlocks(rel)) elog(ERROR, "block number %u is out of range for relation \"%s\"", blkno, RelationGetRelationName(rel)); + if (RelationIsSegmentTable(rel) && ((forknum == BCM_FORKNUM) || (forknum == INIT_FORKNUM))) { + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot get raw page from segment table if forkname is \"%s\" and \"%s\"", + forkNames[BCM_FORKNUM], forkNames[INIT_FORKNUM]))); + } + /* Initialize buffer to copy to */ raw_page = (bytea*)palloc(BLCKSZ + VARHDRSZ); SET_VARSIZE(raw_page, BLCKSZ + VARHDRSZ); raw_page_data = VARDATA(raw_page); + if ((forknum == InvalidForkNumber) || (forknum > INIT_FORKNUM)) { + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot get raw page from stream for Invlid forkname; Valid forknames are \"main\", \"fsm\", \"vm\", \"bcm\", \"init\""))); + } + /* Take a verbatim copy of the page */ buf = ReadBufferExtended(rel, forknum, blkno, RBM_NORMAL, NULL); diff --git a/doc/src/sgml/catalogs.sgmlin b/doc/src/sgml/catalogs.sgmlin index be88ef21cea409abaa6edce4f664eaef163de66f..0dbe778a5d940e1c159ac8eb780eaec1a6b15682 100644 --- a/doc/src/sgml/catalogs.sgmlin +++ b/doc/src/sgml/catalogs.sgmlin @@ -4455,8 +4455,8 @@ protransform regproc pg_proc.oid - Calls to this function can be simplified by this other function - (see ) + Optional planner support function for this function + (see ) diff --git a/doc/src/sgml/xfunc.sgmlin b/doc/src/sgml/xfunc.sgmlin index 27582e742702bd5b300853ec3df204688cdb24d5..8cacfe4571d9885e01cf0fc0d6268de4e4b8971c 100644 --- a/doc/src/sgml/xfunc.sgmlin +++ b/doc/src/sgml/xfunc.sgmlin @@ -3362,45 +3362,6 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray - - Transform Functions - - - Some function calls can be simplified during planning based on - properties specific to the function. For example, - int4mul(n, 1) could be simplified to just n. - To define such function-specific optimizations, write a - transform function and place its OID in the - protransform field of the primary function's - pg_proc entry. The transform function must have the SQL - signature protransform(internal) RETURNS internal. The - argument, actually FuncExpr *, is a dummy node representing a - call to the primary function. If the transform function's study of the - expression tree proves that a simplified expression tree can substitute - for all possible concrete calls represented thereby, build and return - that simplified expression. Otherwise, return a NULL - pointer (not a SQL null). - - - - - We make no guarantee that PostgreSQL will never call the - - - We make no guarantee that Postgres-XC will never call the - - primary function in cases that the transform function could simplify. - Ensure rigorous equivalence between the simplified expression and an - actual call to the primary function. - - - - Currently, this facility is not exposed to users at the SQL level - because of security concerns, so it is only practical to use for - optimizing built-in functions. - - - Shared Memory and LWLocks @@ -3516,3 +3477,87 @@ if (!ptr) + + + Function Optimization Information + + + optimization information + for functions + + + + By default, a function is just a black box that the + database system knows very little about the behavior of. However, + that means that queries using the function may be executed much less + efficiently than they could be. It is possible to supply additional + knowledge that helps the planner optimize function calls. + + + + Some basic facts can be supplied by declarative annotations provided in + the command. Most important of + these is the function's volatility + category (IMMUTABLE, STABLE, + or VOLATILE); one should always be careful to + specify this correctly when defining a function. + The parallel safety property (PARALLEL + UNSAFE, PARALLEL RESTRICTED, or + PARALLEL SAFE) must also be specified if you hope + to use the function in parallelized queries. + It can also be useful to specify the function's estimated execution + cost, and/or the number of rows a set-returning function is estimated + to return. However, the declarative way of specifying those two + facts only allows specifying a constant value, which is often + inadequate. + + + + It is also possible to attach a planner support + function to a SQL-callable function (called + its target function), and thereby provide + knowledge about the target function that is too complex to be + represented declaratively. Planner support functions have to be + written in C (although their target functions might not be), so this is + an advanced feature that relatively few people will use. + + + + A planner support function must have the SQL signature + +supportfn(internal) returns internal + + + + + The details of the API for planner support functions can be found in + file src/include/nodes/supportnodes.h in the + PostgreSQL source code. Here we provide + just an overview of what planner support functions can do. + The set of possible requests to a support function is extensible, + so more things might be possible in future versions. + + + + Some function calls can be simplified during planning based on + properties specific to the function. For example, + int4mul(n, 1) could be simplified to + just n. This type of transformation can be + performed by a planner support function, by having it implement + the SupportRequestSimplify request type. + The support function will be called for each instance of its target + function found in a query parse tree. If it finds that the particular + call can be simplified into some other form, it can build and return a + parse tree representing that expression. This will automatically work + for operators based on the function, too — in the example just + given, n * 1 would also be simplified to + n. + (But note that this is just an example; this particular + optimization is not actually performed by + standard PostgreSQL.) + We make no guarantee that PostgreSQL will + never call the target function in cases that the support function could + simplify. Ensure rigorous equivalence between the simplified + expression and an actual execution of the target function. + + diff --git a/doc/src/sgml/xoper.sgmlin b/doc/src/sgml/xoper.sgmlin index d2090d737ad88cf854ae05e260a88bb948fd59a8..e38c305596becd69aa45850fee27d77a852bab22 100644 --- a/doc/src/sgml/xoper.sgmlin +++ b/doc/src/sgml/xoper.sgmlin @@ -85,6 +85,11 @@ SELECT (a + b) AS c FROM test_complex; Operator Optimization Information &common; + + optimization information + for operators + + A PostgreSQL operator definition can include @@ -114,6 +119,13 @@ SELECT (a + b) AS c FROM test_complex; the ones that release &version; understands. + + It is also possible to attach a planner support function to the function + that underlies an operator, providing another way of telling the system + about the behavior of the operator. + See for more information. + + <literal>COMMUTATOR</> &common; diff --git a/src/Makefile.global.in b/src/Makefile.global.in index daeda4438617d60faefcb8d2344477abd851d458..e258b7d43e337a0ce2a19e779e7d585a26cd73ce 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -174,6 +174,7 @@ enable_jemalloc_debug = @enable_jemalloc_debug@ enable_privategauss = @enable_privategauss@ enable_multiple_nodes = @enable_multiple_nodes@ enable_lite_mode = @enable_lite_mode@ +enable_relocation = @enable_relocation@ enable_finance_mode = @enable_finance_mode@ enable_mot = @enable_mot@ enable_bbox = @enable_bbox@ diff --git a/src/bin/gs_guc/cluster_guc.conf b/src/bin/gs_guc/cluster_guc.conf index f9d5329d96dfe8d6d39b46b28dd56975435d3fe9..7ade9b857a1040b2703e099d207121d5bdf758d9 100755 --- a/src/bin/gs_guc/cluster_guc.conf +++ b/src/bin/gs_guc/cluster_guc.conf @@ -83,6 +83,7 @@ autovacuum_vacuum_scale_factor|real|0,100|NULL|NULL| autovacuum_vacuum_threshold|int|0,2147483647|NULL|NULL| autovacuum_io_limits|int|-1,1073741823|NULL|NULL| autovacuum_mode|enum|analyze,vacuum,mix,none|NULL|NULL| +handle_toast_in_autovac|enum|on,off|NULL|NULL| autoanalyze_timeout|int|0,2147483|NULL|NULL| available_zone|string|0,0|NULL|NULL| backslash_quote|enum|safe_encoding,on,off,true,false,yes,no,1,0|NULL|NULL| @@ -607,6 +608,7 @@ zero_damaged_pages|bool|0,0|NULL|NULL| enable_bloom_filter|bool|0,0|NULL|NULL| cstore_insert_mode|enum|auto,main,delta|NULL|NULL| plan_cache_mode|enum|auto,force_generic_plan,force_custom_plan|NULL|NULL| +plan_cache_type_validation|bool|0,0|NULL|NULL| remote_read_mode|enum|off,non_authentication,authentication|NULL|NULL| enable_debug_vacuum|bool|0,0|NULL|NULL| enable_early_free|bool|0,0|NULL|NULL| @@ -753,7 +755,6 @@ ss_dss_vg_name|string|0,0|NULL|NULL| ss_dss_conn_path|string|0,0|NULL|NULL| ss_enable_dms|bool|0,0|NULL|NULL| ss_enable_catalog_centralized|bool|0,0|NULL|NULL| -ss_enable_reform|bool|0,0|NULL|NULL| ss_enable_ssl|bool|0,0|NULL|NULL| ss_enable_aio|bool|0,0|NULL|NULL| ss_enable_ondemand_realtime_build|bool|0,0|NULL|NULL| diff --git a/src/bin/gs_guc/pg_guc.cpp b/src/bin/gs_guc/pg_guc.cpp index b79565668a01e995162de6586a54ede0c4837aed..eee52a2d18b11815cf8d8dbef9c56bf3f4fe7af0 100644 --- a/src/bin/gs_guc/pg_guc.cpp +++ b/src/bin/gs_guc/pg_guc.cpp @@ -2400,7 +2400,7 @@ print_help(const char* infoStr) #ifdef ENABLE_MULTIPLE_NODES puts("gs_guc " DEF_GS_VERSION); #else - puts("gs_guc (openGauss) " PG_VERSION); + puts("gs_guc " DEF_GS_VERSION); #endif exit(0); } diff --git a/src/bin/initdb/initdb.cpp b/src/bin/initdb/initdb.cpp index 825ce896b121c0dbdb5d8a89a02df8f976a9cef9..fc9ce3f7fbbfded181849b4454e68a1fe13a5cbd 100644 --- a/src/bin/initdb/initdb.cpp +++ b/src/bin/initdb/initdb.cpp @@ -4065,7 +4065,7 @@ int main(int argc, char* argv[]) #ifdef ENABLE_MULTIPLE_NODES puts("gs_initdb " DEF_GS_VERSION); #else - puts("gs_initdb (openGauss) " PG_VERSION); + puts("gs_initdb " DEF_GS_VERSION); #endif exit(0); } diff --git a/src/bin/pg_controldata/pg_controldata.cpp b/src/bin/pg_controldata/pg_controldata.cpp index 0f9c833a48f52751bec2a5759abc1b579fe5814c..9b33c181d22d334f4792d7c9e28215bc08ddc7ef 100644 --- a/src/bin/pg_controldata/pg_controldata.cpp +++ b/src/bin/pg_controldata/pg_controldata.cpp @@ -325,7 +325,7 @@ int main(int argc, char* argv[]) #ifdef ENABLE_MULTIPLE_NODES puts("pg_controldata (PostgreSQL) " PG_VERSION); #else - puts("pg_controldata (openGauss) " PG_VERSION); + puts("pg_controldata " DEF_GS_VERSION); #endif exit_safely(0); } diff --git a/src/bin/pg_ctl/pg_ctl.cpp b/src/bin/pg_ctl/pg_ctl.cpp index 302999924e7d6ba3e09dc0098f5f87a0bdb30a9f..d04e4f41a539d1697452e7c9bdf079461bc003db 100755 --- a/src/bin/pg_ctl/pg_ctl.cpp +++ b/src/bin/pg_ctl/pg_ctl.cpp @@ -3871,7 +3871,6 @@ static void do_help(void) printf(_(" -C, connector CN/DN connect to specified CN/DN for build\n")); #ifndef ENABLE_LITE_MODE printf(_(" --enable-dss enable dss function\n")); - printf(_(" --instance-id=instance_id id number of instance when dss and dms are enabled\n")); printf(_(" --vgname vg name in dss when dss is enabled\n")); printf(_(" --socketpath=socketpath \n")); #endif @@ -5854,7 +5853,7 @@ static void Help(int argc, const char** argv) #ifdef ENABLE_MULTIPLE_NODES puts("gs_ctl " DEF_GS_VERSION); #else - puts("gs_ctl (openGauss) " PG_VERSION); + puts("gs_ctl " DEF_GS_VERSION); #endif exit(0); } diff --git a/src/bin/pg_dump/pg_restore.cpp b/src/bin/pg_dump/pg_restore.cpp index 968800f4e111089880c57a4b198ed476d3028095..5e3ed831855c4b9761a15a6bd9bc946b56fd78e1 100644 --- a/src/bin/pg_dump/pg_restore.cpp +++ b/src/bin/pg_dump/pg_restore.cpp @@ -193,7 +193,7 @@ int main(int argc, char** argv) #ifdef ENABLE_MULTIPLE_NODES puts("gs_restore " DEF_GS_VERSION); #else - puts("gs_restore (openGauss) " PG_VERSION); + puts("gs_restore " DEF_GS_VERSION); #endif exit_nicely(0); } diff --git a/src/bin/pg_resetxlog/pg_resetxlog.cpp b/src/bin/pg_resetxlog/pg_resetxlog.cpp index 840a3ef6ea3c3e7af15616ab72f9eef4fde75c50..23437958521dc9ff7f34bb7311737cfa6f30285c 100644 --- a/src/bin/pg_resetxlog/pg_resetxlog.cpp +++ b/src/bin/pg_resetxlog/pg_resetxlog.cpp @@ -150,7 +150,7 @@ int main(int argc, char* argv[]) #ifdef ENABLE_MULTIPLE_NODES puts("pg_resetxlog (PostgreSQL) " PG_VERSION); #else - puts("pg_resetxlog (openGauss) " PG_VERSION); + puts("pg_resetxlog " DEF_GS_VERSION); #endif exit(0); } diff --git a/src/bin/psql/common.cpp b/src/bin/psql/common.cpp index 4b93121d53a3e7e5ec38b698ba39f77d08882733..6936c85b1647379502db8a866438aaabbe8d89e7 100644 --- a/src/bin/psql/common.cpp +++ b/src/bin/psql/common.cpp @@ -271,6 +271,8 @@ sigjmp_buf sigint_interrupt_jmp; static PGcancel* volatile cancelConn = NULL; +volatile ReadlineStatus readline_status = WAIT_INPUT; + #ifdef WIN32 static CRITICAL_SECTION cancelConnLock; #endif @@ -290,7 +292,7 @@ static void handle_sigint(SIGNAL_ARGS) ResetQueryRetryController(); /* if we are waiting for input, longjmp out of it */ - if (sigint_interrupt_enabled) { + if (sigint_interrupt_enabled && readline_status == WAIT_INPUT) { sigint_interrupt_enabled = false; siglongjmp(sigint_interrupt_jmp, 1); } @@ -311,6 +313,10 @@ static void handle_sigint(SIGNAL_ARGS) } } + if (readline_status == COMPLETE_QUERY) { + readline_status = COMPLETE_CANCELLED; + } + errno = save_errno; /* just in case the write changed it */ } diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h index 193552a91ea7684d98bb39de2f9df96187447630..7a53dbd4ccff2805b8e96b003f2c8073de638a4a 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -74,6 +74,14 @@ extern volatile bool sigint_interrupt_enabled; extern sigjmp_buf sigint_interrupt_jmp; +enum ReadlineStatus { + WAIT_INPUT, + COMPLETE_QUERY, + COMPLETE_CANCELLED +}; + +extern volatile ReadlineStatus readline_status; + extern volatile bool cancel_pressed; /* Note: cancel_pressed is defined in print.c, see that file for reasons */ diff --git a/src/bin/psql/input.cpp b/src/bin/psql/input.cpp index 8a927afd75a6823274de83ab30e75598e0196b41..6f83ec9abb55f06dc88d22e99010ccae5973af26 100644 --- a/src/bin/psql/input.cpp +++ b/src/bin/psql/input.cpp @@ -55,6 +55,9 @@ char* gets_interactive(const char* prompt, PQExpBuffer query_buf) /* Enable SIGINT to longjmp to sigint_interrupt_jmp */ sigint_interrupt_enabled = true; + /* Make current input status to WAIT_INPUT */ + readline_status = WAIT_INPUT; + /* On some platforms, readline is declared as readline(char *) */ result = readline((char*)prompt); diff --git a/src/bin/psql/tab-complete.cpp b/src/bin/psql/tab-complete.cpp index df045ef3dc18e28d9bfa14feff073d5fcc48374d..c0440429eb189e6480285552257f15cfb4b914f7 100644 --- a/src/bin/psql/tab-complete.cpp +++ b/src/bin/psql/tab-complete.cpp @@ -3173,6 +3173,8 @@ static char *_CompleteFromQuery(int isSchemaQuery, const char *text, int state) PQclear(result); result = NULL; + readline_status = COMPLETE_QUERY; + /* Set up suitably-escaped copies of textual inputs */ eText = (char *)pg_malloc(stringLength * 2 + 1); PQescapeString(eText, text, stringLength); @@ -3300,7 +3302,7 @@ static char *_CompleteFromQuery(int isSchemaQuery, const char *text, int state) } /* Find something that matches */ - if (result && PQresultStatus(result) == PGRES_TUPLES_OK) { + if (readline_status == COMPLETE_QUERY && result && PQresultStatus(result) == PGRES_TUPLES_OK) { const char *item = NULL; while (listIndex < PQntuples(result) && (item = PQgetvalue(result, listIndex++, 0))) @@ -3311,6 +3313,8 @@ static char *_CompleteFromQuery(int isSchemaQuery, const char *text, int state) /* If nothing matches, free the db structure and return null */ PQclear(result); result = NULL; + readline_status = WAIT_INPUT; + return NULL; } diff --git a/src/common/backend/catalog/builtin_funcs.ini b/src/common/backend/catalog/builtin_funcs.ini index e98682c98e430f803bfb443e761da688fa3fc546..63ce3f58629cfb479836216682f5e80c4a4a41c8 100644 --- a/src/common/backend/catalog/builtin_funcs.ini +++ b/src/common/backend/catalog/builtin_funcs.ini @@ -6089,8 +6089,8 @@ AddBuiltinFunc(_0(1197), _1("interval_smaller"), _2(2), _3(true), _4(false), _5(interval_smaller), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1186, 1186), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("interval_smaller"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("smaller of two"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( - "interval_transform", 1, - AddBuiltinFunc(_0(3918), _1("interval_transform"), _2(1), _3(true), _4(false), _5(interval_transform), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("interval_transform"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + "interval_support", 1, + AddBuiltinFunc(_0(3918), _1("interval_support"), _2(1), _3(true), _4(false), _5(interval_support), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("interval_support"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "interval_um", 1, @@ -7498,8 +7498,8 @@ AddBuiltinFunc(_0(4171), _1("numeric_text"), _2(1), _3(true), _4(false), _5(numeric_text), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_text"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( - "numeric_transform", 1, - AddBuiltinFunc(_0(3157), _1("numeric_transform"), _2(1), _3(true), _4(false), _5(numeric_transform), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_transform"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + "numeric_support", 1, + AddBuiltinFunc(_0(3157), _1("numeric_support"), _2(1), _3(true), _4(false), _5(numeric_support), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_support"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "numeric_uminus", 1, @@ -11544,8 +11544,8 @@ AddFuncGroup( AddBuiltinFunc(_0(1378), _1("time_smaller"), _2(2), _3(true), _4(false), _5(time_smaller), _6(1083), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1083, 1083), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("time_smaller"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("smaller of two"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( - "time_transform", 1, - AddBuiltinFunc(_0(3944), _1("time_transform"), _2(1), _3(true), _4(false), _5(time_transform), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("time_transform"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + "time_support", 1, + AddBuiltinFunc(_0(3944), _1("time_support"), _2(1), _3(true), _4(false), _5(time_support), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("time_support"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "timedate_pl", 1, @@ -11721,8 +11721,8 @@ AddFuncGroup( AddBuiltinFunc(_0(4178), _1("timestamp_text"), _2(1), _3(true), _4(false), _5(timestamp_text), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1114), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("timestamp_text"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( - "timestamp_transform", 1, - AddBuiltinFunc(_0(3917), _1("timestamp_transform"), _2(1), _3(true), _4(false), _5(timestamp_transform), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("timestamp_transform"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + "timestamp_support", 1, + AddBuiltinFunc(_0(3917), _1("timestamp_support"), _2(1), _3(true), _4(false), _5(timestamp_support), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("timestamp_support"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "timestamp_varchar", 1, @@ -12652,8 +12652,8 @@ AddFuncGroup( AddBuiltinFunc(_0(2459), _1("varbit_send"), _2(1), _3(true), _4(false), _5(varbit_send), _6(17), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1562), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("varbit_send"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("I/O"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( - "varbit_transform", 1, - AddBuiltinFunc(_0(3158), _1("varbit_transform"), _2(1), _3(true), _4(false), _5(varbit_transform), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("varbit_transform"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + "varbit_support", 1, + AddBuiltinFunc(_0(3158), _1("varbit_support"), _2(1), _3(true), _4(false), _5(varbit_support), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("varbit_support"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "varbitcmp", 1, @@ -12725,8 +12725,8 @@ AddFuncGroup( AddBuiltinFunc(_0(4186), _1("varchar_timestamp"), _2(1), _3(true), _4(false), _5(varchar_timestamp), _6(1114), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1043), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("varchar_timestamp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( - "varchar_transform", 1, - AddBuiltinFunc(_0(3097), _1("varchar_transform"), _2(1), _3(true), _4(false), _5(varchar_transform), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("varchar_transform"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + "varchar_support", 1, + AddBuiltinFunc(_0(3097), _1("varchar_support"), _2(1), _3(true), _4(false), _5(varchar_support), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("varchar_support"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "varcharin", 1, diff --git a/src/common/backend/catalog/catalog.cpp b/src/common/backend/catalog/catalog.cpp index fdfff356537bf9cda52f3c6eb45a3ec1f744e938..4b031619f6c0f4572f4da6b08ef98697cc1afbca 100644 --- a/src/common/backend/catalog/catalog.cpp +++ b/src/common/backend/catalog/catalog.cpp @@ -95,6 +95,26 @@ const char* forkNames[] = { "init" /* INIT_FORKNUM */ }; +const char *packageSchemaList[] = {"dbe_application_info", + "dbe_file", + "dbe_lob", + "dbe_match", + "dbe_output", + "dbe_perf", + "dbe_pldebugger", + "dbe_random", + "dbe_raw", + "dbe_scheduler", + "dbe_session", + "dbe_sql", + "dbe_sql_util", + "dbe_task", + "dbe_utility", + "information_schema", + "pkg_service", + "pkg_util", + "sqladvisor"}; + /* * forkname_to_number - look up fork number by name */ @@ -132,6 +152,10 @@ ForkNumber forkname_to_number(char* forkName, BlockNumber* segno) subtoken = strtok_r(token, ".", &tmpsubtoken); Assert(subtoken != NULL); + if (atooid(subtoken)) { + return InvalidForkNumber; + } + if (strlen(subtoken) == parselen) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -1253,27 +1277,6 @@ bool IsPackageSchemaOid(Oid relnamespace) bool IsPackageSchemaName(const char* schemaName) { - const char* packageSchemaList[] = { - "dbe_application_info", - "dbe_file", - "dbe_lob", - "dbe_match", - "dbe_output", - "dbe_perf", - "dbe_pldebugger", - "dbe_random", - "dbe_raw", - "dbe_scheduler", - "dbe_session", - "dbe_sql", - "dbe_sql_util", - "dbe_task", - "dbe_utility", - "information_schema", - "pkg_service", - "pkg_util", - "sqladvisor" - }; int schemaNum = lengthof(packageSchemaList); for (int i = 0; i < schemaNum; ++i) { if (strcmp(schemaName, packageSchemaList[i]) == 0) { diff --git a/src/common/backend/catalog/dependency.cpp b/src/common/backend/catalog/dependency.cpp index f45fc131240e77cfb4db583395cb9aa553a927f6..9ae1da807836cab0db55621d2c8e5b889d88a5ac 100644 --- a/src/common/backend/catalog/dependency.cpp +++ b/src/common/backend/catalog/dependency.cpp @@ -2659,9 +2659,33 @@ char* getObjectDescription(const ObjectAddress* object) break; case OCLASS_PROC: - signature = format_procedure(object->objectId); - appendStringInfo(&buffer, _("function %s"), signature); - pfree_ext(signature); + if (enable_plpgsql_gsdependency()) { + MemoryContext save_context = CurrentMemoryContext; + PG_TRY(); + { + signature = format_procedure(object->objectId); + appendStringInfo(&buffer, _("function %s"), signature); + pfree_ext(signature); + } + PG_CATCH(); + { + ErrorData* edata = &t_thrd.log_cxt.errordata[t_thrd.log_cxt.errordata_stack_depth]; + if (edata->sqlerrcode == ERRCODE_CACHE_LOOKUP_FAILED) { + MemoryContextSwitchTo(save_context); + signature = get_func_name(object->objectId); + appendStringInfo(&buffer, _("function %s"), signature); + pfree_ext(signature); + FlushErrorState(); + } else { + PG_RE_THROW(); + } + } + PG_END_TRY(); + } else { + signature = format_procedure(object->objectId); + appendStringInfo(&buffer, _("function %s"), signature); + pfree_ext(signature); + } break; case OCLASS_PACKAGE: diff --git a/src/common/backend/catalog/gs_utf8_collation.cpp b/src/common/backend/catalog/gs_utf8_collation.cpp index b51e35d7ef864ca73c8468b644cac661781ca2dd..dc7858178a518a3d5ff8d14815ee96dc2e640390 100644 --- a/src/common/backend/catalog/gs_utf8_collation.cpp +++ b/src/common/backend/catalog/gs_utf8_collation.cpp @@ -787,6 +787,14 @@ static int get_current_char_sorted_value(const unsigned char* cur_str, const uns GS_UINT32* next_word, const GS_UNICASE_INFO *uni_plane) { int word_bytes = mb_wc_utf8mb4(cur_str, str_end, next_word); + if (word_bytes <= 0) { + if (word_bytes == GS_ERR_TOOSMALL) { + return 0; + } + word_bytes = 1; + *next_word = *cur_str; + return word_bytes; + } sort_by_unicode(uni_plane->sort_page, next_word); return word_bytes; } \ No newline at end of file diff --git a/src/common/backend/catalog/index.cpp b/src/common/backend/catalog/index.cpp index 73818ce8bcf201d6395bb83e5495d3f2a46fdb1a..204870a4e17fea87db6a7d6003b6bab257c0afc6 100644 --- a/src/common/backend/catalog/index.cpp +++ b/src/common/backend/catalog/index.cpp @@ -5431,24 +5431,24 @@ void reindex_index(Oid indexId, Oid indexPartId, bool skip_constraint_checks, */ TransferPredicateLocksToHeapRelation(iRel); + /* Fetch info needed for index_build */ + indexInfo = BuildIndexInfo(iRel); + + /* If requested, skip checking uniqueness/exclusion constraints */ + if (skip_constraint_checks) { + if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL) + skipped_constraint = true; + indexInfo->ii_Unique = false; + indexInfo->ii_ExclusionOps = NULL; + indexInfo->ii_ExclusionProcs = NULL; + indexInfo->ii_ExclusionStrats = NULL; + } + PG_TRY(); { /* Suppress use of the target index while rebuilding it */ SetReindexProcessing(heapId, indexId); - /* Fetch info needed for index_build */ - indexInfo = BuildIndexInfo(iRel); - - /* If requested, skip checking uniqueness/exclusion constraints */ - if (skip_constraint_checks) { - if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL) - skipped_constraint = true; - indexInfo->ii_Unique = false; - indexInfo->ii_ExclusionOps = NULL; - indexInfo->ii_ExclusionProcs = NULL; - indexInfo->ii_ExclusionStrats = NULL; - } - /* workload client manager */ if (IS_PGXC_COORDINATOR && ENABLE_WORKLOAD_CONTROL) { /* if operatorMem is already set, the mem check is already done */ @@ -5723,7 +5723,6 @@ bool ReindexRelation(Oid relid, int flags, int reindexType, void *baseDesc, Adap PG_TRY(); { - List* doneIndexes = NIL; ListCell* indexId = NULL; if (((uint32)flags) & REINDEX_REL_SUPPRESS_INDEX_USE) { @@ -5738,15 +5737,10 @@ bool ReindexRelation(Oid relid, int flags, int reindexType, void *baseDesc, Adap } /* Reindex all the indexes. */ - doneIndexes = NIL; foreach (indexId, indexIds) { Oid indexOid = lfirst_oid(indexId); Relation indexRel = index_open(indexOid, AccessShareLock); - if (is_pg_class) { - RelationSetIndexList(rel, doneIndexes, InvalidOid); - } - if ((((uint32)reindexType) & REINDEX_ALL_INDEX) || ((((uint32)reindexType) & REINDEX_BTREE_INDEX) && (indexRel->rd_rel->relam == BTREE_AM_OID)) || ((((uint32)reindexType) & REINDEX_HASH_INDEX) && (indexRel->rd_rel->relam == HASH_AM_OID)) || @@ -5770,10 +5764,6 @@ bool ReindexRelation(Oid relid, int flags, int reindexType, void *baseDesc, Adap /* Index should no longer be in the pending list */ Assert(!ReindexIsProcessingIndex(indexOid)); - - if (is_pg_class) { - doneIndexes = lappend_oid(doneIndexes, indexOid); - } } } PG_CATCH(); @@ -5785,10 +5775,6 @@ bool ReindexRelation(Oid relid, int flags, int reindexType, void *baseDesc, Adap PG_END_TRY(); ResetReindexPending(); - if (is_pg_class) { - RelationSetIndexList(rel, indexIds, ClassOidIndexId); - } - // reset all local indexes on partition usable if needed if (RELATION_IS_PARTITIONED(rel)) { /* for partitioned table */ Oid partOid; diff --git a/src/common/backend/catalog/indexing.cpp b/src/common/backend/catalog/indexing.cpp index 222a95550aeefd04091bedc5de3fd45a4a11c454..4b249b468384a1eff9870d9a014cae68431ac587 100644 --- a/src/common/backend/catalog/indexing.cpp +++ b/src/common/backend/catalog/indexing.cpp @@ -69,7 +69,6 @@ void CatalogCloseIndexes(CatalogIndexState indstate) */ void CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple) { - int i; int numIndexes; RelationPtr relationDescs; Relation heapRelation; @@ -77,11 +76,10 @@ void CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple) IndexInfo** indexInfoArray; Datum values[INDEX_MAX_KEYS]; bool isnull[INDEX_MAX_KEYS]; - - /* HOT update does not require index inserts */ +#ifndef USE_ASSERT_CHECKING if (HeapTupleIsHeapOnly(heapTuple)) return; - +#endif /* * Get information from the state structure. Fall out if nothing to do. */ @@ -99,10 +97,12 @@ void CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple) /* * for each index, form and insert the index tuple */ - for (i = 0; i < numIndexes; i++) { + for (int i = 0; i < numIndexes; i++) { IndexInfo* indexInfo = NULL; + Relation index; indexInfo = indexInfoArray[i]; + index = relationDescs[i]; /* If the index is marked as read-only, ignore it */ if (!indexInfo->ii_ReadyForInserts) @@ -115,9 +115,16 @@ void CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple) Assert(indexInfo->ii_Expressions == NIL); Assert(indexInfo->ii_Predicate == NIL); Assert(indexInfo->ii_ExclusionOps == NULL); - Assert(relationDescs[i]->rd_index->indimmediate); + Assert(index->rd_index->indimmediate); Assert(indexInfo->ii_NumIndexKeyAttrs != 0); +#ifdef USE_ASSERT_CHECKING + if (HeapTupleIsHeapOnly(heapTuple)) { + Assert(!ReindexIsProcessingIndex(RelationGetRelid(index))); + continue; + } +#endif /* USE_ASSERT_CHECKING */ + /* * FormIndexDatum fills in its values and isnull parameters with the * appropriate values for the column(s) of the index. diff --git a/src/common/backend/libpq/pqcomm.cpp b/src/common/backend/libpq/pqcomm.cpp index dff215a44a7d94d8cb9efbea8d237d517946f580..896ba48b01ea9068e06c782ec4823ff2cdb5a72e 100644 --- a/src/common/backend/libpq/pqcomm.cpp +++ b/src/common/backend/libpq/pqcomm.cpp @@ -133,13 +133,12 @@ extern ProtocolExtensionConfig default_protocol_config; #define NAPTIME_PER_SEND 10 /* max sleep before sending next batch of data (10ms) */ void pq_close(int code, Datum arg); -int internal_putbytes(const char* s, size_t len); +inline int internal_putbytes(const char* s, size_t len); /* Internal functions */ -static int internal_flush(void); -static void pq_set_nonblocking(bool nonblocking); -static void pq_disk_generate_checking_header( - const char* src_data, StringInfo dest_data, uint32 data_len, uint32 seq_num); +int internal_flush(void); +void pq_set_nonblocking(bool nonblocking); +void pq_disk_generate_checking_header(const char *src_data, StringInfo dest_data, uint32 data_len, uint32 seq_num); static size_t pq_disk_read_data_block( LZ4File* file_handle, char* src_data, char* dest_data, uint32 data_len, uint32 seq_num); @@ -229,7 +228,7 @@ static inline void pq_disk_create_tempfile(void) * @in - size, size of data to be written. * @return - written size, EOF if error happens. */ -static size_t pq_disk_write_tempfile(const void* data, size_t size) +size_t pq_disk_write_tempfile(const void* data, size_t size) { size_t nwritten = 0; @@ -2554,8 +2553,7 @@ void pq_revert_recvbuffer(const char* data, int len) * @in - src data and length and sequence number * @return - int seqnum + int datalength + pg_crc32 crc as char *. */ -static void pq_disk_generate_checking_header( - const char* src_data, StringInfo dest_data, uint32 data_len, uint32 seq_num) +void pq_disk_generate_checking_header(const char *src_data, StringInfo dest_data, uint32 data_len, uint32 seq_num) { Assert(src_data != NULL); diff --git a/src/common/backend/libpq/pqformat.cpp b/src/common/backend/libpq/pqformat.cpp index 9daf0d9fe4f78bfb992851408400d130ad13954a..4fbd22e518d0ffafe450e20574fd81b0e5fa8f2a 100644 --- a/src/common/backend/libpq/pqformat.cpp +++ b/src/common/backend/libpq/pqformat.cpp @@ -161,7 +161,7 @@ void pq_sendcountedtext_printtup(StringInfo buf, const char* str, int slen, int } if (unlikely(p != str)) { /* actual conversion has been done? */ slen = strlen(p); - enlargeStringInfo(buf, slen + sizeof(uint32)); + enlargeBuffer(slen + sizeof(uint32), buf->len, &buf->maxlen, &buf->data); pq_writeint32(buf, (uint32)slen); errno_t rc = memcpy_sp(buf->data + buf->len, (size_t)(buf->maxlen - buf->len), p, (size_t)slen); securec_check(rc, "\0", "\0"); @@ -170,7 +170,7 @@ void pq_sendcountedtext_printtup(StringInfo buf, const char* str, int slen, int pfree(p); p = NULL; } else { - enlargeStringInfo(buf, slen + sizeof(uint32)); + enlargeBuffer(slen + sizeof(uint32), buf->len, &buf->maxlen, &buf->data); pq_writeint32(buf, (uint32)slen); errno_t rc = memcpy_sp(buf->data + buf->len, (size_t)(buf->maxlen - buf->len), str, (size_t)slen); securec_check(rc, "\0", "\0"); diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index 9b6ea6918856be3474bebe0d5ae9ec42c26f6b45..2430473b396e6673eef1e47ac14374ead75f8080 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -2616,6 +2616,19 @@ static Param* _copyParam(const Param* from) return newnode; } +/* + * _copyPriorExpr + */ +static PriorExpr* _copyPriorExpr(const PriorExpr* from) +{ + PriorExpr* newnode =(PriorExpr*)makeNode(PriorExpr); + + COPY_SCALAR_FIELD(xpr.selec); + COPY_NODE_FIELD(node); + + return newnode; +} + /* * _copyRownum */ @@ -5563,6 +5576,17 @@ static AlterFunctionStmt* _copyAlterFunctionStmt(const AlterFunctionStmt* from) return newnode; } +static CompileStmt* _copyCompileStmt(const CompileStmt* from) +{ + CompileStmt* newnode = makeNode(CompileStmt); + + COPY_NODE_FIELD(objName); + COPY_NODE_FIELD(funcArgs); + COPY_SCALAR_FIELD(compileItem); + + return newnode; +} + static DoStmt* _copyDoStmt(const DoStmt* from) { DoStmt* newnode = makeNode(DoStmt); @@ -8059,6 +8083,9 @@ void* copyObject(const void* from) case T_Const: retval = _copyConst((Const*)from); break; + case T_PriorExpr: + retval = _copyPriorExpr((PriorExpr*)from); + break; case T_Param: retval = _copyParam((Param*)from); break; @@ -8399,6 +8426,16 @@ void* copyObject(const void* from) case T_AlterFunctionStmt: retval = _copyAlterFunctionStmt((AlterFunctionStmt*)from); break; + case T_CompileStmt: + u_sess->plsql_cxt.during_compile = true; + if (!enable_plpgsql_gsdependency_guc()) { + u_sess->plsql_cxt.during_compile = false; + retval = 0; + ereport(ERROR, (errmsg("This operation is not supported."))); + break; + } + retval = _copyCompileStmt((CompileStmt*)from); + break; case T_DoStmt: retval = _copyDoStmt((const DoStmt*)from); break; diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 7bba92dafd81bea298579698d81393b44ec3ddf6..63a07def812ae4944e2960b9ccbd53f2ec0bc604 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -199,6 +199,13 @@ static bool _equalConst(const Const* a, const Const* b) return datumIsEqual(a->constvalue, b->constvalue, a->constbyval, a->constlen); } +static bool _equalPriorExpr(const PriorExpr* a, const PriorExpr* b) +{ + COMPARE_NODE_FIELD(node); + + return true; +} + static bool _equalParam(const Param* a, const Param* b) { COMPARE_SCALAR_FIELD(paramkind); @@ -1566,6 +1573,15 @@ static bool _equalAlterFunctionStmt(const AlterFunctionStmt* a, const AlterFunct return true; } +static bool _equalCompileStmt(const CompileStmt* a, const CompileStmt* b) +{ + COMPARE_NODE_FIELD(objName); + COMPARE_NODE_FIELD(funcArgs); + COMPARE_SCALAR_FIELD(compileItem); + + return true; +} + static bool _equalDoStmt(const DoStmt* a, const DoStmt* b) { COMPARE_NODE_FIELD(args); @@ -3629,6 +3645,9 @@ bool equal(const void* a, const void* b) case T_Const: retval = _equalConst((Const*)a, (Const*)b); break; + case T_PriorExpr: + retval = _equalPriorExpr((PriorExpr*)a, (PriorExpr*)b); + break; case T_Param: retval = _equalParam((Param*)a, (Param*)b); break; @@ -3950,6 +3969,16 @@ bool equal(const void* a, const void* b) case T_AlterFunctionStmt: retval = _equalAlterFunctionStmt((AlterFunctionStmt*)a, (AlterFunctionStmt*)b); break; + case T_CompileStmt: + u_sess->plsql_cxt.during_compile = true; + if (!enable_plpgsql_gsdependency_guc()) { + u_sess->plsql_cxt.during_compile = false; + retval = 0; + ereport(ERROR, (errmsg("This operation is not supported."))); + break; + } + retval = _equalCompileStmt((CompileStmt*)a, (CompileStmt*)b); + break; case T_DoStmt: retval = _equalDoStmt((DoStmt*)a, (DoStmt*)b); break; diff --git a/src/common/backend/nodes/nodeFuncs.cpp b/src/common/backend/nodes/nodeFuncs.cpp index e8be183c81707d140b9737f34df3216779c2d142..2f805f6789c13fb7b977d65a48eef3ce4443dfcb 100644 --- a/src/common/backend/nodes/nodeFuncs.cpp +++ b/src/common/backend/nodes/nodeFuncs.cpp @@ -248,6 +248,9 @@ Oid exprType(const Node* expr) type = INT4OID; break; #endif + case T_PriorExpr: + type = exprType(((const PriorExpr*)expr)->node); + break; default: ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("unrecognized node type: %d", (int)nodeTag(expr)))); @@ -489,6 +492,8 @@ int32 exprTypmod(const Node* expr) return exprTypmod((Node*)((const PrefixKey*)expr)->arg); case T_SetVariableExpr: return ((const Const*)(((SetVariableExpr*)expr)->value))->consttypmod; + case T_PriorExpr: + return exprTypmod((Node*)((const PriorExpr*)expr)->node); default: break; } @@ -829,7 +834,14 @@ Oid exprCollation(const Node* expr) coll = exprCollation((Node*)((const NamedArgExpr*)expr)->arg); break; case T_UserVar: - coll = ((const Const*)(((UserVar*)expr)->value))->constcollid; + if (IsA(((UserVar*)expr)->value, FuncExpr)) { + coll = ((const FuncExpr*)(((UserVar*)expr)->value))->funccollid; + } else { + coll = ((const Const*)(((UserVar*)expr)->value))->constcollid; + } + if (!OidIsValid(coll)) { + coll = get_typcollation(exprType((const Node*)(((UserVar*)expr)->value))); + } break; case T_OpExpr: coll = ((const OpExpr*)expr)->opcollid; @@ -977,6 +989,9 @@ Oid exprCollation(const Node* expr) coll = InvalidOid; break; #endif + case T_PriorExpr: + coll = exprCollation((Node*)((const PriorExpr*)expr)->node); + break; default: ereport( ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("unrecognized node type: %d", (int)nodeTag(expr)))); @@ -1193,6 +1208,8 @@ void exprSetCollation(Node* expr, Oid collation) break; case T_UserSetElem: break; + case T_PriorExpr: + return exprSetCollation((Node*)((const PriorExpr*)expr)->node, collation); default: ereport( ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("unrecognized node type: %d", (int)nodeTag(expr)))); @@ -2040,6 +2057,8 @@ bool expression_tree_walker(Node* node, bool (*walker)(), void* context) p2walker(((UserSetElem*)node)->val, context); return true; } + case T_PriorExpr: + return p2walker(((PriorExpr*)node)->node, context); default: ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("expression_tree_walker:unrecognized node type: %d", (int)nodeTag(node)))); @@ -2813,6 +2832,13 @@ Node* expression_tree_mutator(Node* node, Node* (*mutator)(Node*, void*), void* return (Node *)newnode; } break; #endif + case T_PriorExpr: { + PriorExpr* p_expr = (PriorExpr*)node; + PriorExpr* newnode = NULL; + FLATCOPY(newnode, p_expr, PriorExpr, isCopy); + MUTATE(newnode->node, p_expr->node, Node*); + return (Node*)newnode; + } break; default: ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("unrecognized node type: %d", (int)nodeTag(node)))); diff --git a/src/common/backend/nodes/outfuncs.cpp b/src/common/backend/nodes/outfuncs.cpp index 5ca5d62a5fa0587f2f1ae25de15ce265a371b91c..e134fd2e94bea77d39632c3cf48f8cba1d64de44 100755 --- a/src/common/backend/nodes/outfuncs.cpp +++ b/src/common/backend/nodes/outfuncs.cpp @@ -2449,6 +2449,12 @@ static void _outConst(StringInfo str, Const* node) WRITE_CURSORDATA_FIELD(cursor_data); } +static void _outPriorExpr(StringInfo str, PriorExpr* node) +{ + WRITE_NODE_TYPE("PRIOREXPR"); + WRITE_NODE_FIELD(node); +} + static void _outParam(StringInfo str, Param* node) { WRITE_NODE_TYPE("PARAM"); @@ -6489,6 +6495,9 @@ static void _outNode(StringInfo str, const void* obj) case T_Const: _outConst(str, (Const*)obj); break; + case T_PriorExpr: + _outPriorExpr(str, (PriorExpr*)obj); + break; case T_Param: _outParam(str, (Param*)obj); break; diff --git a/src/common/backend/nodes/readfuncs.cpp b/src/common/backend/nodes/readfuncs.cpp index 9675cb0f6c1a2647086010f313bc1d68cb6b3e87..e621064c097b0901d791d12d9de2f35cb5355d47 100755 --- a/src/common/backend/nodes/readfuncs.cpp +++ b/src/common/backend/nodes/readfuncs.cpp @@ -2047,6 +2047,17 @@ static Var* _readVar(void) READ_DONE(); } +/* + * _readPriorExpr + */ +static PriorExpr* _readPriorExpr(void) +{ + READ_LOCALS(PriorExpr); + + READ_NODE_FIELD(node); + READ_DONE(); +} + /* * _readRownum */ @@ -6859,6 +6870,8 @@ Node* parseNodeString(void) return_value = _readNoGPCHint(); } else if (MATCH("ROWNUM", 6)) { return_value = _readRownum(); + } else if (MATCH("PRIOREXPR", 9)) { + return_value = _readPriorExpr(); } else if (MATCH("COPY", 4)) { return_value = _readCopyStmt(); } else if (MATCH("ALTERTABLE", 10)) { diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 32bc15f2c443d3c3b28f1c4e6c8f9080643ceb03..6111ea7436080bed29db4c02c87c6a738a8c6fab 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -2894,12 +2894,25 @@ static void transformVariableSetValueStmt(ParseState* pstate, VariableSetStmt* s static Query* transformSelectStmt(ParseState* pstate, SelectStmt* stmt, bool isFirstNode, bool isCreateView) { Query* qry = makeNode(Query); + ParseState *origin_pstate = NULL; + SelectStmt *origin_stmt = NULL; Node* qual = NULL; ListCell* l = NULL; qry->commandType = CMD_SELECT; if (stmt->startWithClause != NULL) { + errno_t rc; + origin_stmt = (SelectStmt *)copyObject(stmt); + origin_pstate = make_parsestate(NULL); + rc = memcpy_s(origin_pstate, sizeof(ParseState), pstate, sizeof(ParseState)); + origin_pstate->p_rtable = list_copy(pstate->p_rtable); + origin_pstate->p_ctenamespace = list_copy(pstate->p_ctenamespace); + origin_pstate->p_relnamespace = list_copy(pstate->p_relnamespace); + origin_pstate->p_varnamespace = list_copy(pstate->p_varnamespace); + origin_pstate->p_joinlist = list_copy(pstate->p_joinlist); + origin_pstate->p_joinexprs = list_copy(pstate->p_joinexprs); + securec_check(rc, "\0", "\0"); pstate->p_addStartInfo = true; pstate->p_sw_selectstmt = stmt; pstate->origin_with = (WithClause *)copyObject(stmt->withClause); @@ -2934,7 +2947,7 @@ static Query* transformSelectStmt(ParseState* pstate, SelectStmt* stmt, bool isF /* transform START WITH...CONNECT BY clause */ if (shouldTransformStartWithStmt(pstate, stmt, qry)) { - transformStartWith(pstate, stmt, qry); + transformStartWith(pstate, origin_pstate, stmt, origin_stmt, qry, isFirstNode, isCreateView); } /* transform targetlist */ diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 1c92e253228d043de4265598e8cea142e80bc38d..5833f028fc9a586c2caef1178a2a7cd93dd8a104 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -4651,9 +4651,22 @@ alter_table_cmd: $$ = (Node *)n; } | + INVISIBLE + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_InvisibleIndexDirect; + $$ = (Node *)n; + } + | + VISIBLE + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_VisibleIndexDirect; + $$ = (Node *)n; + } + | ALTER INDEX index_name INVISIBLE { - BCompatibilityOptionSupportCheck($4); AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_InvisibleIndex; n->name = $3; @@ -4662,7 +4675,6 @@ alter_table_cmd: | ALTER INDEX index_name VISIBLE { - BCompatibilityOptionSupportCheck($4); AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_VisibleIndex; n->name = $3; @@ -5440,13 +5452,11 @@ table_index_option: } | INVISIBLE { - BCompatibilityOptionSupportCheck($1); Value *n = makeString("invisible"); $$ = (Node*)n; } | VISIBLE { - BCompatibilityOptionSupportCheck($1); Value *n = makeString("visible"); $$ = (Node*)n; } @@ -16066,7 +16076,9 @@ CreateProcedureStmt: ; CreatePackageStmt: - CREATE opt_or_replace PACKAGE pkg_name invoker_rights as_is {pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true;set_function_style_a();} + CREATE opt_or_replace PACKAGE pkg_name invoker_rights as_is {pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->plsql_cxt.isCreatePkg = true; + set_function_style_a();} { set_create_plsql_type_start(); u_sess->plsql_cxt.need_create_depend = true; @@ -16345,6 +16357,7 @@ pkg_body_subprogram: { if (tok == END_P) { pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = false; + u_sess->plsql_cxt.isCreatePkg = false; tok = YYLEX; proc_e = yylloc; @@ -16487,7 +16500,9 @@ pkg_body_subprogram: { } ; CreatePackageBodyStmt: - CREATE opt_or_replace PACKAGE BODY_P pkg_name as_is {pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true;set_function_style_a();} pkg_body_subprogram + CREATE opt_or_replace PACKAGE BODY_P pkg_name as_is {pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->plsql_cxt.isCreatePkg = true; + set_function_style_a();} pkg_body_subprogram { set_create_plsql_type_start(); u_sess->plsql_cxt.need_create_depend = true; @@ -16561,6 +16576,7 @@ CreatePackageBodyStmt: } else { n->pkginit = NULL; } + u_sess->plsql_cxt.isCreatePkg = false; $$ = (Node *)n; } ; @@ -24578,6 +24594,42 @@ table_ref: relation_expr %prec UMINUS $1->indexhints = $7; $$ = (Node *)$1; } + | relation_expr PARTITION '(' name ')' tablesample_clause + { + RangeTableSample *n = (RangeTableSample *) $6; + $1->partitionname = $4; + $1->ispartition = true; + /* relation_expr goes inside the RangeTableSample node */ + n->relation = (Node *) $1; + $$ = (Node *) n; + } + | relation_expr SUBPARTITION '(' name ')' tablesample_clause + { + RangeTableSample *n = (RangeTableSample *) $6; + $1->subpartitionname = $4; + $1->issubpartition = true; + /* relation_expr goes inside the RangeTableSample node */ + n->relation = (Node *) $1; + $$ = (Node *) n; + } + | relation_expr PARTITION_FOR '(' expr_list ')' tablesample_clause + { + RangeTableSample *n = (RangeTableSample *) $6; + $1->partitionKeyValuesList = $4; + $1->ispartition = true; + /* relation_expr goes inside the RangeTableSample node */ + n->relation = (Node *) $1; + $$ = (Node *) n; + } + | relation_expr SUBPARTITION_FOR '(' expr_list ')' tablesample_clause + { + RangeTableSample *n = (RangeTableSample *) $6; + $1->partitionKeyValuesList = $4; + $1->issubpartition = true; + /* relation_expr goes inside the RangeTableSample node */ + n->relation = (Node *) $1; + $$ = (Node *) n; + } | func_table %prec UMINUS { RangeFunction *n = makeNode(RangeFunction); diff --git a/src/common/backend/parser/parse_clause.cpp b/src/common/backend/parser/parse_clause.cpp index 81689f832cf96d6aa0b98635f2eb26d9f350f7de..42710183c33a580f6ca950b168123ce88e7b27a7 100644 --- a/src/common/backend/parser/parse_clause.cpp +++ b/src/common/backend/parser/parse_clause.cpp @@ -793,7 +793,7 @@ static TableSampleClause* transformRangeTableSample(ParseState* pstate, RangeTab Node* arg = (Node*)lfirst(larg); arg = transformExpr(pstate, arg, EXPR_KIND_FROM_FUNCTION); - arg = coerce_to_specific_type(pstate, arg, FLOAT4OID, "TABLESAMPLE"); + arg = coerce_to_specific_type(pstate, arg, FLOAT8OID, "TABLESAMPLE"); assign_expr_collations(pstate, arg); fargs = lappend(fargs, arg); } @@ -982,11 +982,11 @@ Node* transformFromClauseItem(ParseState* pstate, Node* n, RangeTblEntry** top_r rtr = (RangeTblRef*)rel; rte = rt_fetch(rtr->rtindex, pstate->p_rtable); - /* We only support this on plain relations */ - if (rte->relkind != RELKIND_RELATION) { + /* We only support this on plain relations and views, materialized views and join views with kp-tables */ + if (rte->relkind != RELKIND_RELATION && rte->relkind != RELKIND_MATVIEW && rte->relkind != RELKIND_VIEW) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("TABLESAMPLE clause can only be applied to tables."), + errmsg("TABLESAMPLE clause can only be applied to tables, materialized views and key-preserved join views."), parser_errposition(pstate, exprLocation(rts->relation)))); } diff --git a/src/common/backend/parser/parse_coerce.cpp b/src/common/backend/parser/parse_coerce.cpp index b2803a9cf85ed3ebe91fc943c5704470f61038e2..54660cf7a884a8acc5d016c4b22bca76a448a8c0 100644 --- a/src/common/backend/parser/parse_coerce.cpp +++ b/src/common/backend/parser/parse_coerce.cpp @@ -524,7 +524,7 @@ Node* coerce_type(ParseState* pstate, Node* node, Oid inputTypeId, Oid targetTyp newcon->consttype = baseTypeId; newcon->consttypmod = inputTypeMod; - if (OidIsValid(GetCollationConnection()) && + if (!DB_IS_CMPT(B_FORMAT) && OidIsValid(GetCollationConnection()) && IsSupportCharsetType(baseTypeId)) { newcon->constcollid = GetCollationConnection(); } else { diff --git a/src/common/backend/parser/parse_collate.cpp b/src/common/backend/parser/parse_collate.cpp index 306a30d338f2308e40cdc3de4baa6b465a4ae7d3..07a89eeac881c85015e7fff8a22ab2a4410d5803 100644 --- a/src/common/backend/parser/parse_collate.cpp +++ b/src/common/backend/parser/parse_collate.cpp @@ -136,7 +136,7 @@ FORCE_INLINE static void get_valid_collation(Oid& collation, CollateStrength& st strength = context.strength; location = context.location; derivation = context.derivation; - } else if (ENABLE_MULTI_CHARSET && + } else if (!DB_IS_CMPT(B_FORMAT) && ENABLE_MULTI_CHARSET && context.strength == COLLATE_NONE && (OidIsValid(GetCollationConnection()) || context.derivation == DERIVATION_SYSCONST)) { /* collation of version() is UTF8_GENERAL_CI */ diff --git a/src/common/backend/parser/parse_expr.cpp b/src/common/backend/parser/parse_expr.cpp index 932652526af19a2c0c584bf73730ee73b6384942..f36cc1558bc491b3d02d3c3f6e54a221aa3d2892 100644 --- a/src/common/backend/parser/parse_expr.cpp +++ b/src/common/backend/parser/parse_expr.cpp @@ -98,6 +98,7 @@ static Node* transformConnectByRootFuncCall(ParseState* pstate, Node* funcNameVa static bool CheckSwAbortedRTE(ParseState *pstate, char *relname); static char *ColumnRefFindRelname(ParseState *pstate, const char *colname); static Node *transformStartWithColumnRef(ParseState *pstate, ColumnRef *cref, char **colname); +static Node *transformStartWithWhereClauseColumnRef(ParseState *pstate, ColumnRef *cref, char *colname); static Node* tryTransformFunc(ParseState* pstate, List* fields, int location); static void SubCheckOutParam(List* exprtargs, Oid funcid); static Node* transformPrefixKey(ParseState* pstate, PrefixKey* pkey); @@ -353,6 +354,12 @@ Node *transformExprRecurse(ParseState *pstate, Node *expr) if (pstate->shouldCheckOrderbyCol) { pstate->orderbyCols = lappend(pstate->orderbyCols, expr); } + + if (((ColumnRef*)expr)->prior && t_thrd.proc->workingVersionNum >= PRIOR_EXPR_VERSION_NUM) { + PriorExpr* p_expr = makeNode(PriorExpr); + p_expr->node = result; + result = (Node*)p_expr; + } break; case T_ParamRef: @@ -853,8 +860,13 @@ Node* transformColumnRef(ParseState* pstate, ColumnRef* cref) AssertEreport(IsA(field1, String), MOD_OPT, ""); colname = strVal(field1); - if (pstate->p_hasStartWith) { - Node *expr = transformStartWithColumnRef(pstate, cref, &colname); + if (pstate->p_hasStartWith || pstate->p_split_where_for_swcb) { + Node *expr = NULL; + if (pstate->p_hasStartWith) { + expr = transformStartWithColumnRef(pstate, cref, &colname); + } else { + expr = transformStartWithWhereClauseColumnRef(pstate, cref, colname); + } /* function case, return directly */ if (expr != NULL) { @@ -1796,7 +1808,7 @@ static Node* transformFuncCall(ParseState* pstate, FuncCall* fn) /* ... and hand off to ParseFuncOrColumn */ result = ParseFuncOrColumn(pstate, fn->funcname, targs, last_srf, fn, fn->location, fn->call_func); - if (IsStartWithFunction((FuncExpr*)result) && !pstate->p_hasStartWith) { + if (IsStartWithFunction((FuncExpr*)result) && !pstate->p_hasStartWith && !pstate->p_split_where_for_swcb) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmodule(MOD_OPT), errmsg("Invalid function call."), @@ -3846,3 +3858,47 @@ ParseExprKindName(ParseExprKind exprKind) } return "unrecognized expression kind"; } + +/* + * transformStartWithWhereClauseColumnRef + * transform cref for start with where spliting stage + */ +static Node *transformStartWithWhereClauseColumnRef(ParseState *pstate, ColumnRef *cref, char *colname) +{ + Assert (colname != NULL); + + ListCell *lc = NULL; + RangeTblEntry *rte = NULL; + foreach (lc, pstate->p_rtable) { + rte = (RangeTblEntry *)lfirst(lc); + if (rte->rtekind == RTE_SUBQUERY && rte->alias != NULL && rte->alias->aliasname != NULL && + pg_strcasecmp(rte->alias->aliasname, "__sw_pseudo_col_table__") == 0) { + break; + } + } + + int len = list_length(cref->fields); + if (len == 1) { + Node *field = (Node*)linitial(cref->fields); + + if (pg_strcasecmp(colname, "connect_by_root") == 0) { + Node *funexpr = transformConnectByRootFuncCall(pstate, field, cref); + + /* + * Return function funexpr, otherwise process + * connect_by_root as regular case + */ + if (funexpr != NULL) { + return funexpr; + } + } + + /* for pseudo column, we return the corresponding var */ + if (IsPseudoReturnColumn(colname)) { + return scanRTEForColumn(pstate, rte, colname, cref->location); + } + } + + return NULL; +} + diff --git a/src/common/backend/parser/parse_node.cpp b/src/common/backend/parser/parse_node.cpp index 800c77d356ae52a77b1ebcdfe5693f6d8fb13a3e..b87da89de745bfd3a9cc3443ed3c6b0938a5189c 100644 --- a/src/common/backend/parser/parse_node.cpp +++ b/src/common/backend/parser/parse_node.cpp @@ -520,7 +520,7 @@ Const* make_const(ParseState* pstate, Value* value, int location) typid = UNKNOWNOID; /* will be coerced later */ typelen = -2; /* cstring-style varwidth type */ typebyval = false; - if (OidIsValid(GetCollationConnection())) { + if (!DB_IS_CMPT(B_FORMAT) && OidIsValid(GetCollationConnection())) { collid = GetCollationConnection(); } break; diff --git a/src/common/backend/parser/parse_relation.cpp b/src/common/backend/parser/parse_relation.cpp index bfcd6d8529270104c3c564334679c7fb6aa031ad..82d84396ce22d7e805d2d7a646303e0dea2051b0 100755 --- a/src/common/backend/parser/parse_relation.cpp +++ b/src/common/backend/parser/parse_relation.cpp @@ -2202,6 +2202,12 @@ void expandRTE(RangeTblEntry* rte, int rtindex, int sublevels_up, int location, break; case RTE_SUBQUERY: { /* Subquery RTE */ + /* for start with pseudo table, we mark its targetlist resjunk */ + if (rte->alias != NULL && rte->alias->aliasname != NULL && + pg_strcasecmp(rte->alias->aliasname, "__sw_pseudo_col_table__") == 0) { + break; + } + ListCell* aliasp_item = list_head(rte->eref->colnames); ListCell* tlistitem = NULL; diff --git a/src/common/backend/parser/parse_startwith.cpp b/src/common/backend/parser/parse_startwith.cpp index 5c4f21e6f7df21c5586ce44084bed13de5320c83..d1b8f8f2d9942598b4f5235737a071f4e83fbd2a 100644 --- a/src/common/backend/parser/parse_startwith.cpp +++ b/src/common/backend/parser/parse_startwith.cpp @@ -62,6 +62,8 @@ */ typedef struct StartWithTransformContext { ParseState* pstate; + ParseState* origin_pstate; + SelectStmt *origin_stmt; List *relInfoList; List *where_infos; List *connectby_prior_name; @@ -95,6 +97,8 @@ typedef struct StartWithTransformContext { Node *connectByLevelExpr; Node *connectByOtherExpr; bool nocycle; + /* used to track the varnos of given expr */ + Bitmapset *expr_varno_set; } StartWithTransformContext; typedef enum StartWithRewrite { @@ -133,11 +137,11 @@ static void AddWithClauseToBranch(ParseState *pstate, SelectStmt *stmt, List *re static void transformSingleRTE(ParseState* pstate, Query* qry, StartWithTransformContext *context, - Node *start_clause); -static void transformFromList(ParseState* pstate, - Query* qry, - StartWithTransformContext *context, - Node *n); + Node *sw_clause); +static void transformFromList(ParseState* pstate, Query* qry, + StartWithTransformContext *context, Node *sw_clause, + List *tlist, + bool is_first_node, bool is_creat_view); static RangeTblEntry *transformStartWithCTE(ParseState* pstate, List *prior_names); static bool preSkipPLSQLParams(ParseState *pstate, ColumnRef *cref); @@ -162,6 +166,7 @@ static void CreateStartWithCTE(ParseState *pstate, static Node *makeBoolAConst(bool state, int location); static StartWithRewrite ChooseSWCBStrategy(StartWithTransformContext context); static Node *tryReplaceFakeValue(Node *node); +static RangeSubselect *makeSWCBPseudoTable(); static Node *makeBoolAConst(bool state, int location) { @@ -232,7 +237,8 @@ static Node *makeBoolAConst(bool state, int location) * **************************************************************************************** */ -void transformStartWith(ParseState *pstate, SelectStmt *stmt, Query *qry) +void transformStartWith(ParseState *pstate, ParseState *origin_pstate, SelectStmt *stmt, + SelectStmt *origin_stmt, Query *qry, bool is_first_node, bool is_creat_view) { ListCell *lc = NULL; StartWithTransformContext context; @@ -249,6 +255,8 @@ void transformStartWith(ParseState *pstate, SelectStmt *stmt, Query *qry) securec_check(rc, "\0", "\0"); context.pstate = pstate; + context.origin_pstate = origin_pstate; + context.origin_stmt = origin_stmt; context.relInfoList = NULL; context.connectby_prior_name = NULL; @@ -272,7 +280,9 @@ void transformStartWith(ParseState *pstate, SelectStmt *stmt, Query *qry) if (op == SW_SINGLE) { transformSingleRTE(pstate, qry, &context, (Node *)stmt->startWithClause); } else { - transformFromList(pstate, qry, &context, (Node *)stmt->startWithClause); + transformFromList(pstate, qry, &context, (Node *)stmt->startWithClause, stmt->targetList, + is_first_node, is_creat_view); + stmt->whereClause = context.whereClause; } return; @@ -753,7 +763,7 @@ static void HandleSWCBColumnRef(StartWithTransformContext *context, Node *node) } else { context->relInfoList = list_concat_unique(context->relInfoList, result); } - + column->prior = false; return; } @@ -1509,55 +1519,161 @@ static void AddWithClauseToBranch(ParseState *pstate, SelectStmt *stmt, List *re return; } -static bool count_columnref_walker(Node *node, int *columnref_count) +static void make_full_varnamespace(StartWithTransformContext *context, RangeSubselect *pseudo_rte, + bool is_first_node, bool is_create_view) +{ + SelectStmt *stmt = makeNode(SelectStmt); + stmt->withClause = context->origin_stmt->withClause; + stmt->fromClause = lappend(context->origin_stmt->fromClause, pseudo_rte); + stmt->targetList = context->origin_stmt->targetList; + stmt->lockingClause = context->origin_stmt->lockingClause; + stmt->windowClause = context->origin_stmt->windowClause; + stmt->intoClause = context->origin_stmt->intoClause; + + (void)transformStmt(context->origin_pstate, (Node *)stmt, is_first_node, is_create_view); +} + +static bool is_swcb_pseudo_var(Var *var, StartWithTransformContext *context) +{ + bool is_pseudo_tbl = false; + if (var != NULL && var->varlevelsup == 0) { + RangeTblEntry *rte = rt_fetch(var->varno, context->origin_pstate->p_rtable); + if (rte->rtekind == RTE_SUBQUERY) { + Alias *alias = rte->alias; + is_pseudo_tbl = alias != NULL && alias->aliasname != NULL && + pg_strcasecmp(alias->aliasname, "__sw_pseudo_col_table__") == 0; + } + } + return is_pseudo_tbl; +} + +static bool find_varno_in_node(Node *node, StartWithTransformContext *context) { if (node == NULL) { return false; } - - if (!IsA(node, ColumnRef)) { - return raw_expression_tree_walker(node, (bool (*)()) count_columnref_walker, (void*)columnref_count); + + check_stack_depth(); + + if (IsA(node, Var)) { + /* if var is passed from upper query, we don't push it down into start with */ + Var *var = (Var *)node; + if (((Var *)node)->varlevelsup == 0) { + context->expr_varno_set = bms_add_member(context->expr_varno_set, var->varno); + } else { + bms_free_ext(context->expr_varno_set); + return true; + } + } else { + return expression_tree_walker(node, (bool (*)())find_varno_in_node, (void *)context); } - - *columnref_count = *columnref_count + 1; - + return false; } -static bool walker_to_exclude_non_join_quals(Node *node, Node *context_node) +static bool count_table_ref_walker(Node *node, StartWithTransformContext *context) { if (node == NULL) { return false; } - if (!IsA(node, A_Expr)) { - return raw_expression_tree_walker(node, (bool (*)()) walker_to_exclude_non_join_quals, (void*)NULL); + check_stack_depth(); + + /* we don't push down sublink */ + if (IsA(node, SubLink)) { + bms_free_ext(context->expr_varno_set); + return true; } - A_Expr* expr = (A_Expr*) node; - if (expr->kind != AEXPR_OP) { - return raw_expression_tree_walker(node, (bool (*)()) walker_to_exclude_non_join_quals, (void*)NULL); + if (!IsA(node, ColumnRef)) { + return raw_expression_tree_walker(node, (bool (*)()) count_table_ref_walker, (void*)context); } - /* - * this is to achieve consistent result sets with those produced by the original - * start with .. connect by syntax, which does not push filter quals down to connect quals. - * if no more than one column item appears inside an AEXPR_OP, we guess that it is - * not a join qual so should not be filtered in sw op, and force it to be true. - * this rule is not always correct but should work fine most of the time. - * could be improved later on, e.g. find better ways to extract non-join quals - * from the where clause. - */ - int columnref_count = 0; - (void) raw_expression_tree_walker(node, (bool (*)()) count_columnref_walker, (void*)&columnref_count); + Node *ret_node = (Node *)transformColumnRef(context->origin_pstate, (ColumnRef *)node); - if (columnref_count <= 1) { - expr->lexpr = makeBoolAConst(true, -1); - expr->rexpr = makeBoolAConst(true, -1); - expr->kind = AEXPR_OR; + if ((IsA(ret_node, Var) && is_swcb_pseudo_var(((Var *)ret_node), context)) || + (IsA(ret_node, FuncExpr) && IsStartWithFunction((FuncExpr *)ret_node))) { + return false; } - return false; + return find_varno_in_node(ret_node, context); +} + +/* + * split_where_expr_by_join + * + * According to the logic of Hierarchical Queries processing, start with operation will be as follows + * 1. Evaluating JOIN expr in where clause if there any(should only be muti-table join). + * 2. Evaluating START WITH/CONNECT BY condition. + * 3. Evaluating remaining where clause a.k.a NON-JOIN quals if there any. + * + * Based on that, we have to push down the join-qual for start-with/connect-by quals, but non-join quals save for later + * filtering right after start with operation is done. + * Note that, for OR expr, if we have to replace the sub_expr, we have to set it as FALSE, other case will be TRUE. + * + * For expr = (A AND (B OR C)) OR (D AND E) AND (F OR G) OR (H OR I), and we assume C, E, F, I is non_join qual, + * + * so the remaining JOIN expr will be + * (A AND B) OR (D) AND (G) OR H + * NON-JOIN expr will be + * (C) OR (E) AND (F) OR (I) + */ +static void split_where_expr_by_join(Node **p_expr_join, Node **p_expr_non_join, + StartWithTransformContext *context) +{ + if (p_expr_join == NULL || (p_expr_join != NULL && *p_expr_join == NULL)) { + return; + } + + Node *expr_join = *p_expr_join; + Node *expr_non_join = *p_expr_non_join; + + if (IsA(expr_join, A_Expr)) { + A_Expr *a_expr_join = (A_Expr *)expr_join; + A_Expr *a_expr_non_join = (A_Expr *)expr_non_join; + + if (a_expr_join->kind == AEXPR_AND || a_expr_join->kind == AEXPR_OR) { + if (a_expr_join->lexpr != NULL) { + split_where_expr_by_join(&(a_expr_join->lexpr), &(a_expr_non_join->lexpr), context); + } + if (a_expr_join->rexpr != NULL) { + split_where_expr_by_join(&(a_expr_join->rexpr), &(a_expr_non_join->rexpr), context); + } + if (a_expr_join->lexpr == NULL) { + *p_expr_join = a_expr_join->rexpr; + } else if (a_expr_join->rexpr == NULL) { + *p_expr_join = a_expr_join->lexpr; + } + + if (a_expr_non_join->lexpr == NULL) { + *p_expr_non_join = a_expr_non_join->rexpr; + } else if (a_expr_non_join->rexpr == NULL) { + *p_expr_non_join = a_expr_non_join->lexpr; + } + } else { + bms_free_ext(context->expr_varno_set); + count_table_ref_walker((Node *)a_expr_join, context); + /* if there're more than one tableref in this expr, then must be a join */ + if (bms_membership(context->expr_varno_set) == BMS_MULTIPLE) { + pfree_ext(expr_non_join); + *p_expr_non_join = NULL; + } else { + pfree_ext(expr_join); + *p_expr_join = NULL; + } + } + } else { + /* must not be a join qual for non-a_expr type */ + bms_free_ext(context->expr_varno_set); + count_table_ref_walker(expr_join, context); + if (bms_membership(context->expr_varno_set) == BMS_MULTIPLE) { + pfree_ext(expr_non_join); + *p_expr_non_join = NULL; + } else { + pfree_ext(expr_join); + *p_expr_join = NULL; + } + } } /* @@ -1613,22 +1729,6 @@ static SelectStmt *CreateStartWithCTEInnerBranch(ParseState* pstate, origin_table = (Node *)joiniter; } - - if (whereClause != NULL) { - JoinExpr *final_join = (JoinExpr *)origin_table; - /* pushdown requires deep copying of the quals */ - Node *whereCopy = (Node *)copyObject(whereClause); - /* only join quals can be pushed down */ - raw_expression_tree_walker((Node *)whereCopy, - (bool (*)())walker_to_exclude_non_join_quals, (void*)NULL); - - if (final_join->quals == NULL) { - final_join->quals = whereCopy; - } else { - final_join->quals = - (Node *)makeA_Expr(AEXPR_AND, NULL, whereCopy, final_join->quals, -1); - } - } } /* process regular/level */ @@ -1642,7 +1742,15 @@ static SelectStmt *CreateStartWithCTEInnerBranch(ParseState* pstate, join->larg = (Node *)work_table; join->rarg = origin_table; join->usingClause = NIL; - join->quals = (Node *)copyObject(connectByExpr); + Node *where_quals = NULL; + if (whereClause != NULL && connectByExpr != NULL) { + where_quals = (Node *)makeA_Expr(AEXPR_AND, NULL, whereClause, connectByExpr, -1); + } else if (whereClause != NULL) { + where_quals = (Node *)copyObject(whereClause); + } else { + where_quals = (Node *)copyObject(connectByExpr); + } + join->quals = where_quals; result->targetList = expandAllTargetList(relInfoList); result->fromClause = list_make1(join); @@ -1700,17 +1808,11 @@ static SelectStmt *CreateStartWithCTEOuterBranch(ParseState *pstate, /* push whereClause down to init part, taking care to avoid NULL in expr. */ quals = (Node *)startWithExpr; - Node* whereClauseCopy = (Node *)copyObject(whereClause); - if (whereClause != NULL) { - /* only join quals can be pushed down */ - raw_expression_tree_walker((Node*)whereClauseCopy, - (bool (*)())walker_to_exclude_non_join_quals, (void*)NULL); - } if (quals == NULL) { - quals = whereClauseCopy; + quals = whereClause; } else if (whereClause != NULL) { - quals = (Node *)makeA_Expr(AEXPR_AND, NULL, whereClauseCopy, + quals = (Node *)makeA_Expr(AEXPR_AND, NULL, whereClause, (Node*)startWithExpr, -1); } @@ -1871,22 +1973,32 @@ static RangeTblEntry *transformStartWithCTE(ParseState* pstate, List *prior_name * @Return: detail to be added * -------------------------------------------------------------------------------------- */ -static void transformFromList(ParseState* pstate, Query* qry, - StartWithTransformContext *context, Node *n) +static void transformFromList(ParseState* pstate, Query* qry, StartWithTransformContext *context, + Node *sw_clause, List *tlist, bool is_first_node, bool is_creat_view) { ListCell *lc = NULL; A_Expr *startWithExpr = (A_Expr *)context->startWithExpr; A_Expr *connectByExpr = (A_Expr *)context->connectByExpr; List *relInfoList = context->relInfoList; - Node *whereClause = context->whereClause; + Node *whereClauseOnlyJoin = (Node *)copyObject(context->whereClause); + + if (context->whereClause != NULL) { + RangeSubselect *sw_pseudo_table = makeSWCBPseudoTable(); + context->origin_pstate->p_split_where_for_swcb = true; + + /* add pseudo var namespace and alias var namespace into where_pstate */ + make_full_varnamespace(context, sw_pseudo_table, is_first_node, is_creat_view); + split_where_expr_by_join(&whereClauseOnlyJoin, &(context->whereClause), context); + free_parsestate(context->origin_pstate); + } /* make union-all branch for none-recursive part */ SelectStmt *outerBranch = CreateStartWithCTEOuterBranch(pstate, context, - relInfoList, (Node *)startWithExpr, whereClause); + relInfoList, (Node *)startWithExpr, whereClauseOnlyJoin); /* make joinExpr for recursive part */ SelectStmt *innerBranch = CreateStartWithCTEInnerBranch(pstate, context, - relInfoList, (Node *)connectByExpr, whereClause); + relInfoList, (Node *)connectByExpr, (Node *)copyObject(whereClauseOnlyJoin)); CreateStartWithCTE(pstate, qry, outerBranch, innerBranch, context); @@ -1939,7 +2051,7 @@ static void transformFromList(ParseState* pstate, Query* qry, * -------------------------------------------------------------------------------------- */ static void transformSingleRTE(ParseState* pstate, Query* qry, - StartWithTransformContext *context, Node *start_clause) + StartWithTransformContext *context, Node *sw_clause) { ListCell *lc = NULL; @@ -2049,3 +2161,44 @@ static List *expandAllTargetList(List *targetRelInfoList) return targetlist; } + +/* + * semtc_make_swcb_pseudo_table + * make a rte contains all of the start with pseudo cols, used for transform + */ +static RangeSubselect *makeSWCBPseudoTable() +{ + /* make a stmt for subquery */ + List *pseudo_tlist = NULL; + ResTarget *res_target = NULL; + A_Const *a_const = NULL; + StartWithCTEPseudoReturnAtts *att = NULL; + for (uint i = 0; i < STARTWITH_PSEUDO_RETURN_ATTNUMS; i++) { + /* if allow keyword rownum as ident, we don't treat "rownum" as pseudo column */ + if (i == SWCOL_ROWNUM) { + continue; + } + att = &g_StartWithCTEPseudoReturnAtts[i]; + + /* make var for pseudo return column */ + a_const = makeNode(A_Const); + a_const->val.type = T_Integer; + a_const->val.val.ival = 1; + a_const->location = -1; + res_target = makeNode(ResTarget); + res_target->name = att->colname; + res_target->indirection = NIL; + res_target->val = (Node *)a_const; + res_target->location = -1; + pseudo_tlist = lappend(pseudo_tlist, res_target); + } + + SelectStmt *stmt = makeNode(SelectStmt); + stmt->targetList = pseudo_tlist; + + RangeSubselect* subselect = makeNode(RangeSubselect); + subselect->subquery = (Node*)stmt; + Alias* alias = makeAlias("__sw_pseudo_col_table__", NIL); + subselect->alias = alias; + return subselect; +} diff --git a/src/common/backend/parser/parse_target.cpp b/src/common/backend/parser/parse_target.cpp index adc23c1129f9eb711dda74e1303d52cff1119ab6..ff960c57c4859eff157718324872c9de68daf798 100644 --- a/src/common/backend/parser/parse_target.cpp +++ b/src/common/backend/parser/parse_target.cpp @@ -135,7 +135,7 @@ List* transformTargetList(ParseState* pstate, List* targetlist, ParseExprKind ex if (IsA(res->val, ColumnRef)) { ColumnRef* cref = (ColumnRef*)res->val; - if (cref->prior) { + if (cref->prior && t_thrd.proc->workingVersionNum < PRIOR_EXPR_VERSION_NUM) { ereport(ERROR, (errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE), errmsg("Not Support prior column in TargetList in case swcb."))); diff --git a/src/common/backend/utils/adt/date.cpp b/src/common/backend/utils/adt/date.cpp index b417ef5ce3e177e4a8ec52322b3f7f4d580a1de5..209eba52a1bac2ad927bde056823b780b81c9981 100644 --- a/src/common/backend/utils/adt/date.cpp +++ b/src/common/backend/utils/adt/date.cpp @@ -24,6 +24,7 @@ #include "commands/copy.h" #include "libpq/pqformat.h" #include "miscadmin.h" +#include "nodes/supportnodes.h" #include "parser/scansup.h" #include "utils/array.h" #include "utils/builtins.h" @@ -1354,13 +1355,24 @@ Datum timetypmodout(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(anytime_typmodout(false, typmod)); } -/* time_transform() - * Flatten calls to time_scale() and timetz_scale() that solely represent - * increases in allowed precision. +/* + * time_support() + * + * Planner support function for the time_scale() and timetz_scale() + * length coercion functions (we need not distinguish them here). */ -Datum time_transform(PG_FUNCTION_ARGS) +Datum time_support(PG_FUNCTION_ARGS) { - PG_RETURN_POINTER(TemporalTransform(MAX_TIME_PRECISION, (Node*)PG_GETARG_POINTER(0))); + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; + + if (IsA(rawreq, SupportRequestSimplify)) { + SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; + + ret = TemporalSimplify(MAX_TIME_PRECISION, (Node *) req->fcall); + } + + PG_RETURN_POINTER(ret); } /* time_scale() diff --git a/src/common/backend/utils/adt/datetime.cpp b/src/common/backend/utils/adt/datetime.cpp index a14b71f8289930033377572acada66f3f5a2690f..e8f924cf673e224fe98bab64a9a0e951bb2fc966 100644 --- a/src/common/backend/utils/adt/datetime.cpp +++ b/src/common/backend/utils/adt/datetime.cpp @@ -4081,15 +4081,22 @@ bool CheckDateTokenTables(void) } /* - * Common code for temporal protransform functions. Types time, timetz, - * timestamp and timestamptz each have a range of allowed precisions. An - * unspecified precision is rigorously equivalent to the highest specifiable - * precision. + * Common code for temporal protransform functions: simplify, if possible, + * a call to a temporal type's length-coercion function. + * + * Types time, timetz, timestamp and timestamptz each have a range of allowed + * precisions. An unspecified precision is rigorously equivalent to the + * highest specifiable precision. We can replace the function call with a + * no-op RelabelType if it is coercing to the same or higher precision as the + * input is known to have. + * + * The input Node is always a FuncExpr, but to reduce the #include footprint + * of datetime.h, we declare it as Node *. * * Note: timestamp_scale throws an error when the typmod is out of range, but * we can't get there from a cast: our typmodin will have caught it already. */ -Node* TemporalTransform(int32 max_precis, Node* node) +Node* TemporalSimplify(int32 max_precis, Node* node) { FuncExpr* expr = (FuncExpr*)node; Node* ret = NULL; diff --git a/src/common/backend/utils/adt/format_type.cpp b/src/common/backend/utils/adt/format_type.cpp index 29c98a2262a904b4a6562d1315a46556053d1220..b82c181e876f47928fb2774dce088f7d9edd7297 100644 --- a/src/common/backend/utils/adt/format_type.cpp +++ b/src/common/backend/utils/adt/format_type.cpp @@ -151,7 +151,7 @@ static char* format_type_internal( array_base_type = typeform->typelem; if (array_base_type != InvalidOid && typeform->typstorage != 'p' && type_oid != OIDVECTOREXTENDOID && - type_oid != INT2VECTOREXTENDOID) { + type_oid != INT2VECTOREXTENDOID && typeform->typtype != TYPTYPE_TABLEOF) { /* Switch our attention to the array element type */ ReleaseSysCache(tuple); tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(array_base_type)); diff --git a/src/common/backend/utils/adt/formatting.cpp b/src/common/backend/utils/adt/formatting.cpp index a31c4b9880e3fa54dff1051a22792978247e8b3a..1e89835eed30375bbd86e1f9327009f4ebda038c 100644 --- a/src/common/backend/utils/adt/formatting.cpp +++ b/src/common/backend/utils/adt/formatting.cpp @@ -4097,10 +4097,10 @@ static void DCH_from_char(FormatNode* node, char* in, TmFromChar* out, bool* non } } - if (*s) - *non_match = true; - else + if (TrimStr(s) == NULL) *non_match = false; + else + *non_match = true; } static DCHCacheEntry* DCH_cache_getnew(const char* str) diff --git a/src/common/backend/utils/adt/numeric.cpp b/src/common/backend/utils/adt/numeric.cpp index 159e955d8a3c28969110ef73a122bbb705db5994..dfffb2070b449efa6ccfb45704c60e19086479a9 100644 --- a/src/common/backend/utils/adt/numeric.cpp +++ b/src/common/backend/utils/adt/numeric.cpp @@ -34,6 +34,7 @@ #include "libpq/pqformat.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" +#include "nodes/supportnodes.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/biginteger.h" @@ -696,43 +697,49 @@ Datum numeric_send(PG_FUNCTION_ARGS) } /* - * numeric_transform() - + * numeric_support() - * - * Flatten calls to numeric's length coercion function that solely represent - * increases in allowable precision. Scale changes mutate every datum, so - * they are unoptimizable. Some values, e.g. 1E-1001, can only fit into an - * unconstrained numeric, so a change from an unconstrained numeric to any - * constrained numeric is also unoptimizable. + * Planner support function for the numeric() length coercion function. + * + * Flatten calls that solely represent increases in allowable precision. + * Scale changes mutate every datum, so they are unoptimizable. Some values, + * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from + * an unconstrained numeric to any constrained numeric is also unoptimizable. */ -Datum numeric_transform(PG_FUNCTION_ARGS) +Datum numeric_support(PG_FUNCTION_ARGS) { - FuncExpr* expr = (FuncExpr*)PG_GETARG_POINTER(0); - Node* ret = NULL; - Node* typmod = NULL; + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; - Assert(IsA(expr, FuncExpr)); - Assert(list_length(expr->args) >= 2); + if (IsA(rawreq, SupportRequestSimplify)) { + SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; + FuncExpr *expr = req->fcall; + Node* typmod = NULL; - typmod = (Node*)lsecond(expr->args); + Assert(IsA(expr, FuncExpr)); + Assert(list_length(expr->args) >= 2); - if (IsA(typmod, Const) && !((Const*)typmod)->constisnull) { - Node* source = (Node*)linitial(expr->args); - int32 old_typmod = exprTypmod(source); - int32 new_typmod = DatumGetInt32(((Const*)typmod)->constvalue); - int32 old_scale = (int32)(((uint32)(old_typmod - VARHDRSZ)) & 0xffff); - int32 new_scale = (int32)(((uint32)(new_typmod - VARHDRSZ)) & 0xffff); - int32 old_precision = (int32)(((uint32)(old_typmod - VARHDRSZ)) >> 16 & 0xffff); - int32 new_precision = (int32)(((uint32)(new_typmod - VARHDRSZ)) >> 16 & 0xffff); + typmod = (Node*)lsecond(expr->args); - /* - * If new_typmod < VARHDRSZ, the destination is unconstrained; that's - * always OK. If old_typmod >= VARHDRSZ, the source is constrained, - * and we're OK if the scale is unchanged and the precision is not - * decreasing. See further notes in function header comment. - */ - if (new_typmod < (int32)VARHDRSZ || - (old_typmod >= (int32)VARHDRSZ && new_scale == old_scale && new_precision >= old_precision)) - ret = relabel_to_typmod(source, new_typmod); + if (IsA(typmod, Const) && !((Const*)typmod)->constisnull) { + Node* source = (Node*)linitial(expr->args); + int32 old_typmod = exprTypmod(source); + int32 new_typmod = DatumGetInt32(((Const*)typmod)->constvalue); + int32 old_scale = (int32)(((uint32)(old_typmod - VARHDRSZ)) & 0xffff); + int32 new_scale = (int32)(((uint32)(new_typmod - VARHDRSZ)) & 0xffff); + int32 old_precision = (int32)(((uint32)(old_typmod - VARHDRSZ)) >> 16 & 0xffff); + int32 new_precision = (int32)(((uint32)(new_typmod - VARHDRSZ)) >> 16 & 0xffff); + + /* + * If new_typmod < VARHDRSZ, the destination is unconstrained; that's + * always OK. If old_typmod >= VARHDRSZ, the source is constrained, + * and we're OK if the scale is unchanged and the precision is not + * decreasing. See further notes in function header comment. + */ + if (new_typmod < (int32)VARHDRSZ || + (old_typmod >= (int32)VARHDRSZ && new_scale == old_scale && new_precision >= old_precision)) + ret = relabel_to_typmod(source, new_typmod); + } } PG_RETURN_POINTER(ret); diff --git a/src/common/backend/utils/adt/numutils.cpp b/src/common/backend/utils/adt/numutils.cpp index fc581008a255dbf2859367d10bcaed6e3044c247..084e01b1bdbbdc00b667c9750ecb947243ecdf39 100644 --- a/src/common/backend/utils/adt/numutils.cpp +++ b/src/common/backend/utils/adt/numutils.cpp @@ -59,6 +59,38 @@ decimalLength32(const uint32 v) return t + (v >= PowersOfTen[t]); } +static inline int decimalLength64(const uint64 v) +{ + int t; + static const uint64 PowersOfTen[] = {UINT64CONST(1), + UINT64CONST(10), + UINT64CONST(100), + UINT64CONST(1000), + UINT64CONST(10000), + UINT64CONST(100000), + UINT64CONST(1000000), + UINT64CONST(10000000), + UINT64CONST(100000000), + UINT64CONST(1000000000), + UINT64CONST(10000000000), + UINT64CONST(100000000000), + UINT64CONST(1000000000000), + UINT64CONST(10000000000000), + UINT64CONST(100000000000000), + UINT64CONST(1000000000000000), + UINT64CONST(10000000000000000), + UINT64CONST(100000000000000000), + UINT64CONST(1000000000000000000), + UINT64CONST(10000000000000000000UL)}; + + /* + * Compute base-10 logarithm by dividing the base-2 logarithm by a + * good-enough approximation of the base-2 logarithm of 10 + */ + t = (pg_leftmost_one_pos64(v) + 1) * 1233 / 4096; + return t + (v >= PowersOfTen[t]); +} + /* * pg_atoi: convert string to integer * @@ -407,6 +439,72 @@ void pg_ltoa(int32 value, char* a) } } +char *pg_ltoa_printtup(int32 value, int *len) +{ + uint32 uvalue = (uint32) value; + char *a = u_sess->utils_cxt.int4output_buffer; + int olength = 0, i = 0, signLength = 0; + + if (value < 0) { + uvalue = (uint32) 0 - uvalue; + a[signLength++] = '-'; + } + + a = a + signLength; + + /* Degenerate case */ + if (value == 0) { + *a = '0'; + *len = 1; + a[*len] = '\0'; + return u_sess->utils_cxt.int4output_buffer; + } + + olength = decimalLength32(uvalue); + + /* + * Compute the result string. Use memcpy instead of memcpy_s/memcpy_sp for + * better performance, memcpy_s or memcpy_sp will degrade performance. + */ + while (uvalue >= 10000) { + const uint32 c = uvalue - 10000 * (uvalue / 10000); + const uint32 c0 = (c % 100) << 1; + const uint32 c1 = (c / 100) << 1; + + char *pos = a + olength - i; + + uvalue /= 10000; + + memcpy(pos - 2, DIGIT_TABLE + c0, 2); + memcpy(pos - 4, DIGIT_TABLE + c1, 2); + i += 4; + } + if (uvalue >= 100) { + const uint32 c = (uvalue % 100) << 1; + + char *pos = a + olength - i; + + uvalue /= 100; + + memcpy(pos - 2, DIGIT_TABLE + c, 2); + i += 2; + } + if (uvalue >= 10) { + const uint32 c = uvalue << 1; + + char *pos = a + olength - i; + + memcpy(pos - 2, DIGIT_TABLE + c, 2); + } else { + *a = (char)('0' + uvalue); + } + + *len = olength + signLength; + a[*len] = '\0'; + + return u_sess->utils_cxt.int4output_buffer; +} + /* * pg_lltoa: convert a signed 64-bit integer to its string representation * @@ -462,6 +560,94 @@ void pg_lltoa(int64 value, char* a) } } +char* pg_lltoa_printtup(int64 value, int* len) +{ + uint64 uvalue = (uint64) value; + char *a = u_sess->utils_cxt.int8output_buffer; + int olength = 0, i = 0, signLength = 0; + + if (value < 0) { + uvalue = (uint64) 0 - uvalue; + a[signLength++] = '-'; + } + + a = a + signLength; + + /* Degenerate case */ + if (value == 0) { + *a = '0'; + *len = 1; + a[*len] = '\0'; + return u_sess->utils_cxt.int8output_buffer; + } + + olength = decimalLength64(uvalue); + + /* + * Compute the result string. Use memcpy instead of memcpy_s/memcpy_sp for + * better performance, memcpy_s or memcpy_sp will degrade performance. + */ + while (uvalue >= 100000000) { + const uint64 q = uvalue / 100000000; + uint32 value3 = (uint32)(uvalue - 100000000 * q); + + const uint32 c = value3 % 10000; + const uint32 d = value3 / 10000; + const uint32 c0 = (c % 100) << 1; + const uint32 c1 = (c / 100) << 1; + const uint32 d0 = (d % 100) << 1; + const uint32 d1 = (d / 100) << 1; + + char *pos = a + olength - i; + + uvalue = q; + + memcpy(pos - 2, DIGIT_TABLE + c0, 2); + memcpy(pos - 4, DIGIT_TABLE + c1, 2); + memcpy(pos - 6, DIGIT_TABLE + d0, 2); + memcpy(pos - 8, DIGIT_TABLE + d1, 2); + i += 8; + } + + /* Switch to 32-bit for speed */ + uint32 value2 = (uint32)uvalue; + + if (value2 >= 10000) { + const uint32 c = value2 - 10000 * (value2 / 10000); + const uint32 c0 = (c % 100) << 1; + const uint32 c1 = (c / 100) << 1; + + char *pos = a + olength - i; + + value2 /= 10000; + + memcpy(pos - 2, DIGIT_TABLE + c0, 2); + memcpy(pos - 4, DIGIT_TABLE + c1, 2); + i += 4; + } + if (value2 >= 100) { + const uint32 c = (value2 % 100) << 1; + char *pos = a + olength - i; + + value2 /= 100; + + memcpy(pos - 2, DIGIT_TABLE + c, 2); + i += 2; + } + if (value2 >= 10) { + const uint32 c = value2 << 1; + char *pos = a + olength - i; + + memcpy(pos - 2, DIGIT_TABLE + c, 2); + } else + *a = (char)('0' + value2); + + *len = olength + signLength; + a[*len] = '\0'; + + return u_sess->utils_cxt.int8output_buffer; +} + /* * pg_lltoa: convert a signed 128-bit integer to its string representation * diff --git a/src/common/backend/utils/adt/pg_locale.cpp b/src/common/backend/utils/adt/pg_locale.cpp index ab5619ecf130613742378168c95bff1306029a20..472f947b48bbaf14a98028d51bc131b923604ad7 100644 --- a/src/common/backend/utils/adt/pg_locale.cpp +++ b/src/common/backend/utils/adt/pg_locale.cpp @@ -91,24 +91,19 @@ static char* IsoLocaleName(const char*); /* MSVC specific */ * ensure that, but that has to be done elsewhere after all the individual * LC_XXX variables have been set correctly. (Thank you Perl for making this * kluge necessary.) + * NB: Do not call this function to modify thread's locale information. */ char* pg_perm_setlocale(int category, const char* locale) { char* result = NULL; const char* envvar = NULL; - char* envbuf = NULL; #ifndef WIN32 - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); - - result = gs_setlocale_r(category, locale); - - if (IsUnderPostmaster) { - localeLock.unLock(); - return result; - } - localeLock.unLock(); + /* + * We only call this function during server startup, so we can set locale + * information without synchronization. + */ + result = setlocale(category, locale); #else /* @@ -134,11 +129,9 @@ char* pg_perm_setlocale(int category, const char* locale) switch (category) { case LC_COLLATE: envvar = "LC_COLLATE"; - envbuf = t_thrd.lc_cxt.lc_collate_envbuf; break; case LC_CTYPE: envvar = "LC_CTYPE"; - envbuf = t_thrd.lc_cxt.lc_ctype_envbuf; break; #ifdef WIN32 result = IsoLocaleName(locale); @@ -147,33 +140,22 @@ char* pg_perm_setlocale(int category, const char* locale) #endif /* WIN32 */ case LC_MONETARY: envvar = "LC_MONETARY"; - envbuf = t_thrd.lc_cxt.lc_monetary_envbuf; break; case LC_NUMERIC: envvar = "LC_NUMERIC"; - envbuf = t_thrd.lc_cxt.lc_numeric_envbuf; break; case LC_TIME: envvar = "LC_TIME"; - envbuf = t_thrd.lc_cxt.lc_time_envbuf; break; case LC_MESSAGES: envvar = "LC_MESSAGES"; - envbuf = t_thrd.lc_cxt.lc_messages_envbuf; break; default: ereport(FATAL, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("unrecognized LC category: %d", category))); - envvar = NULL; /* keep compiler quiet */ - envbuf = NULL; - return NULL; + return NULL; /* keep compiler quiet */ } - errno_t ss_rc = snprintf_s(envbuf, LC_ENV_BUFSIZE, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result); - if (ss_rc > LC_ENV_BUFSIZE - 1) - return NULL; - securec_check_ss(ss_rc, "\0", "\0"); - - if (gs_putenv_r(envbuf)) + if (setenv(envvar, result, 1) != 0) return NULL; return result; @@ -198,11 +180,8 @@ bool check_locale(int category, const char* locale, char** canonname) *canonname = NULL; /* in case of failure */ } - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); - save = gs_setlocale_r(category, NULL); + save = gs_perm_setlocale_r(category, NULL); if (save == NULL) { - localeLock.unLock(); return false; /* won't happen, we hope */ } @@ -210,18 +189,17 @@ bool check_locale(int category, const char* locale, char** canonname) save = pstrdup(save); /* set the locale with setlocale, to see if it accepts it. */ - res = gs_setlocale_r(category, locale); + res = gs_perm_setlocale_r(category, locale); /* save canonical name if requested. */ if ((res != NULL) && (canonname != NULL)) *canonname = pstrdup(res); /* restore old value. */ - if (!gs_setlocale_r(category, save)) + if (!gs_perm_setlocale_r(category, save)) elog(WARNING, "failed to restore old locale \"%s\"", save); pfree_ext(save); - localeLock.unLock(); return (res != NULL); } @@ -319,7 +297,7 @@ void assign_locale_messages(const char* newval, void* extra) * We ignore failure, as per comment above. */ #if defined(ENABLE_NLS) && defined(LC_MESSAGES) - (void) pg_perm_setlocale(LC_MESSAGES, newval); + (void) gs_perm_setlocale_r(LC_MESSAGES, newval); #endif } @@ -431,15 +409,12 @@ struct lconv* PGLC_localeconv(void) free_struct_lconv(curlconv); - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); - /* Save user's values of monetary and numeric locales */ - save_lc_monetary = gs_setlocale_r(LC_MONETARY, NULL); + save_lc_monetary = gs_perm_setlocale_r(LC_MONETARY, NULL); if (save_lc_monetary != NULL) save_lc_monetary = pstrdup(save_lc_monetary); - save_lc_numeric = gs_setlocale_r(LC_NUMERIC, NULL); + save_lc_numeric = gs_perm_setlocale_r(LC_NUMERIC, NULL); if (save_lc_numeric != NULL) save_lc_numeric = pstrdup(save_lc_numeric); @@ -476,7 +451,7 @@ struct lconv* PGLC_localeconv(void) #endif /* Get formatting information for numeric */ - gs_setlocale_r(LC_NUMERIC, u_sess->attr.attr_common.locale_numeric); + gs_perm_setlocale_r(LC_NUMERIC, u_sess->attr.attr_common.locale_numeric); extlconv = localeconv(); /* @@ -505,7 +480,7 @@ struct lconv* PGLC_localeconv(void) #endif /* Get formatting information for monetary */ - gs_setlocale_r(LC_MONETARY, u_sess->attr.attr_common.locale_monetary); + gs_perm_setlocale_r(LC_MONETARY, u_sess->attr.attr_common.locale_monetary); extlconv = localeconv(); encoding = pg_get_encoding_from_locale(u_sess->attr.attr_common.locale_monetary, true); @@ -540,14 +515,14 @@ struct lconv* PGLC_localeconv(void) { /* Try to restore internal settings */ if (save_lc_monetary != NULL) { - if (!gs_setlocale_r(LC_MONETARY, save_lc_monetary)) { + if (!gs_perm_setlocale_r(LC_MONETARY, save_lc_monetary)) { elog(WARNING, "failed to restore old locale"); } pfree_ext(save_lc_monetary); } if (save_lc_numeric != NULL) { - if (!gs_setlocale_r(LC_NUMERIC, save_lc_numeric)) { + if (!gs_perm_setlocale_r(LC_NUMERIC, save_lc_numeric)) { elog(WARNING, "failed to restore old locale"); } pfree_ext(save_lc_numeric); @@ -556,7 +531,7 @@ struct lconv* PGLC_localeconv(void) #ifdef WIN32 /* Try to restore internal ctype settings */ if (save_lc_ctype != NULL) { - if (!gs_setlocale_r(LC_CTYPE, save_lc_ctype)) { + if (!gs_perm_setlocale_r(LC_CTYPE, save_lc_ctype)) { elog(WARNING, "failed to restore old locale"); } pfree_ext(save_lc_ctype); @@ -567,22 +542,20 @@ struct lconv* PGLC_localeconv(void) MemoryContextSwitchTo(old_context); - localeLock.unLock(); - PG_RE_THROW(); } PG_END_TRY(); /* Try to restore internal settings */ if (save_lc_monetary != NULL) { - if (!gs_setlocale_r(LC_MONETARY, save_lc_monetary)) { + if (!gs_perm_setlocale_r(LC_MONETARY, save_lc_monetary)) { elog(WARNING, "failed to restore old locale"); } pfree_ext(save_lc_monetary); } if (save_lc_numeric != NULL) { - if (!gs_setlocale_r(LC_NUMERIC, save_lc_numeric)) { + if (!gs_perm_setlocale_r(LC_NUMERIC, save_lc_numeric)) { elog(WARNING, "failed to restore old locale"); } pfree_ext(save_lc_numeric); @@ -598,8 +571,6 @@ struct lconv* PGLC_localeconv(void) } #endif - localeLock.unLock(); - /* reload LC_MONETARY and LC_NUMERIC from session context to thread context */ rc = strncpy_s( NameStr(t_thrd.port_cxt.cur_monetary), NAMEDATALEN, u_sess->attr.attr_common.locale_monetary, NAMEDATALEN - 1); @@ -737,11 +708,8 @@ void cache_locale_time(void) elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", u_sess->attr.attr_common.locale_time); - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); - /* save user's value of time locale */ - save_lc_time = gs_setlocale_r(LC_TIME, NULL); + save_lc_time = gs_perm_setlocale_r(LC_TIME, NULL); if (save_lc_time != NULL) save_lc_time = pstrdup(save_lc_time); @@ -765,7 +733,7 @@ void cache_locale_time(void) setlocale(LC_CTYPE, u_sess->attr.attr_common.locale_time); #endif - gs_setlocale_r(LC_TIME, u_sess->attr.attr_common.locale_time); + gs_perm_setlocale_r(LC_TIME, u_sess->attr.attr_common.locale_time); timenow = time(NULL); localtime_r(&timenow, &timeinfo); @@ -787,7 +755,7 @@ void cache_locale_time(void) /* try to restore internal settings */ if (save_lc_time != NULL) { - if (!gs_setlocale_r(LC_TIME, save_lc_time)) + if (!gs_perm_setlocale_r(LC_TIME, save_lc_time)) elog(WARNING, "failed to restore old locale"); pfree_ext(save_lc_time); } @@ -801,7 +769,6 @@ void cache_locale_time(void) } #endif - localeLock.unLock(); u_sess->lc_cxt.cur_lc_time_valid = true; } @@ -1017,11 +984,8 @@ bool lc_collate_is_c(Oid collation) if (u_sess->lc_cxt.lc_collate_result >= 0) return (bool)u_sess->lc_cxt.lc_collate_result; - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); - localeptr = gs_setlocale_r(LC_COLLATE, NULL); + localeptr = gs_perm_setlocale_r(LC_COLLATE, NULL); if (localeptr == NULL) { - localeLock.unLock(); ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION), errmsg("invalid LC_COLLATE setting"))); } @@ -1032,7 +996,6 @@ bool lc_collate_is_c(Oid collation) else u_sess->lc_cxt.lc_collate_result = false; - localeLock.unLock(); return (bool)u_sess->lc_cxt.lc_collate_result; } @@ -1070,11 +1033,8 @@ bool lc_ctype_is_c(Oid collation) if (u_sess->lc_cxt.lc_ctype_result >= 0) return (bool)u_sess->lc_cxt.lc_ctype_result; - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); - localeptr = gs_setlocale_r(LC_CTYPE, NULL); + localeptr = gs_perm_setlocale_r(LC_CTYPE, NULL); if (localeptr == NULL) { - localeLock.unLock(); ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION), errmsg("invalid LC_CTYPE setting"))); } @@ -1085,7 +1045,6 @@ bool lc_ctype_is_c(Oid collation) else u_sess->lc_cxt.lc_ctype_result = false; - localeLock.unLock(); return (bool)u_sess->lc_cxt.lc_ctype_result; } diff --git a/src/common/backend/utils/adt/regproc.cpp b/src/common/backend/utils/adt/regproc.cpp index c5e4713fdb6c55794e3b653750d6693997537149..bf0d636994a345147d3916e70548d39af661bf56 100644 --- a/src/common/backend/utils/adt/regproc.cpp +++ b/src/common/backend/utils/adt/regproc.cpp @@ -364,7 +364,7 @@ char * format_procedure_no_visible(Oid procedure_oid) { char* result = NULL; HeapTuple proctup; - proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid)); + proctup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procedure_oid)); if (HeapTupleIsValid(proctup)) { Form_pg_proc procform = (Form_pg_proc)GETSTRUCT(proctup); char* proname = NameStr(procform->proname); @@ -383,7 +383,7 @@ char * format_procedure_no_visible(Oid procedure_oid) } appendStringInfoChar(&buf, ')'); result = buf.data; - ReleaseSysCache(proctup); + heap_freetuple(proctup); } else { /* If OID doesn't match any pg_proc entry, return it numerically */ result = (char*)palloc(NAMEDATALEN); @@ -406,7 +406,7 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) char* result = NULL; HeapTuple proctup; - proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid)); + proctup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procedure_oid)); if (HeapTupleIsValid(proctup)) { Form_pg_proc procform = (Form_pg_proc)GETSTRUCT(proctup); @@ -443,7 +443,7 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) result = buf.data; - ReleaseSysCache(proctup); + heap_freetuple(proctup); } else { /* If OID doesn't match any pg_proc entry, return it numerically */ result = (char*)palloc(NAMEDATALEN); diff --git a/src/common/backend/utils/adt/ruleutils.cpp b/src/common/backend/utils/adt/ruleutils.cpp index e90fe06cf4be54027b49941eb30f04da5d984880..cc65140c03c46ca4df82055a3be0e1193957325a 100644 --- a/src/common/backend/utils/adt/ruleutils.cpp +++ b/src/common/backend/utils/adt/ruleutils.cpp @@ -10425,6 +10425,12 @@ static void get_rule_expr(Node* node, deparse_context* context, bool showimplici appendStringInfoChar(buf, ')'); } break; + case T_PriorExpr: { + appendContextKeyword(context, "Prior ", 0, 0, 0); + PriorExpr* prior_expr = (PriorExpr*)node; + get_rule_expr(prior_expr->node, context, showimplicit, no_alias); + } break; + case T_NullTest: { NullTest* ntest = (NullTest*)node; diff --git a/src/common/backend/utils/adt/timestamp.cpp b/src/common/backend/utils/adt/timestamp.cpp index 9f5bdcbf27d90b84c204b1f8dbfbbfbbb24f259c..0039c3a44aa32fe996156ca39313813ad2b85b73 100644 --- a/src/common/backend/utils/adt/timestamp.cpp +++ b/src/common/backend/utils/adt/timestamp.cpp @@ -30,6 +30,7 @@ #include "libpq/pqformat.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" +#include "nodes/supportnodes.h" #include "parser/scansup.h" #include "utils/array.h" #include "utils/builtins.h" @@ -720,13 +721,24 @@ Datum timestamptypmodout(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(anytimestamp_typmodout(false, typmod)); } -/* timestamp_transform() - * Flatten calls to timestamp_scale() and timestamptz_scale() that solely - * represent increases in allowed precision. +/* + * timestamp_support() + * + * Planner support function for the timestamp_scale() and timestamptz_scale() + * length coercion functions (we need not distinguish them here). */ -Datum timestamp_transform(PG_FUNCTION_ARGS) +Datum timestamp_support(PG_FUNCTION_ARGS) { - PG_RETURN_POINTER(TemporalTransform(MAX_TIMESTAMP_PRECISION, (Node*)PG_GETARG_POINTER(0))); + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; + + if (IsA(rawreq, SupportRequestSimplify)) { + SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; + + ret = TemporalSimplify(MAX_TIMESTAMP_PRECISION, (Node *) req->fcall); + } + + PG_RETURN_POINTER(ret); } /* timestamp_scale() @@ -1257,58 +1269,69 @@ static int intervaltypmodleastfield(int32 typmod) return 0; /* can't get here, but keep compiler quiet */ } -/* interval_transform() +/* + * interval_support() + * + * Planner support function for interval_scale(). + * * Flatten superfluous calls to interval_scale(). The interval typmod is * complex to permit accepting and regurgitating all SQL standard variations. * For truncation purposes, it boils down to a single, simple granularity. */ -Datum interval_transform(PG_FUNCTION_ARGS) -{ - FuncExpr* expr = (FuncExpr*)PG_GETARG_POINTER(0); - Node* ret = NULL; - Node* typmod = NULL; - - Assert(IsA(expr, FuncExpr)); - Assert(list_length(expr->args) >= 2); - - typmod = (Node*)lsecond(expr->args); - - if (IsA(typmod, Const) && !((Const*)typmod)->constisnull) { - Node* source = (Node*)linitial(expr->args); - int32 new_typmod = DatumGetInt32(((Const*)typmod)->constvalue); - bool noop = false; - - if (new_typmod < 0) - noop = true; - else { - int32 old_typmod = exprTypmod(source); - int old_least_field; - int new_least_field; - int old_precis; - int new_precis; - - old_least_field = intervaltypmodleastfield(old_typmod); - new_least_field = intervaltypmodleastfield(new_typmod); - if (old_typmod < 0) { - old_precis = INTERVAL_FULL_PRECISION; - } else { - old_precis = INTERVAL_PRECISION(old_typmod); - } - new_precis = INTERVAL_PRECISION(new_typmod); +Datum interval_support(PG_FUNCTION_ARGS) +{ + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; + + if (IsA(rawreq, SupportRequestSimplify)) { + SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; + FuncExpr *expr = req->fcall; + Node* typmod = NULL; + + Assert(IsA(expr, FuncExpr)); + Assert(list_length(expr->args) >= 2); + + typmod = (Node*)lsecond(expr->args); + + if (IsA(typmod, Const) && !((Const*)typmod)->constisnull) { + Node* source = (Node*)linitial(expr->args); + int32 new_typmod = DatumGetInt32(((Const*)typmod)->constvalue); + bool noop = false; + + if (new_typmod < 0) + noop = true; + else { + int32 old_typmod = exprTypmod(source); + int old_least_field; + int new_least_field; + int old_precis; + int new_precis; + + old_least_field = intervaltypmodleastfield(old_typmod); + new_least_field = intervaltypmodleastfield(new_typmod); + if (old_typmod < 0) { + old_precis = INTERVAL_FULL_PRECISION; + } else { + old_precis = INTERVAL_PRECISION(old_typmod); + } + new_precis = INTERVAL_PRECISION(new_typmod); - /* - * Cast is a no-op if least field stays the same or decreases - * while precision stays the same or increases. But precision, - * which is to say, sub-second precision, only affects ranges that - * include SECOND. - */ - noop = - (new_least_field <= old_least_field) && - (old_least_field > 0 /* SECOND */ || new_precis >= MAX_INTERVAL_PRECISION || new_precis >= old_precis); + /* + * Cast is a no-op if least field stays the same or decreases + * while precision stays the same or increases. But precision, + * which is to say, sub-second precision, only affects ranges that + * include SECOND. + */ + noop = + (new_least_field <= old_least_field) && + (old_least_field > 0 /* SECOND */ || + new_precis >= MAX_INTERVAL_PRECISION || + new_precis >= old_precis); + } + if (noop) + ret = relabel_to_typmod(source, new_typmod); } - if (noop) - ret = relabel_to_typmod(source, new_typmod); - } + } PG_RETURN_POINTER(ret); } @@ -1378,7 +1401,7 @@ static void AdjustIntervalForTypmod(Interval* interval, int32 typmod) * can't do it consistently. (We cannot enforce a range limit on the * highest expected field, since we do not have any equivalent of * SQL's .) If we ever decide to - * revisit this, interval_transform will likely require adjusting. + * revisit this, interval_support will likely require adjusting. * * Note: before PG 8.4 we interpreted a limited set of fields as * actually causing a "modulo" operation on a given value, potentially diff --git a/src/common/backend/utils/adt/varbit.cpp b/src/common/backend/utils/adt/varbit.cpp index af4fc873497d12547ce8e5013dac2c1c6a0ad3b5..ccb22b51f248f1a394d4c19be0e7fd7ef121089a 100644 --- a/src/common/backend/utils/adt/varbit.cpp +++ b/src/common/backend/utils/adt/varbit.cpp @@ -21,6 +21,7 @@ #include "common/int.h" #include "libpq/pqformat.h" #include "nodes/nodeFuncs.h" +#include "nodes/supportnodes.h" #include "utils/array.h" #include "utils/varbit.h" @@ -605,31 +606,39 @@ Datum varbit_send(PG_FUNCTION_ARGS) } /* - * varbit_transform() - * Flatten calls to varbit's length coercion function that set the new maximum - * length >= the previous maximum length. We can ignore the isExplicit - * argument, since that only affects truncation cases. + * varbit_support() + * + * Planner support function for the varbit() length coercion function. + * + * Currently, the only interesting thing we can do is flatten calls that set + * the new maximum length >= the previous maximum length. We can ignore the + * isExplicit argument, since that only affects truncation cases. */ -Datum varbit_transform(PG_FUNCTION_ARGS) +Datum varbit_support(PG_FUNCTION_ARGS) { - FuncExpr* expr = (FuncExpr*)PG_GETARG_POINTER(0); - Node* ret = NULL; - Node* typmod = NULL; + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; - Assert(IsA(expr, FuncExpr)); - Assert(list_length(expr->args) >= 2); + if (IsA(rawreq, SupportRequestSimplify)) { + SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; + FuncExpr *expr = req->fcall; + Node* typmod = NULL; - typmod = (Node*)lsecond(expr->args); + Assert(IsA(expr, FuncExpr)); + Assert(list_length(expr->args) >= 2); - if (IsA(typmod, Const) && !((Const*)typmod)->constisnull) { - Node* source = (Node*)linitial(expr->args); - int32 new_typmod = DatumGetInt32(((Const*)typmod)->constvalue); - int32 old_max = exprTypmod(source); - int32 new_max = new_typmod; + typmod = (Node*)lsecond(expr->args); - /* Note: varbit() treats typmod 0 as invalid, so we do too */ - if (new_max <= 0 || (old_max > 0 && old_max <= new_max)) - ret = relabel_to_typmod(source, new_typmod); + if (IsA(typmod, Const) && !((Const*)typmod)->constisnull) { + Node* source = (Node*)linitial(expr->args); + int32 new_typmod = DatumGetInt32(((Const*)typmod)->constvalue); + int32 old_max = exprTypmod(source); + int32 new_max = new_typmod; + + /* Note: varbit() treats typmod 0 as invalid, so we do too */ + if (new_max <= 0 || (old_max > 0 && old_max <= new_max)) + ret = relabel_to_typmod(source, new_typmod); + } } PG_RETURN_POINTER(ret); diff --git a/src/common/backend/utils/adt/varchar.cpp b/src/common/backend/utils/adt/varchar.cpp index 00def681a17817dec1ab383372bf2885a15d38e3..f0d2b25c179a458a309da131bc2ca10e04880a60 100644 --- a/src/common/backend/utils/adt/varchar.cpp +++ b/src/common/backend/utils/adt/varchar.cpp @@ -19,6 +19,7 @@ #include "access/tuptoaster.h" #include "libpq/pqformat.h" #include "nodes/nodeFuncs.h" +#include "nodes/supportnodes.h" #include "utils/array.h" #include "utils/builtins.h" #include "mb/pg_wchar.h" @@ -579,31 +580,39 @@ Datum varcharsend(PG_FUNCTION_ARGS) } /* - * varchar_transform() - * Flatten calls to varchar's length coercion function that set the new maximum - * length >= the previous maximum length. We can ignore the isExplicit - * argument, since that only affects truncation cases. + * varchar_support() + * + * Planner support function for the varchar() length coercion function. + * + * Currently, the only interesting thing we can do is flatten calls that set + * the new maximum length >= the previous maximum length. We can ignore the + * isExplicit argument, since that only affects truncation cases. */ -Datum varchar_transform(PG_FUNCTION_ARGS) +Datum varchar_support(PG_FUNCTION_ARGS) { - FuncExpr* expr = (FuncExpr*)PG_GETARG_POINTER(0); - Node* ret = NULL; - Node* typmod = NULL; + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; - Assert(IsA(expr, FuncExpr)); - Assert(list_length(expr->args) >= 2); + if (IsA(rawreq, SupportRequestSimplify)) { + SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; + FuncExpr *expr = req->fcall; + Node *typmod; - typmod = (Node*)lsecond(expr->args); + Assert(list_length(expr->args) >= 2); - if (IsA(typmod, Const) && !((Const*)typmod)->constisnull) { - Node* source = (Node*)linitial(expr->args); - int32 old_typmod = exprTypmod(source); - int32 new_typmod = DatumGetInt32(((Const*)typmod)->constvalue); - int32 old_max = old_typmod - VARHDRSZ; - int32 new_max = new_typmod - VARHDRSZ; + typmod = (Node *) lsecond(expr->args); - if (new_typmod < 0 || (old_typmod >= 0 && old_max <= new_max)) - ret = relabel_to_typmod(source, new_typmod); + if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull) + { + Node *source = (Node *) linitial(expr->args); + int32 old_typmod = exprTypmod(source); + int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue); + int32 old_max = old_typmod - VARHDRSZ; + int32 new_max = new_typmod - VARHDRSZ; + + if (new_typmod < 0 || (old_typmod >= 0 && old_max <= new_max)) + ret = relabel_to_typmod(source, new_typmod); + } } PG_RETURN_POINTER(ret); diff --git a/src/common/backend/utils/adt/varlena.cpp b/src/common/backend/utils/adt/varlena.cpp index 5e5152c609b3cc54c826dd17aa854fc05b26a0b4..daf0fb4c5a779d4b310300a19063bbd831390f14 100644 --- a/src/common/backend/utils/adt/varlena.cpp +++ b/src/common/backend/utils/adt/varlena.cpp @@ -266,20 +266,6 @@ char* output_text_to_cstring(const text* t) return result; } -char* output_int32_to_cstring(int32 value) -{ - u_sess->utils_cxt.int4output_buffer[0] = '\0'; - pg_ltoa(value, u_sess->utils_cxt.int4output_buffer); - return u_sess->utils_cxt.int4output_buffer; -} - -char* output_int64_to_cstring(int64 value) -{ - u_sess->utils_cxt.int8output_buffer[0] = '\0'; - pg_lltoa(value, u_sess->utils_cxt.int8output_buffer); - return u_sess->utils_cxt.int8output_buffer; -} - /* * text_to_cstring_buffer * @@ -6437,16 +6423,28 @@ Datum group_concat_transfn(PG_FUNCTION_ARGS) */ Datum group_concat_finalfn(PG_FUNCTION_ARGS) { - StringInfo state; - /* cannot be called directly because of internal-type argument */ Assert(AggCheckCallContext(fcinfo, NULL)); if (!PG_ARGISNULL(0)) { /* result not null */ - state = (StringInfo)PG_GETARG_POINTER(0); + StringInfo state = (StringInfo)PG_GETARG_POINTER(0); + int cur_charset = get_valid_charset_by_collation(PG_GET_COLLATION()); + int encoding_max_length = pg_wchar_table[cur_charset].maxmblen; + int real_len = state->len - encoding_max_length; + char* real_data = state->data + real_len; + while (real_data != NULL) { + int cur_len = pg_wchar_table[cur_charset].mblen((const unsigned char*)real_data); + real_len += cur_len; + if (real_len > state->len) { + state->len = (real_len - cur_len); + break; + } + real_data += cur_len; + } PG_RETURN_TEXT_P(cstring_to_text_with_len(state->data, state->len)); - } else + } else { PG_RETURN_NULL(); + } } /* diff --git a/src/common/backend/utils/adt/xid.cpp b/src/common/backend/utils/adt/xid.cpp index 03081e9ff69013577c05da566bfc405b289e0192..1bb4ac86697dc678f31a2a37ac49bf3289dc4a8c 100644 --- a/src/common/backend/utils/adt/xid.cpp +++ b/src/common/backend/utils/adt/xid.cpp @@ -178,9 +178,9 @@ Datum xid_age(PG_FUNCTION_ARGS) /* Permanent XIDs are always infinitely old */ if (!TransactionIdIsNormal(xid)) - PG_RETURN_INT64(INT64_MAX); + PG_RETURN_TRANSACTIONID(UINT64_MAX); - PG_RETURN_INT64((int64)(now - xid)); + PG_RETURN_TRANSACTIONID((TransactionId)(now - xid)); } /* diff --git a/src/common/backend/utils/cache/lsyscache.cpp b/src/common/backend/utils/cache/lsyscache.cpp index da583b39560ab10ff4ea711be3b7c7a031e4c601..632c4872bd5db242d560134dd9626363fbf71996 100644 --- a/src/common/backend/utils/cache/lsyscache.cpp +++ b/src/common/backend/utils/cache/lsyscache.cpp @@ -2151,7 +2151,7 @@ constexpr int16 DATE_TYPLEN = 4; constexpr int16 TIMESTAMP_TYPLEN = 8; int16 get_typlen(Oid typid) { - if (typid == INT4OID || typid == DATEOID) { + if (typid == INT4OID || typid == DATEOID || typid == FLOAT4OID) { return DATE_TYPLEN; } else if (typid == BPCHAROID || typid == VARCHAROID) { return -1; @@ -2665,6 +2665,7 @@ Oid get_typeoid_with_namespace(const char* typname) */ Oid get_pgxc_nodeoid(const char* nodename) { +#ifdef ENABLE_MULTIPLE_NODES Oid node_oid = InvalidOid; CatCList* memlist = NULL; int i; @@ -2679,6 +2680,9 @@ Oid get_pgxc_nodeoid(const char* nodename) } ReleaseSysCacheList(memlist); return node_oid; +#else + return InvalidOid; +#endif } Oid get_pgxc_datanodeoid(const char* nodename, bool missingOK) diff --git a/src/common/backend/utils/cache/plancache.cpp b/src/common/backend/utils/cache/plancache.cpp index f6ddd974258c0c452341ccf4ddb6084b56deb382..bf845433cf46e8408bb3ad1615a47a7112013bd5 100644 --- a/src/common/backend/utils/cache/plancache.cpp +++ b/src/common/backend/utils/cache/plancache.cpp @@ -1056,8 +1056,15 @@ List* RevalidateCachedQuery(CachedPlanSource* plansource, bool has_lp) } else if (resultDesc == NULL || plansource->resultDesc == NULL || !equalTupleDescs(resultDesc, plansource->resultDesc)) { /* can we give a better error message? */ - if (plansource->fixed_result) - ereport(ERROR, (errcode(ERRCODE_INVALID_CACHE_PLAN), errmsg("cached plan must not change result type"))); + if (plansource->fixed_result) { + ereport(ERROR, (errcode(ERRCODE_INVALID_CACHE_PLAN), + errmsg("cached plan must not change result type"))); + } else if (!FORCE_VALIDATE_PLANCACHE_RESULT) { + /* If result type validation is turned off, better notice the caller */ + ereport(NOTICE, (errmsg("cached plan's result type has changed"), + errdetail("plan cache result type validation is turned off"))); + } + oldcxt = MemoryContextSwitchTo(plansource->context); if (resultDesc) resultDesc = CreateTupleDescCopy(resultDesc); diff --git a/src/common/backend/utils/cache/relcache.cpp b/src/common/backend/utils/cache/relcache.cpp index 116e0705672cb1611a0abcf68936372d4e379e9d..593cadc602a078c79404c96f5b9db507c74dcad1 100755 --- a/src/common/backend/utils/cache/relcache.cpp +++ b/src/common/backend/utils/cache/relcache.cpp @@ -5049,48 +5049,66 @@ void RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, Multi * index, pg_class.relfilenode doesn't change; instead we have to send the * update to the relation mapper. */ - if (RelationIsMapped(relation)) + if (RelationIsMapped(relation)) { + /* This case is only supported for indexes */ + Assert(relation->rd_rel->relkind == RELKIND_INDEX); + + /* Since we're not updating pg_class, these had better not change */ + Assert(classform->relfrozenxid == freezeXid); + + /* + * In some code paths it's possible that the tuple update we'd + * otherwise do here is the only thing that would assign an XID for + * the current transaction. However, we must have an XID to delete + * files, so make sure one is assigned. + */ + (void) GetCurrentTransactionId(); + + /* Do the deed */ RelationMapUpdateMap(RelationGetRelid(relation), newrelfilenode, relation->rd_rel->relisshared, false); - else + + /* Since we're not updating pg_class, must trigger inval manually */ + CacheInvalidateRelcache(relation); + } else { classform->relfilenode = newrelfilenode; - /* These changes are safe even for a mapped relation */ - if (!RELKIND_IS_SEQUENCE(relation->rd_rel->relkind)) { - classform->relpages = 0; /* it's empty until further notice */ - classform->reltuples = 0; - classform->relallvisible = 0; - } - /* set classform's relfrozenxid and relfrozenxid64 */ - classform->relfrozenxid = (ShortTransactionId)InvalidTransactionId; + /* relpages etc. never change for sequences */ + if (relation->rd_rel->relkind != RELKIND_SEQUENCE) { + classform->relpages = 0; /* it's empty until further notice */ + classform->reltuples = 0; + classform->relallvisible = 0; + } - rc = memset_s(values, sizeof(values), 0, sizeof(values)); - securec_check(rc, "\0", "\0"); - rc = memset_s(nulls, sizeof(nulls), false, sizeof(nulls)); - securec_check(rc, "\0", "\0"); - rc = memset_s(replaces, sizeof(replaces), false, sizeof(replaces)); - securec_check(rc, "\0", "\0"); + /* set classform's relfrozenxid and relfrozenxid64 */ + classform->relfrozenxid = (ShortTransactionId)InvalidTransactionId; + + rc = memset_s(values, sizeof(values), 0, sizeof(values)); + securec_check(rc, "\0", "\0"); + rc = memset_s(nulls, sizeof(nulls), false, sizeof(nulls)); + securec_check(rc, "\0", "\0"); + rc = memset_s(replaces, sizeof(replaces), false, sizeof(replaces)); + securec_check(rc, "\0", "\0"); - replaces[Anum_pg_class_relfrozenxid64 - 1] = true; - values[Anum_pg_class_relfrozenxid64 - 1] = TransactionIdGetDatum(freezeXid); + replaces[Anum_pg_class_relfrozenxid64 - 1] = true; + values[Anum_pg_class_relfrozenxid64 - 1] = TransactionIdGetDatum(freezeXid); #ifndef ENABLE_MULTIPLE_NODES - replaces[Anum_pg_class_relminmxid - 1] = true; - values[Anum_pg_class_relminmxid - 1] = TransactionIdGetDatum(minmulti); + replaces[Anum_pg_class_relminmxid - 1] = true; + values[Anum_pg_class_relminmxid - 1] = TransactionIdGetDatum(minmulti); #endif + nctup = heap_modify_tuple(tuple, RelationGetDescr(pg_class), values, nulls, replaces); - nctup = heap_modify_tuple(tuple, RelationGetDescr(pg_class), values, nulls, replaces); - - simple_heap_update(pg_class, &nctup->t_self, nctup); - CatalogUpdateIndexes(pg_class, nctup); - - heap_freetuple_ext(nctup); + simple_heap_update(pg_class, &nctup->t_self, nctup); + CatalogUpdateIndexes(pg_class, nctup); + heap_freetuple_ext(nctup); + } heap_freetuple_ext(tuple); heap_close(pg_class, RowExclusiveLock); } /* - * Make the pg_class row change visible, as well as the relation map - * change if any. This will cause the relcache entry to get updated, too. + * Make the pg_class row change or relation map change visible. + * This will cause the relcache entry to get updated, too. */ CommandCounterIncrement(); diff --git a/src/common/backend/utils/fmgr/dfmgr.cpp b/src/common/backend/utils/fmgr/dfmgr.cpp index acad6a35a4356e68bef82c841b06d637e1d54bcb..b0d56ef6cf6993fb52d4a77150a2b482764b1926 100644 --- a/src/common/backend/utils/fmgr/dfmgr.cpp +++ b/src/common/backend/utils/fmgr/dfmgr.cpp @@ -217,9 +217,7 @@ void* internal_load_library(const char* libname) char* file = last_dir_separator(libname); file = (file == NULL) ? ((char*)libname) : (file + 1); - AutoMutexLock libraryLock(&file_list_lock); - libraryLock.lock(); - + PthreadMutexLock(t_thrd.utils_cxt.CurrentResourceOwner, &file_list_lock, true); /* * Scan the list of loaded FILES to see if the file has been loaded. */ @@ -401,7 +399,7 @@ void* internal_load_library(const char* libname) u_sess->fmgr_cxt.file_init_tail = file_init_scanner; } - libraryLock.unLock(); + PthreadMutexUnlock(t_thrd.utils_cxt.CurrentResourceOwner, &file_list_lock, true); return file_scanner->handle; } diff --git a/src/common/backend/utils/fmgr/funcapi.cpp b/src/common/backend/utils/fmgr/funcapi.cpp index 12c4d00dae3f92fec7956d2989e2dd38ccfa7cae..025f4200a8087a487e2c6b31471f9b3fc9daa352 100644 --- a/src/common/backend/utils/fmgr/funcapi.cpp +++ b/src/common/backend/utils/fmgr/funcapi.cpp @@ -207,11 +207,28 @@ bool is_function_with_plpgsql_language_and_outparam(Oid funcid) ReleaseSysCache(tp); return false; } - isNull = false; - (void)SysCacheGetAttr(PROCOID, tp, Anum_pg_proc_proallargtypes, &isNull); + + Datum proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, tp, Anum_pg_proc_proargmodes, &isNull); if (!isNull) { - existOutParam = true; + ArrayType* arr = DatumGetArrayTypeP(proargmodes); + if (arr != NULL) { + int modelen = ARR_DIMS(arr)[0]; + char *argmodes = (char*)ARR_DATA_PTR(arr); + for (int i = 0; i < modelen; i++) { + if (argmodes[i] == PROARGMODE_OUT || argmodes[i] == PROARGMODE_INOUT || + argmodes[i] == PROARGMODE_TABLE) { + existOutParam = true; + break; + } + } + } + } + Form_pg_proc procstruct = (Form_pg_proc)GETSTRUCT(tp); + if (existOutParam && procstruct->proretset) { + ReleaseSysCache(tp); + return false; } + ReleaseSysCache(tp); return existOutParam; } diff --git a/src/common/backend/utils/gsplsql/gsdependencies.cpp b/src/common/backend/utils/gsplsql/gsdependencies.cpp index 25e9d7f3024297c91c6a78ed938600eac2d3769c..8e140fea5974248431084eced28983291d311cce 100644 --- a/src/common/backend/utils/gsplsql/gsdependencies.cpp +++ b/src/common/backend/utils/gsplsql/gsdependencies.cpp @@ -43,6 +43,7 @@ #include "catalog/pg_proc_fn.h" #include "parser/parse_type.h" #include "utils/lsyscache.h" +#include "storage/lock/lock.h" static void complete_process_variables(PLpgSQL_package* pkg, bool isCreate, bool isRecompile); static bool datumIsVariable(PLpgSQL_datum* datum); @@ -76,6 +77,142 @@ static bool gsplsql_exist_func_object_in_dependencies_obj(char* nsp_name, char* const char* old_func_head_name, const char* old_func_name); static bool gsplsql_exist_func_object_in_dependencies(char* nsp_name, char* pkg_name, const char* old_func_head_name); +void gsplsql_do_autonomous_compile(Oid objoid, bool is_pkg) +{ + if (u_sess->plsql_cxt.during_compile) { + return; + } + if (u_sess->plsql_cxt.is_exec_autonomous || u_sess->is_autonomous_session) { + return; + } + if (unlikely(g_instance.attr.attr_storage.max_concurrent_autonomous_transactions <= 0)) { + ereport(WARNING, (errcode(ERRCODE_PLPGSQL_ERROR), + errmsg("The %s cannot be %s.", "compile function/package operator", "called in autonomous transaction"), + errdetail("The value of max_concurrent_autonomous_transactions must be greater than 0."), + errcause("%s depends on autonomous transaction.", "compile invalid function/package in dml"), + erraction("set max_concurrent_autonomous_transactions to a large value."))); + return; + } + bool pushed = SPI_push_conditional(); + MemoryContext tmp_context = AllocSetContextCreate(u_sess->temp_mem_cxt, + "autonomous compile tmp context", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + MemoryContext old_cxt = MemoryContextSwitchTo(tmp_context); + ResourceOwner old_owner = t_thrd.utils_cxt.CurrentResourceOwner; + + /* release lock for compiled object */ + bool found = false; + GSPLSQLLockedObjKey key; + if (is_pkg) { + key = {1, objoid, u_sess->proc_cxt.MyDatabaseId}; + } else { + key = {0, objoid, u_sess->proc_cxt.MyDatabaseId}; + } + GSPLSQLLockedObjEntry* entry = NULL; + if (u_sess->plsql_cxt.plpgsql_lock_objects) { + entry = (GSPLSQLLockedObjEntry*)hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, &key, HASH_FIND, &found); + if (found && entry->has_locked) { + if (!is_pkg) { + UnlockProcedureIdForSession(objoid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + } else { + UnlockPackageIdForSession(objoid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + } + entry->has_locked = false; + } + } + + StringInfoData str; + char* pkg_name = NULL; + char* proc_name = NULL; + char* obj_type = NULL; + char* schema_name = NULL; + initStringInfo(&str); + appendStringInfoString(&str, + "declare\n" + "PRAGMA AUTONOMOUS_TRANSACTION;\n" + "begin\n"); + /* check guc value*/ + appendStringInfo(&str, "set %s=%s;\n", "behavior_compat_options", "\'plpgsql_dependency\'"); + + if (is_pkg) { + schema_name = GetPackageSchemaName(objoid); + obj_type = "package"; + pkg_name = GetPackageName(objoid); + appendStringInfo(&str, "alter %s %s.%s ", obj_type, schema_name, quote_identifier(pkg_name)); + } else { + char res = get_func_prokind(objoid); + if (PROC_IS_PRO(res)) { + obj_type = "procedure"; + } else if (PROC_IS_FUNC(res)) { + obj_type = "function"; + } else { + ereport(WARNING, (errcode(ERRCODE_PLPGSQL_ERROR), + errmsg("get wrong func type by func oid %u", objoid))); + } + schema_name = get_namespace_name(get_func_namespace(objoid)); + proc_name = format_procedure_no_visible(objoid); + appendStringInfo(&str, "alter %s %s.%s ", obj_type, schema_name, proc_name); + } + appendStringInfoString(&str, "compile;\n"); + appendStringInfoString(&str, "end;"); + + int save_compile_status = getCompileStatus(); + List* save_compile_list = u_sess->plsql_cxt.compile_context_list; + PLpgSQL_compile_context* save_compile_context = u_sess->plsql_cxt.curr_compile_context; + u_sess->plsql_cxt.during_compile = true; + PG_TRY(); + { + List* raw_parse_list = raw_parser(str.data, NULL); + DoStmt* stmt = (DoStmt*)linitial(raw_parse_list); + (void)CompileStatusSwtichTo(NONE_STATUS); + u_sess->plsql_cxt.curr_compile_context = NULL; + u_sess->plsql_cxt.compile_context_list = NULL; + ExecuteDoStmt(stmt, true); + t_thrd.utils_cxt.CurrentResourceOwner = old_owner; + } + PG_CATCH(); + { + (void)CompileStatusSwtichTo(save_compile_status); + u_sess->plsql_cxt.curr_compile_context = save_compile_context; + u_sess->plsql_cxt.compile_context_list = save_compile_list; + u_sess->plsql_cxt.during_compile = false; + MemoryContextSwitchTo(old_cxt); + t_thrd.utils_cxt.CurrentResourceOwner = old_owner; + + ErrorData* errdata = CopyErrorData(); + FlushErrorState(); + ereport(ERROR, (errcode(ERRCODE_PLPGSQL_ERROR), + errmsg("Executed %s %s is invalid, and do compile ddl %s.", obj_type, + is_pkg ? pkg_name : proc_name, str.data), + errdetail("COMPLIE fail reason: (%s,%d) %s.", errdata->funcname, + errdata->lineno, errdata->message), + erraction("Please call ALTER PACKAGE/FUNCTION COMPILE to validate %s %s.", + obj_type, is_pkg ? pkg_name : proc_name))); + } + PG_END_TRY(); + (void)CompileStatusSwtichTo(save_compile_status); + u_sess->plsql_cxt.curr_compile_context = save_compile_context; + u_sess->plsql_cxt.compile_context_list = save_compile_list; + u_sess->plsql_cxt.during_compile = false; + MemoryContextSwitchTo(old_cxt); + MemoryContextDelete(tmp_context); + SPI_pop_conditional(pushed); + /* hold lock again */ + if (u_sess->plsql_cxt.plpgsql_lock_objects) { + entry = (GSPLSQLLockedObjEntry*)hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, &key, HASH_FIND, &found); + if (found && !entry->has_locked) { + if (!is_pkg) { + LockProcedureIdForSession(objoid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + } else { + LockPackageIdForSession(objoid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + } + entry->has_locked = true; + } + } +} + bool gsplsql_exists_func_obj(Oid nsp_oid, Oid pkg_oid, const char* old_func_head_name, const char* old_func_name) { char* nsp_name = get_namespace_name(nsp_oid); @@ -1094,6 +1231,12 @@ void gsplsql_prepare_gs_depend_for_pkg_compile(PLpgSQL_package* pkg, bool isCrea GSDEPEND_OBJECT_TYPE_INVALID, isCreate ? GSDEPEND_REFOBJ_POS_IN_PKGALL_OBJ : GSDEPEND_REFOBJ_POS_IN_PKGRECOMPILE_OBJ }; + NameData schema_name_data; + NameData pkg_name_data; + StringInfoData object_name_data; + gsplsql_construct_non_empty_obj(&obj_desc, &schema_name_data, &pkg_name_data, &object_name_data); + uint32 hash_value = string_hash(object_name_data.data, object_name_data.len); + LockDatabaseObject(DependenciesRelationId, hash_value, 0, AccessExclusiveLock); pkg->preRefObjectOidList = gsplsql_delete_objs(relation, &obj_desc); heap_close(relation, RowExclusiveLock); pkg->preSelfObjectList = gsplsql_get_depend_obj_list_by_specified_pkg(schema_name, pkg->pkg_signature, diff --git a/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp b/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp index 7a0dec7fa9e60e9e828de0b94fad5a3b0c111194..c0a57548bc35b7b32590e574efb64634dde756a0 100644 --- a/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp +++ b/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp @@ -300,7 +300,7 @@ Oid gsplsql_get_proc_oid(const char* schemaName, const char* packageName, const } ReleaseSysCacheList(catlist); FreeStringInfo(&procNameStr); - ereport(ERROR, (errmodule(MOD_PLSQL), errmsg("function %s does not exist", name))); + ereport(WARNING, (errmodule(MOD_PLSQL), errmsg("function %s does not exist", name))); return InvalidOid; } @@ -347,7 +347,7 @@ Oid gsplsql_get_proc_oid(const char* schemaName, const char* packageName, const } } ReleaseSysCacheList(catlist); - ereport(ERROR, (errmodule(MOD_PLSQL), errmsg("function %s does not exist", name))); + ereport(WARNING, (errmodule(MOD_PLSQL), errmsg("function %s does not exist", name))); return InvalidOid; } diff --git a/src/common/backend/utils/init/globals.cpp b/src/common/backend/utils/init/globals.cpp index a0fe847ecd7edc2ad5488f3356c3af60b2defa2e..3092695bff12509ccdd8e83f4887ceb550d732d3 100644 --- a/src/common/backend/utils/init/globals.cpp +++ b/src/common/backend/utils/init/globals.cpp @@ -75,12 +75,13 @@ bool will_shutdown = false; * NEXT | 92899 | ? | ? * ********************************************/ -const uint32 GRAND_VERSION_NUM = 92926; +const uint32 GRAND_VERSION_NUM = 92928; /******************************************** * 2.VERSION NUM FOR EACH FEATURE * Please write indescending order. ********************************************/ +const uint32 PRIOR_EXPR_VERSION_NUM = 92928; const uint32 PUBLICATION_DDL_VERSION_NUM = 92921; const uint32 UPSERT_ALIAS_VERSION_NUM = 92920; const uint32 SUPPORT_GS_DEPENDENCY_VERSION_NUM = 92916; diff --git a/src/common/backend/utils/init/postinit.cpp b/src/common/backend/utils/init/postinit.cpp index 590d4ff63d20c8941d4a881a9b0342bf9526dac9..fa9642a3ab1ec0d95b221028532699b694ff86fa 100644 --- a/src/common/backend/utils/init/postinit.cpp +++ b/src/common/backend/utils/init/postinit.cpp @@ -403,7 +403,7 @@ static void SetEncordingInfo(Form_pg_database dbform, char* collate, char* ctype collate = NameStr(dbform->datcollate); ctype = NameStr(dbform->datctype); - if (pg_perm_setlocale(LC_COLLATE, collate) == NULL) { + if (gs_perm_setlocale_r(LC_COLLATE, collate) == NULL) { ereport(FATAL, (errmsg("database locale is incompatible with operating system"), errdetail("The database was initialized with LC_COLLATE \"%s\", " @@ -412,7 +412,7 @@ static void SetEncordingInfo(Form_pg_database dbform, char* collate, char* ctype errhint("Recreate the database with another locale or install the missing locale."))); } - if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL) { + if (gs_perm_setlocale_r(LC_CTYPE, ctype) == NULL) { ereport(FATAL, (errmsg("database locale is incompatible with operating system"), errdetail("The database was initialized with LC_CTYPE \"%s\", " @@ -425,10 +425,11 @@ static void SetEncordingInfo(Form_pg_database dbform, char* collate, char* ctype SetConfigOption("lc_collate", collate, PGC_INTERNAL, PGC_S_OVERRIDE); SetConfigOption("lc_ctype", ctype, PGC_INTERNAL, PGC_S_OVERRIDE); - /* Use the right encoding in translated messages */ -#ifdef ENABLE_NLS - pg_bind_textdomain_codeset(textdomain(NULL)); -#endif + /* + * GNU gettext selects a default encoding for the messages it emits in a + * platform-specific manner; it uses the Windows ANSI code page on Windows + * and follows LC_CTYPE on other platforms. + */ } if (IS_THREAD_POOL_WORKER) { diff --git a/src/common/backend/utils/mb/mbutils.cpp b/src/common/backend/utils/mb/mbutils.cpp index 85663c196f1ee219c8d34bac1ccf333220109a9b..39df8aed77f3057d9f302827718e970168ee5f88 100644 --- a/src/common/backend/utils/mb/mbutils.cpp +++ b/src/common/backend/utils/mb/mbutils.cpp @@ -1148,6 +1148,39 @@ void SetDatabaseEncoding(int encoding) Assert(u_sess->mb_cxt.DatabaseEncoding->encoding == encoding); } +#if defined(ENABLE_NLS) +/* + * Make one bind_textdomain_codeset() call, translating a pg_enc to a gettext + * codeset. Fails for MULE_INTERNAL, an encoding unknown to gettext; can also + * fail for gettext-internal causes like out-of-memory. + */ +static bool +raw_pg_bind_textdomain_codeset(const char *domainname, int encoding) +{ + bool elog_ok = (CurrentMemoryContext != NULL); + int i; + + for (i = 0; pg_enc2gettext_tbl[i].name != NULL; i++) + { + if (pg_enc2gettext_tbl[i].encoding == encoding) + { + if (bind_textdomain_codeset(domainname, + pg_enc2gettext_tbl[i].name) != NULL) + return true; + + if (elog_ok) + elog(LOG, "bind_textdomain_codeset failed"); + else + write_stderr("bind_textdomain_codeset failed"); + + break; + } + } + + return false; +} +#endif + /* * Bind gettext to the codeset equivalent with the database encoding. */ @@ -1168,27 +1201,17 @@ void pg_bind_textdomain_codeset(const char* domain_name) * it. */ #ifndef WIN32 - /* setlocale is thread-unsafe */ - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); - const char* ctype = gs_setlocale_r(LC_CTYPE, NULL); - - if (pg_strcasecmp(ctype, "C") != 0 && pg_strcasecmp(ctype, "POSIX") != 0) { - localeLock.unLock(); - return; - } + const char* ctype = gs_perm_setlocale_r(LC_CTYPE, NULL); - localeLock.unLock(); + /* + * XXX: If LC_CTYPE is C/POSIX, and database's encoding is not PG_SQL_ASCII, + * bind_textdomain_codeset() modify the server's codeset, which is not right. + * However, we can't handle this situation under multi-threading architecture. + */ + if (ctype && (pg_strcasecmp(ctype, "C") == 0 || pg_strcasecmp(ctype, "POSIX") == 0)) #endif - - for (i = 0; pg_enc2gettext_tbl[i].name != NULL; i++) { - if (pg_enc2gettext_tbl[i].encoding == encoding) { - if (bind_textdomain_codeset(domain_name, pg_enc2gettext_tbl[i].name) == NULL) { - ereport(LOG, (errmsg("bind_textdomain_codeset failed"))); - } - break; - } - } + if (encoding != PG_SQL_ASCII) + raw_pg_bind_textdomain_codeset(domain, encoding); #endif } @@ -1218,7 +1241,7 @@ const char* GetCharsetConnectionName(void) Oid GetCollationConnection(void) { - if (!ENABLE_MULTI_CHARSET) { + if (!ENABLE_MULTI_CHARSET || !DB_IS_CMPT(B_FORMAT)) { return InvalidOid; } return u_sess->mb_cxt.collation_connection; @@ -1241,11 +1264,8 @@ int GetPlatformEncoding(void) if (u_sess->mb_cxt.PlatformEncoding == NULL) { int encoding; - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); /* try to determine encoding of server's environment locale */ encoding = pg_get_encoding_from_locale("", true); - localeLock.unLock(); if (encoding < 0) { encoding = PG_SQL_ASCII; diff --git a/src/common/backend/utils/misc/guc.cpp b/src/common/backend/utils/misc/guc.cpp index 941fd7bf51f477931da3d7134abf2db22848f516..c91cc42678b98fbb6dd3c1cc24056a3384acba20 100755 --- a/src/common/backend/utils/misc/guc.cpp +++ b/src/common/backend/utils/misc/guc.cpp @@ -5334,10 +5334,6 @@ void InitializePostmasterGUC() #endif g_instance.attr.attr_network.PoolerPort = g_instance.attr.attr_network.PostPortNumber + 1; parseDmsInstanceCount(); -#ifndef USE_ASSERT_CHECKING - /* in Release, this param is ON and undisclosed */ - g_instance.attr.attr_storage.dms_attr.enable_reform = true; -#endif } /* diff --git a/src/common/backend/utils/misc/guc/guc_sql.cpp b/src/common/backend/utils/misc/guc/guc_sql.cpp index 1638943a3694e12d3b8836352108c84c90fcfcb0..a750be81c43ad665cf6640e6cce1574e3a0be553 100755 --- a/src/common/backend/utils/misc/guc/guc_sql.cpp +++ b/src/common/backend/utils/misc/guc/guc_sql.cpp @@ -390,7 +390,8 @@ static const struct behavior_compat_entry behavior_compat_options[OPT_MAX] = { {"select_into_return_null", OPT_SELECT_INTO_RETURN_NULL}, {"accept_empty_str", OPT_ACCEPT_EMPTY_STR}, {"plpgsql_dependency", OPT_PLPGSQL_DEPENDENCY}, - {"proc_uncheck_default_param", OPT_PROC_UNCHECK_DEFAULT_PARAM} + {"proc_uncheck_default_param", OPT_PROC_UNCHECK_DEFAULT_PARAM}, + {"update_unusable_unique_index_on_iud", OPT_UPDATE_UNUSABLE_UNIQUE_INDEX_ON_IUD} }; // increase SQL_IGNORE_STRATEGY_NUM if we need more strategy @@ -1204,6 +1205,18 @@ static void InitSqlConfigureNamesBool() NULL, NULL}, + {{"plan_cache_type_validation", + PGC_POSTMASTER, + NODE_ALL, + XC_HOUSEKEEPING_OPTIONS, + gettext_noop("Turns off pbe result type check: allow user to change the plan cache result on the fly."), + NULL}, + &g_instance.attr.attr_sql.plan_cache_type_validation, + true, + NULL, + NULL, + NULL}, + {{"lo_compat_privileges", PGC_SUSET, NODE_ALL, diff --git a/src/common/backend/utils/misc/guc/guc_storage.cpp b/src/common/backend/utils/misc/guc/guc_storage.cpp index e1e51df463ec7c4b05e6dd0244675f34ba50309a..bc39a2695e6e1955fa4483ea6dc4fef9a1a699d4 100755 --- a/src/common/backend/utils/misc/guc/guc_storage.cpp +++ b/src/common/backend/utils/misc/guc/guc_storage.cpp @@ -1134,20 +1134,6 @@ static void InitStorageConfigureNamesBool() NULL, NULL, NULL}, -#ifdef USE_ASSERT_CHECKING - {{"ss_enable_reform", - PGC_POSTMASTER, - NODE_SINGLENODE, - SHARED_STORAGE_OPTIONS, - gettext_noop("Whether use dms reform"), - NULL, - GUC_SUPERUSER_ONLY}, - &g_instance.attr.attr_storage.dms_attr.enable_reform, - true, - NULL, - NULL, - NULL}, -#endif {{"ss_enable_ssl", PGC_POSTMASTER, NODE_SINGLENODE, @@ -1368,6 +1354,17 @@ static void InitStorageConfigureNamesBool() NULL, NULL}, /* End-of-list marker */ + {{"handle_toast_in_autovac", + PGC_SIGHUP, + NODE_ALL, + AUTOVACUUM, + gettext_noop("Set whether toast needs to be processed in autovacuum."), + NULL}, + &u_sess->attr.attr_storage.handle_toast_in_autovac, + false, + NULL, + NULL, + NULL}, {{NULL, (GucContext)0, (GucNodeType)0, diff --git a/src/common/backend/utils/misc/pg_controldata.cpp b/src/common/backend/utils/misc/pg_controldata.cpp index 63435a47e5224b5ec4baaca1b725b0f4e7f70e1d..9ebca45a4e803284d466b068496876f8fb4379e7 100644 --- a/src/common/backend/utils/misc/pg_controldata.cpp +++ b/src/common/backend/utils/misc/pg_controldata.cpp @@ -134,16 +134,16 @@ static void OpenControlFileForDSS(char *controlFilePath, ControlFileData *contro while (true) { if (pread(fd, buffer, read_size, seekpos) != read_size) { LWLockRelease(ControlFileLock); - ereport(ERROR, (errcode_for_file_access(), errmsg("could not read from control file %s : %s"), fileName, - TRANSLATE_ERRNO)); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not read from control file %s : %s", fileName, + TRANSLATE_ERRNO))); } rc = memcpy_s(controlFile, (size_t)len, buffer, (size_t)len); securec_check(rc, "", ""); if (close(fd) < 0) { LWLockRelease(ControlFileLock); - ereport(ERROR, (errcode_for_file_access(), errmsg("could not close control file %s : %s"), fileName, - TRANSLATE_ERRNO)); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not close control file %s : %s", fileName, + TRANSLATE_ERRNO))); } /* Now check the CRC. */ diff --git a/src/common/backend/utils/sort/tuplesort.cpp b/src/common/backend/utils/sort/tuplesort.cpp index eb818ee0b71d416dc8e31c6b3e42058f01688503..81b7b9887eb66e6a6e7bace7cb0b3ea6dc7f4445 100644 --- a/src/common/backend/utils/sort/tuplesort.cpp +++ b/src/common/backend/utils/sort/tuplesort.cpp @@ -3411,7 +3411,6 @@ static void* readtup_alloc(Tuplesortstate *state, Size tuplen) * We pre-allocate enough slots in the slab arena that we should never run * out. */ - Assert(state->slabFreeHead); if (tuplen > SLAB_SLOT_SIZE || !state->slabFreeHead) { return MemoryContextAlloc(state->sortcontext, tuplen); diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index c60d7b225d82d940f20f1b9fbf7bded343399a2e..3600c43ca107d0418025f68b65322c0b016f7490 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -354,7 +354,7 @@ static void processFunctionRecordOutParam(int varno, Oid funcoid, int* outparam) %type decl_varname_list %type decl_const decl_notnull exit_type %type decl_defval decl_rec_defval decl_cursor_query -%type decl_datatype +%type decl_datatype opt_cursor_returntype %type decl_collate %type decl_cursor_args %type decl_cursor_arglist assign_list @@ -1355,7 +1355,7 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no pfree_ext($2->name); pfree($2); } - | K_TYPE decl_varname as_is K_REF K_CURSOR ';' + | K_TYPE decl_varname as_is K_REF K_CURSOR opt_cursor_returntype ';' { IsInPublicNamespace($2->name); /* add name of cursor type to PLPGSQL_NSTYPE_REFCURSOR */ @@ -1983,22 +1983,28 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no | K_FUNCTION {u_sess->parser_cxt.is_procedure=false;} spec_proc { DefElem *def = $3; + bool oldisCreateFunction = u_sess->plsql_cxt.isCreateFunction; u_sess->plsql_cxt.procedure_start_line = GetLineNumber(u_sess->plsql_cxt.curr_compile_context->core_yy->scanbuf, @1); u_sess->plsql_cxt.plpgsql_yylloc = @1; u_sess->plsql_cxt.isCreateFunction = true; + set_is_create_pkg_function(true); raw_parse_package_function(def->defname, def->location, def->begin_location); - u_sess->plsql_cxt.isCreateFunction = false; + set_is_create_pkg_function(false); + u_sess->plsql_cxt.isCreateFunction = oldisCreateFunction; u_sess->plsql_cxt.procedure_start_line = 0; u_sess->plsql_cxt.plpgsql_yylloc = 0; } | K_PROCEDURE {u_sess->parser_cxt.is_procedure=true;} spec_proc { DefElem *def = $3; + bool oldisCreateFunction = u_sess->plsql_cxt.isCreateFunction; u_sess->plsql_cxt.procedure_start_line = GetLineNumber(u_sess->plsql_cxt.curr_compile_context->core_yy->scanbuf, @1); u_sess->plsql_cxt.plpgsql_yylloc = plpgsql_yylloc; u_sess->plsql_cxt.isCreateFunction = true; + set_is_create_pkg_function(true); raw_parse_package_function(def->defname, def->location, def->begin_location); - u_sess->plsql_cxt.isCreateFunction = false; + set_is_create_pkg_function(false); + u_sess->plsql_cxt.isCreateFunction = oldisCreateFunction; u_sess->plsql_cxt.procedure_start_line = 0; u_sess->plsql_cxt.plpgsql_yylloc = 0; } @@ -2341,6 +2347,31 @@ cursor_in_out_option : K_IN | /* empty */ ; +opt_cursor_returntype: /* empty */ + { + $$ = NULL; + } + | K_RETURN decl_datatype + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + const char* message = "cursor return type is only supposed in A compatibility"; + InsertErrorMessage(message, plpgsql_yylloc); + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("cursor return type is only supposed in A compatibility"))); + } + if ($2->dtype != PLPGSQL_DTYPE_RECORD_TYPE && $2->typinput.fn_oid != F_RECORD_IN) { + const char* message = "invalid cursor return type"; + InsertErrorMessage(message, plpgsql_yylloc); + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid cursor return type; %s must be a record type", $2->typname))); + } + $$ = $2; + } + ; + + decl_is_for : K_IS | /* A db */ K_FOR; /* SQL standard */ @@ -9739,13 +9770,6 @@ read_datatype(int tok) if (result) return result; } - } else { - if (tok == ';') { - PLpgSQL_datum* datum = GetPackageDatum(dtnames); - if (datum != NULL && datum->dtype == PLPGSQL_DTYPE_RECORD_TYPE) { - check_record_type((PLpgSQL_rec_type*)datum, yylloc, false); - } - } } } @@ -10346,6 +10370,18 @@ make_execsql_stmt(int firsttoken, int location) if (i != (nattr - 1)) { appendStringInfoString(&ds, ","); } + PLpgSQL_recfield* rec_field = NULL; + rec_field = (PLpgSQL_recfield*)palloc0(sizeof(PLpgSQL_recfield)); + rec_field->dtype = PLPGSQL_DTYPE_RECFIELD; + rec_field->fieldname = pstrdup(NameStr(pg_att_form->attname)); + + int nnames = 0; + PLpgSQL_nsitem* ns = plpgsql_ns_lookup(plpgsql_ns_top(), false, rec_data->refname, NameStr(pg_att_form->attname), NULL, &nnames); + if (ns == NULL) { + yyerror("insert an nonexistent variable"); + } + rec_field->recparentno = ns->itemno; + (void)plpgsql_adddatum((PLpgSQL_datum*)rec_field); } } appendStringInfoString(&ds, ")"); diff --git a/src/common/pl/plpgsql/src/pl_comp.cpp b/src/common/pl/plpgsql/src/pl_comp.cpp index ef35f53b9e8f0c97dcfc4174bf244e605dce0729..4500725d25071dc114438e8324f1c3d5cb73a8da 100644 --- a/src/common/pl/plpgsql/src/pl_comp.cpp +++ b/src/common/pl/plpgsql/src/pl_comp.cpp @@ -52,6 +52,8 @@ #include "catalog/gs_dependencies_fn.h" #include "catalog/pg_object.h" #include "catalog/pg_type_fn.h" +#include "storage/lmgr.h" +#include "access/hash.h" /* functions reference other modules */ extern THR_LOCAL List* baseSearchPath; @@ -170,7 +172,17 @@ PLpgSQL_function* plpgsql_compile(FunctionCallInfo fcinfo, bool for_validator, b if (!func_valid) { fcinfo->flinfo->fn_extra = NULL; } + if (!func_valid && !u_sess->plsql_cxt.need_create_depend && !isRecompile) { + if (!OidIsValid(packageOid)) { + gsplsql_do_autonomous_compile(func_oid, false); + } + } } + +#ifndef ENABLE_MULTIPLE_NODES + /* Locking is performed before compilation. */ + gsplsql_lock_func_pkg_dependency_all(func_oid, PLSQL_FUNCTION_OBJ); +#endif recheck: if (func == NULL) { @@ -971,10 +983,11 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup, * directly to it. If there's more than one, build a row that * holds all of them. */ - if (num_out_args == 1 && !is_function_with_plpgsql_language_and_outparam(func->fn_oid)) { + func->is_plpgsql_func_with_outparam = is_function_with_plpgsql_language_and_outparam(func->fn_oid); + if (num_out_args == 1 && !func->is_plpgsql_func_with_outparam) { func->out_param_varno = out_arg_variables[0]->dno; } else if (num_out_args > 1 || (num_out_args == 1 && - is_function_with_plpgsql_language_and_outparam(func->fn_oid))) { + func->is_plpgsql_func_with_outparam)) { PLpgSQL_row* row = build_row_from_vars(out_arg_variables, num_out_args); row->isImplicit = true; @@ -5286,3 +5299,176 @@ Node* plpgsql_check_match_var(Node* node, ParseState* pstate, ColumnRef* cref) } return ans; } + +static uint32 gsplsql_lock_obj_hash_code(const void* key, Size size) +{ + const GSPLSQLLockedObjKey* k = (const GSPLSQLLockedObjKey*)key; + return hash_uint32((uint32)k->objId) ^ hash_uint32((uint32)k->dbId) ^ hash_uint32((uint32)k->isPkg); +} + +static int gsplsql_lock_obj_compare(const void* a, const void* b, Size keysize) +{ + const GSPLSQLLockedObjKey* left = (const GSPLSQLLockedObjKey*)a; + const GSPLSQLLockedObjKey* right = (const GSPLSQLLockedObjKey*)b; + if (left->isPkg == right->isPkg && left->objId == right->objId && + left->dbId == right->dbId) { + return 0; + } + return 1; +} + +void init_lock_hash_table() +{ + if (u_sess->plsql_cxt.plpgsql_lock_objects != NULL) { + return; + } + HASHCTL ctl; + errno_t rc = EOK; + rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); + securec_check(rc, "\0", "\0"); + ctl.keysize = sizeof(GSPLSQLLockedObjKey); + ctl.entrysize = sizeof(GSPLSQLLockedObjEntry); + ctl.hash = gsplsql_lock_obj_hash_code; + ctl.match = gsplsql_lock_obj_compare; + ctl.hcxt = SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER); + u_sess->plsql_cxt.plpgsql_lock_objects = hash_create( + "GSPLSQL locked object", GSPLSQL_LOCKED_HTAB_SIZE, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); +} + +/* In-depth traversal: Add a read lock to the object on which the package depends */ +void gsplsql_lock_func_pkg_dependency_all(Oid obj_oid, GSPLSQLObjectType type) +{ + if (u_sess->plsql_cxt.isCreateFunction || u_sess->plsql_cxt.isCreatePkg || + u_sess->plsql_cxt.is_alter_compile_stmt || u_sess->plsql_cxt.during_compile) { + return; + } + /* Only lock valid Oid and non-builtin function*/ + if (!OidIsValid(obj_oid) || obj_oid < (Oid)FirstBootstrapObjectId) { + return; + } + MemoryContext oldcxt = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER)); + if (unlikely(u_sess->plsql_cxt.plpgsql_lock_objects == NULL)) { + init_lock_hash_table(); + } + bool found = false; + GSPLSQLLockedObjKey key; + if (type == PLSQL_FUNCTION_OBJ) { + key = {0, obj_oid, u_sess->proc_cxt.MyDatabaseId}; + } else { + key = {1, obj_oid, u_sess->proc_cxt.MyDatabaseId}; + } + GSPLSQLLockedObjEntry* entry = (GSPLSQLLockedObjEntry*)hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, + &key, HASH_ENTER, &found); + if (!found || !entry->has_locked) { + entry->has_locked = false; + if (type == PLSQL_FUNCTION_OBJ) { + LockProcedureIdForSession(obj_oid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + } else { + LockPackageIdForSession(obj_oid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + } + entry->has_locked = true; + } + /* Lock the dependent object of pkg */ + if (type != PLSQL_PACKAGE_OBJ) { + (void)MemoryContextSwitchTo(oldcxt); + return; + } + PLpgSQL_pkg_hashkey hashkey; + ListCell* lc = NULL; + hashkey.pkgOid = obj_oid; + PLpgSQL_package* pkg = plpgsql_pkg_HashTableLookup(&hashkey); + if (pkg == NULL) { + (void)MemoryContextSwitchTo(oldcxt); + return; + } + foreach(lc, pkg->invalItems) { + FuncInvalItem* item = (FuncInvalItem*)lfirst(lc); + if (unlikely((item->cacheId != PACKAGEOID))) { + continue; + } + key = {1, item->objId, item->dbId}; + entry = (GSPLSQLLockedObjEntry*)hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, + &key, HASH_ENTER, &found); + if (!found || !entry->has_locked) { + entry->has_locked = false; + LockPackageIdForSession(item->objId, item->dbId, AccessShareLock); + entry->has_locked = true; + } + } + (void)MemoryContextSwitchTo(oldcxt); +} + +void gsplsql_unlock_func_pkg_dependency_all() +{ + if (u_sess->SPI_cxt._connected > 0 || u_sess->plsql_cxt.plpgsql_lock_objects == NULL || + hash_get_num_entries(u_sess->plsql_cxt.plpgsql_lock_objects) == 0) { + return; + } + HASH_SEQ_STATUS status; + GSPLSQLLockedObjEntry *hentry = NULL; + hash_seq_init(&status, u_sess->plsql_cxt.plpgsql_lock_objects); + while ((hentry = (GSPLSQLLockedObjEntry *) hash_seq_search(&status)) != NULL) { + if (hentry->has_locked) { + if (hentry->key.isPkg == 1) { + UnlockPackageIdForSession(hentry->key.objId, hentry->key.dbId, AccessShareLock); + } else { + UnlockProcedureIdForSession(hentry->key.objId, hentry->key.dbId, AccessShareLock); + } + } + hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, &hentry->key, HASH_REMOVE, NULL); + } +} + +void gsplsql_lock_depend_pkg_on_session(PLpgSQL_function* func) +{ + if (func == NULL) { + return; + } + /* Only lock valid Oid and non-builtin function*/ + if (!OidIsValid(func->fn_oid) || func->fn_oid < (Oid)FirstBootstrapObjectId) { + return; + } + MemoryContext oldcxt = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER)); + if (unlikely(u_sess->plsql_cxt.plpgsql_lock_objects == NULL)) { + init_lock_hash_table(); + } + bool found = false; + GSPLSQLLockedObjKey key; + GSPLSQLLockedObjEntry* entry = NULL; + key = {0, func->fn_oid, u_sess->proc_cxt.MyDatabaseId}; + entry = (GSPLSQLLockedObjEntry*)hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, + &key, HASH_ENTER, &found); + if (!found || !entry->has_locked) { + entry->has_locked = false; + LockProcedureIdForSession(func->fn_oid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + entry->has_locked = true; + } + if (OidIsValid(func->pkg_oid)) { + found = false; + key = {1, func->pkg_oid, u_sess->proc_cxt.MyDatabaseId}; + entry = (GSPLSQLLockedObjEntry*)hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, + &key, HASH_ENTER, &found); + if (!found || !entry->has_locked) { + entry->has_locked = false; + LockPackageIdForSession(func->pkg_oid, u_sess->proc_cxt.MyDatabaseId, AccessShareLock); + entry->has_locked = true; + } + } + List* invalItems = func->invalItems; + ListCell* lc = NULL; + foreach(lc, invalItems) { + FuncInvalItem* item = (FuncInvalItem*)lfirst(lc); + if (unlikely((item->cacheId != PACKAGEOID))) { + continue; + } + key = {1, item->objId, item->dbId}; + entry = (GSPLSQLLockedObjEntry*)hash_search(u_sess->plsql_cxt.plpgsql_lock_objects, + &key, HASH_ENTER, &found); + if (!found || !entry->has_locked) { + entry->has_locked = false; + LockPackageIdForSession(item->objId, item->dbId, AccessShareLock); + entry->has_locked = true; + } + } + (void)MemoryContextSwitchTo(oldcxt); +} \ No newline at end of file diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index c275b96920b8fdd61055bd3ac6f3ff5e8ab6c8d3..2d7672b78cf97d4df71a874fd5799ea38bbe42fb 100644 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -1419,7 +1419,7 @@ Datum plpgsql_exec_function(PLpgSQL_function* func, errmodule(MOD_PLSQL), errmsg("Mismatch between function parameter number [%d:%d].", func->fn_nargs, fcinfo->nargs))); } - bool is_plpgsql_function_with_outparam = is_function_with_plpgsql_language_and_outparam(func->fn_oid); + bool is_plpgsql_function_with_outparam = func->is_plpgsql_func_with_outparam; if (func->fn_nargs != fcinfo->nargs && is_plpgsql_function_with_outparam) { procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(func->fn_oid)); proArgModes = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargmodes, &isNULL); @@ -1929,7 +1929,11 @@ HeapTuple plpgsql_exec_trigger(PLpgSQL_function* func, TriggerData* trigdata) */ estate.err_text = gettext_noop("during initialization of execution state"); for (i = 0; i < estate.ndatums; i++) { - estate.datums[i] = copy_plpgsql_datum(func->datums[i]); + if (!func->datums[i]->ispkg) { + estate.datums[i] = copy_plpgsql_datum(func->datums[i]); + } else { + estate.datums[i] = func->datums[i]; + } } /* @@ -5948,8 +5952,7 @@ static int exec_stmt_return(PLpgSQL_execstate* estate, PLpgSQL_stmt_return* stmt return PLPGSQL_RC_RETURN; } - bool needParamSeperation = estate->func->is_plpgsql_func_with_outparam && - ((estate->func->guc_stat & OPT_PROC_OUTPARAM_OVERRIDE) != 0); + bool needParamSeperation = estate->func->is_plpgsql_func_with_outparam; if (needParamSeperation && stmt->expr == NULL) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmodule(MOD_PLSQL), errmsg("Value assignment for the out parameter in plpgsql language functions, Unsupported " @@ -9081,6 +9084,8 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v bool* nulls = NULL; bool* replaces = NULL; bool attisnull = false; + MemoryContext temp = NULL; + MemoryContext target_cxt = NULL; Oid atttype; int32 atttypmod; errno_t rc = EOK; @@ -9142,8 +9147,10 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v * Now call heap_modify_tuple() to create a new tuple that * replaces the old one in the record. */ + target_cxt = rec->ispkg ? rec->pkg->pkg_cxt : CurrentMemoryContext; + temp = MemoryContextSwitchTo(target_cxt); newtup = heap_modify_tuple(rec->tup, rec->tupdesc, values, nulls, replaces); - + temp = MemoryContextSwitchTo(temp); if (rec->freetup) { heap_freetuple_ext(rec->tup); } diff --git a/src/common/pl/plpgsql/src/pl_handler.cpp b/src/common/pl/plpgsql/src/pl_handler.cpp index ccc5c14343726d2759ef94af4b62ddde22bc0ee2..4f86628fd01dba862b785a5d2891f7b5ef43b13b 100755 --- a/src/common/pl/plpgsql/src/pl_handler.cpp +++ b/src/common/pl/plpgsql/src/pl_handler.cpp @@ -816,6 +816,9 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS) bool save_need_create_depend = u_sess->plsql_cxt.need_create_depend; u_sess->plsql_cxt.need_create_depend = false; + if (u_sess->SPI_cxt._connected == -1) { + plpgsql_hashtable_clear_invalid_obj(); + } _PG_init(); /* @@ -864,7 +867,8 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS) #endif int connect = SPI_connectid(); Oid firstLevelPkgOid = InvalidOid; - bool save_curr_status = GetCurrCompilePgObjStatus(); + bool save_curr_status = GetCurrCompilePgObjStatus(); + bool save_is_exec_autonomous = u_sess->plsql_cxt.is_exec_autonomous; PG_TRY(); { PGSTAT_START_PLSQL_TIME_RECORD(); @@ -899,7 +903,13 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS) if (func->fn_readonly) { stp_disable_xact_and_set_err_msg(&savedisAllowCommitRollback, STP_XACT_IMMUTABLE); } - func->is_plpgsql_func_with_outparam = is_function_with_plpgsql_language_and_outparam(func->fn_oid); + + bool guc_changed = ((u_sess->utils_cxt.behavior_compat_flags & OPT_PROC_OUTPARAM_OVERRIDE) != + (func->guc_stat & OPT_PROC_OUTPARAM_OVERRIDE)); + if (guc_changed) { + ereport(ERROR, (errcode(ERRCODE_PLPGSQL_ERROR), errmodule(MOD_PLSQL), + errmsg("Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session."))); + } restoreCallFromPkgOid(firstLevelPkgOid); @@ -1093,6 +1103,7 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS) { u_sess->plsql_cxt.need_create_depend = save_need_create_depend; SetCurrCompilePgObjStatus(save_curr_status); + u_sess->plsql_cxt.is_exec_autonomous = save_is_exec_autonomous; /* clean stp save pointer if the outermost function is end. */ if (u_sess->SPI_cxt._connected == 0) { t_thrd.utils_cxt.STPSavedResourceOwner = NULL; @@ -1101,6 +1112,7 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS) SetSendCommandId(saveSetSendCommandId); #else dopControl.ResetSmp(); + gsplsql_unlock_func_pkg_dependency_all(); #endif /* ErrorData could be allocted in SPI's MemoryContext, copy it. */ oldContext = MemoryContextSwitchTo(oldContext); @@ -1127,6 +1139,7 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS) SetSendCommandId(saveSetSendCommandId); #else dopControl.ResetSmp(); + gsplsql_unlock_func_pkg_dependency_all(); #endif /* @@ -1170,11 +1183,22 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) int rc; PGSTAT_INIT_TIME_RECORD(); bool needRecord = false; + Oid package_oid = InvalidOid; + if (u_sess->SPI_cxt._connected == -1) { + plpgsql_hashtable_clear_invalid_obj(); + } _PG_init(); AssertEreport(IsA(codeblock, InlineCodeBlock), MOD_PLSQL, "Inline code block is required."); + if (u_sess->plsql_cxt.curr_compile_context != NULL && + u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package != NULL) { + package_oid = u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_oid; +#ifndef ENABLE_MULTIPLE_NODES + gsplsql_lock_func_pkg_dependency_all(package_oid, PLSQL_PACKAGE_OBJ); +#endif + } /* * Connect to SPI manager */ @@ -1208,6 +1232,7 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) /* Compile the anonymous code block */ PLpgSQL_compile_context* save_compile_context = u_sess->plsql_cxt.curr_compile_context; + int save_compile_status = getCompileStatus(); PG_TRY(); { func = plpgsql_compile_inline(codeblock->source_text); @@ -1219,9 +1244,11 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) PG_CATCH(); { #ifndef ENABLE_MULTIPLE_NODES + gsplsql_unlock_func_pkg_dependency_all(); dopControl.ResetSmp(); #endif popToOldCompileContext(save_compile_context); + CompileStatusSwtichTo(save_compile_status); PG_RE_THROW(); } PG_END_TRY(); @@ -1233,6 +1260,9 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) /* Mark the function as busy, just pro forma */ func->use_count++; +#ifndef ENABLE_MULTIPLE_NODES + gsplsql_lock_depend_pkg_on_session(func); +#endif /* * Set up a fake fcinfo with just enough info to satisfy * plpgsql_exec_function(). In particular note that this sets things up @@ -1250,7 +1280,7 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) /* save flag for nest plpgsql compile */ save_compile_context = u_sess->plsql_cxt.curr_compile_context; int save_compile_list_length = list_length(u_sess->plsql_cxt.compile_context_list); - int save_compile_status = u_sess->plsql_cxt.compile_status; + save_compile_status = u_sess->plsql_cxt.compile_status; DebugInfo* save_debug_info = func->debug; NodeTag old_node_tag = t_thrd.postgres_cxt.cur_command_tag; FormatCallStack* saveplcallstack = t_thrd.log_cxt.call_stack; @@ -1270,6 +1300,9 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) t_thrd.utils_cxt.STPSavedResourceOwner = NULL; } t_thrd.log_cxt.call_stack = saveplcallstack; +#ifndef ENABLE_MULTIPLE_NODES + gsplsql_unlock_func_pkg_dependency_all(); +#endif /* Decrement package use-count */ DecreasePackageUseCount(func); @@ -1302,6 +1335,9 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) SetSendCommandId(saveSetSendCommandId); #endif + if (u_sess->SPI_cxt._connected == 0) { + plpgsql_hashtable_clear_invalid_obj(); + } PG_RE_THROW(); } PG_END_TRY(); @@ -1329,6 +1365,7 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) #ifdef ENABLE_MULTIPLE_NODES SetSendCommandId(saveSetSendCommandId); #else + gsplsql_unlock_func_pkg_dependency_all(); dopControl.ResetSmp(); #endif @@ -1357,6 +1394,9 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) } else { plpgsql_free_function_memory(func); } + if (u_sess->SPI_cxt._connected == 0) { + plpgsql_hashtable_clear_invalid_obj(); + } /* * Disconnect from SPI manager @@ -1901,6 +1941,7 @@ void record_pkg_function_dependency(PLpgSQL_package* pkg, List** invalItems, Oid inval_item->cacheId = PACKAGEOID; inval_item->objId = pkgid; } + inval_item->dbId = u_sess->proc_cxt.MyDatabaseId; *invalItems = lappend(*invalItems, inval_item); } } diff --git a/src/common/pl/plpgsql/src/pl_package.cpp b/src/common/pl/plpgsql/src/pl_package.cpp index cd5772fffdc1c236110cd23d3e67ae3b7cfbf80a..170aff0c0bd70f794a1e9e04725dc02c788604bd 100644 --- a/src/common/pl/plpgsql/src/pl_package.cpp +++ b/src/common/pl/plpgsql/src/pl_package.cpp @@ -1136,8 +1136,17 @@ PLpgSQL_package* plpgsql_pkg_compile(Oid pkgOid, bool for_validator, bool isSpec } else { pkg_body_valid = GetPgObjectValid(pkgOid, OBJECT_TYPE_PKGBODY); } + if ((!pkg_body_valid || !pkg_spec_valid) && !u_sess->plsql_cxt.need_create_depend && !isRecompile) { + gsplsql_do_autonomous_compile(pkgOid, true); + } } } +#ifndef ENABLE_MULTIPLE_NODES + /* Locking is performed before compilation. */ + if (u_sess->SPI_cxt._connected >= 0) { + gsplsql_lock_func_pkg_dependency_all(pkgOid, PLSQL_PACKAGE_OBJ); + } +#endif pkg = plpgsql_pkg_HashTableLookup(&hashkey); if ((!pkg_body_valid || !pkg_spec_valid) && pkg != NULL && !u_sess->plsql_cxt.need_create_depend && u_sess->SPI_cxt._connected >= 0 && diff --git a/src/common/port/chklocale.cpp b/src/common/port/chklocale.cpp index 4b38e732e9c823f31b520ee3d57237dbab9c2e37..ff79e4d0edfdbebca93640d06b885b8ff11813d7 100644 --- a/src/common/port/chklocale.cpp +++ b/src/common/port/chklocale.cpp @@ -275,7 +275,7 @@ int pg_get_encoding_from_locale(const char* ctype, bool write_message) return PG_SQL_ASCII; } - save = gs_setlocale_r(LC_CTYPE, NULL); + save = gs_perm_setlocale_r(LC_CTYPE, NULL); if (save == NULL) { return -1; /* setlocale() broken, must copy result, or it might change after setlocale */ } @@ -288,7 +288,7 @@ int pg_get_encoding_from_locale(const char* ctype, bool write_message) return -1; /* out of memory; unlikely */ } - name = gs_setlocale_r(LC_CTYPE, ctype); + name = gs_perm_setlocale_r(LC_CTYPE, ctype); if (name == NULL) { #ifdef FRONTEND free(save); @@ -310,7 +310,7 @@ int pg_get_encoding_from_locale(const char* ctype, bool write_message) sys = win32_langinfo(name); #endif - (void)gs_setlocale_r(LC_CTYPE, save); + (void)gs_perm_setlocale_r(LC_CTYPE, save); #ifdef FRONTEND free(save); #else @@ -318,7 +318,7 @@ int pg_get_encoding_from_locale(const char* ctype, bool write_message) #endif } else { /* much easier... */ - ctype = gs_setlocale_r(LC_CTYPE, NULL); + ctype = gs_perm_setlocale_r(LC_CTYPE, NULL); if (ctype == NULL) { return -1; /* setlocale() broken? */ } @@ -404,49 +404,35 @@ int pg_get_encoding_from_locale(const char* ctype, bool write_message) } #ifndef WIN32 -char* gs_setlocale_r(int category, const char* locale) +char* gs_perm_setlocale_r(int category, const char* locale) { char* result = NULL; #ifdef FRONTEND result = setlocale(category, locale); #else - - if (!IsUnderPostmaster) { - // query locale not modify - result = setlocale(category, locale); - } else { - if (locale == NULL) { - if (t_thrd.port_cxt.save_locale_r != (locale_t)0) { - // get locale directly - result = gs_nl_langinfo_r(NL_LOCALE_NAME((unsigned int)category)); - } else { - // query locale not modify - result = setlocale(category, NULL); - } - } else { - int category_mask = 0; - - if (category == LC_ALL) { - category_mask = LC_ALL_MASK; - } else { - category_mask = (1 << (unsigned int)category); - } - - t_thrd.port_cxt.save_locale_r = newlocale(category_mask, locale, t_thrd.port_cxt.save_locale_r); - if (t_thrd.port_cxt.save_locale_r == (locale_t)0) { - return NULL; - } - - locale_t last_locale = uselocale(t_thrd.port_cxt.save_locale_r); - - if (last_locale == (locale_t)0) { - return NULL; - } - - result = (char*)locale; - } + if (locale) { + locale_t old_locale; + int category_mask = 0; + + if (category == LC_ALL) + category_mask = LC_ALL_MASK; + else + category_mask = (1 << (unsigned int)category); + + t_thrd.port_cxt.save_locale_r = newlocale(category_mask, locale, t_thrd.port_cxt.save_locale_r); + if (t_thrd.port_cxt.save_locale_r == (locale_t)0) + return NULL; + old_locale = uselocale(t_thrd.port_cxt.save_locale_r); + if (old_locale == (locale_t)0) + return NULL; +#ifdef ENABLE_NLS + /* Use the right encoding in translated messages. */ + if (LC_CTYPE == category) + pg_bind_textdomain_codeset(textdomain(NULL)); +#endif } + result = gs_nl_langinfo_r(NL_LOCALE_NAME((unsigned int)category)); #endif return result; @@ -466,7 +452,7 @@ char* gs_nl_langinfo_r(nl_item item) } #else -char* gs_setlocale_r(int category, const char* locale) +char* gs_perm_setlocale_r(int category, const char* locale) { return setlocale(category, locale); } diff --git a/src/common/port/exec.cpp b/src/common/port/exec.cpp index 008a9c985826098df0a0f43cd48c720e13dec5ee..f9a8934ef21b67145cbdb31004a6e6f7576aba90 100644 --- a/src/common/port/exec.cpp +++ b/src/common/port/exec.cpp @@ -574,7 +574,7 @@ void set_pglocale_pgservice(const char* argv0, const char* app) /* don't set LC_ALL in the backend */ if (strcmp(app, PG_TEXTDOMAIN("gaussdb")) != 0) { - (void)gs_setlocale_r(LC_ALL, ""); + (void)setlocale(LC_ALL, ""); } if (find_my_exec(argv0, my_exec_path) < 0) { diff --git a/src/common/port/win32setlocale.cpp b/src/common/port/win32setlocale.cpp index 0b26d012d4ee817b8c189f5391a4a42ed12c0aa8..9fba20296d0bc013ad6c7052d63b5d82228ec9fd 100644 --- a/src/common/port/win32setlocale.cpp +++ b/src/common/port/win32setlocale.cpp @@ -69,7 +69,7 @@ char* pgwin32_setlocale(int category, const char* locale) errno_t rc; if (locale == NULL) { - return gs_setlocale_r(category, locale); + return gs_perm_setlocale_r(category, locale); } /* Check if the locale name matches any of the problematic ones. */ @@ -124,11 +124,11 @@ char* pgwin32_setlocale(int category, const char* locale) /* Call the real setlocale() function */ if (alias != NULL) { - result = gs_setlocale_r(category, alias); + result = gs_perm_setlocale_r(category, alias); free(alias); alias = NULL; } else { - result = gs_setlocale_r(category, locale); + result = gs_perm_setlocale_r(category, locale); } return result; diff --git a/src/gausskernel/CMakeLists.txt b/src/gausskernel/CMakeLists.txt index 10a9fb1189381160076e1619ef3dd2766462fdd4..0d1aefda1c2aba51695afeef989e295583c1449f 100755 --- a/src/gausskernel/CMakeLists.txt +++ b/src/gausskernel/CMakeLists.txt @@ -396,6 +396,9 @@ if(NOT "${ENABLE_UT}" STREQUAL "ON") add_executable(gaussdb ${gaussdb_objects}) target_link_options(gaussdb PRIVATE ${gaussdb_LINK_OPTIONS}) +if("${ENABLE_RELOCATION}" STREQUAL "ON") + target_link_options(gaussdb PRIVATE ${gaussdb_LINK_OPTIONS} "LINKER:-q") +endif() target_link_directories(gaussdb PRIVATE ${gaussdb_LINK_DIRS}) target_link_libraries(gaussdb PRIVATE ${gaussdb_LINK_LIBS}) add_dependencies(gaussdb ${gaussdb_DEPEND_LIST}) @@ -409,7 +412,10 @@ if(NOT "${ENABLE_UT}" STREQUAL "ON") endif() install(TARGETS gaussdb RUNTIME DESTINATION bin) -if(NOT "${ENABLE_LITE_MODE}" STREQUAL "ON") +if("${ENABLE_RELOCATION}" STREQUAL "ON") + install(CODE "execute_process(COMMAND cp gaussdb gaussdb.map WORKING_DIRECTORY \$ENV\{DESTDIR\}${CMAKE_INSTALL_PREFIX}/bin)") +endif() + if(NOT "${ENABLE_LITE_MODE}" STREQUAL "ON") install(CODE "execute_process(COMMAND ln -sf gaussdb gs_encrypt WORKING_DIRECTORY \$ENV\{DESTDIR\}${CMAKE_INSTALL_PREFIX}/bin)") install(CODE "message(\"-- Created symlink: gs_encrypt -> gaussdb\")") endif() diff --git a/src/gausskernel/Makefile b/src/gausskernel/Makefile index b8d6a87b192da0444b7c3d06dccc94f7a3c133cd..ac5791f433da23c382398079b2233cca05e0984e 100755 --- a/src/gausskernel/Makefile +++ b/src/gausskernel/Makefile @@ -305,6 +305,9 @@ ifneq ($(PORTNAME), aix) gaussdb: $(OBJS) | $(CC) $(CXXFLAGS) $(LDFLAGS) $(LDFLAGS_EX) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) $(LLVMLIBS) $(HOTPATCH_ATOMIC_LDS) -o $@ +ifeq ($(enable_relocation), yes) + $(CC) $(CXXFLAGS) $(LDFLAGS) $(LDFLAGS_EX) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) $(LLVMLIBS) $(HOTPATCH_ATOMIC_LDS) -o $@.map -Wl,-q +endif $(CRC_CHECK) db: $(OBJS) @@ -705,6 +708,10 @@ endif install-bin: gaussdb $(POSTGRES_IMP) installdirs libcgroup $(INSTALL_PROGRAM) gaussdb$(X) '$(DESTDIR)$(bindir)/gaussdb$(X)' $(INSTALL_PROGRAM) '$(LZ4_BIN_PATH)/lz4' '$(DESTDIR)$(bindir)/lz4' +ifeq ($(enable_relocation), yes) + $(INSTALL_PROGRAM) gaussdb$(X).map '$(DESTDIR)$(bindir)/gaussdb$(X).map' +endif + ifeq ($(enable_lite_mode), no) @if test -d $(KERBEROS_BIN_PATH); then cp -rf $(KERBEROS_BIN_PATH)/klist $(DESTDIR)$(bindir)/; fi @if test -d $(KERBEROS_BIN_PATH); then cp -rf $(KERBEROS_BIN_PATH)/kinit $(DESTDIR)$(bindir)/; fi diff --git a/src/gausskernel/ddes/adapter/ss_dms.cpp b/src/gausskernel/ddes/adapter/ss_dms.cpp index 6fe490817fa6d841801b64e70fd5a6ffbb00bf4f..76d107e2d8d34b34590a1dd20696a10d53681a3f 100644 --- a/src/gausskernel/ddes/adapter/ss_dms.cpp +++ b/src/gausskernel/ddes/adapter/ss_dms.cpp @@ -206,10 +206,9 @@ int dms_request_page(dms_context_t *dms_ctx, dms_buf_ctrl_t *ctrl, dms_lock_mode return g_ss_dms_func.dms_request_page(dms_ctx, ctrl, mode); } -int dms_broadcast_msg(dms_context_t *dms_ctx, char *data, unsigned int len, unsigned char handle_recv_msg, - unsigned int timeout) +int dms_broadcast_msg(dms_context_t *dms_ctx, dms_broadcast_info_t *dms_broad_info) { - return g_ss_dms_func.dms_broadcast_msg(dms_ctx, data, len, handle_recv_msg, timeout); + return g_ss_dms_func.dms_broadcast_msg(dms_ctx, dms_broad_info); } int dms_request_opengauss_update_xid(dms_context_t *dms_ctx, unsigned short t_infomask, unsigned short t_infomask2, diff --git a/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp b/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp index 88efa27b1430bf2dae35e13604c7235e89cceead..c7cb3d69bd5ef3e3132ba49e053700358bbc92f0 100644 --- a/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp +++ b/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp @@ -64,6 +64,7 @@ void InitDmsBufCtrl(void) void InitDmsContext(dms_context_t *dmsContext) { + (void)memset_s(dmsContext, sizeof(dms_context_t), 0, sizeof(dms_context_t)); /* Proc threads id range: [0, TotalProcs - 1]. Non-proc threads id range: [TotalProcs + 1, TotalProcs + 4] */ uint32 TotalProcs = (uint32)(GLOBAL_ALL_PROCS); dmsContext->inst_id = (unsigned int)SS_MY_INST_ID; @@ -87,8 +88,15 @@ void InitDmsBufContext(dms_context_t* dmsBufCxt, BufferTag buftag) void TransformLockTagToDmsLatch(dms_drlatch_t* dlatch, const LOCKTAG locktag) { - DmsInitLatch(&dlatch->drid, locktag.locktag_type, locktag.locktag_field1, locktag.locktag_field2, - locktag.locktag_field3, locktag.locktag_field4, locktag.locktag_field5); + int32 ret = memset_sp(&dlatch->drid, sizeof(dms_drid_t), 0, sizeof(dms_drid_t)); + securec_check(ret, "", ""); + + dlatch->drid.type = locktag.locktag_type; + dlatch->drid.oid = locktag.locktag_field1; + dlatch->drid.index = locktag.locktag_field2; + dlatch->drid.parent_part = locktag.locktag_field3; + dlatch->drid.part = locktag.locktag_field4; + dlatch->drid.uid = locktag.locktag_field5; } static void CalcSegDmsPhysicalLoc(BufferDesc* buf_desc, Buffer buffer, bool check_standby) @@ -660,7 +668,7 @@ void BufValidateDrc(BufferDesc *buf_desc) dms_context_t dms_ctx; InitDmsBufContext(&dms_ctx, buf_desc->tag); unsigned long long lsn = (unsigned long long)BufferGetLSN(buf_desc); - bool is_dirty = (buf_desc->state & (BM_DIRTY | BM_JUST_DIRTIED)) > 0 ? true : false; + bool is_dirty = SSBufferIsDirty(buf_desc); dms_validate_drc(&dms_ctx, buf_ctrl, lsn, (unsigned char)is_dirty); } @@ -960,6 +968,14 @@ bool SSTryFlushBuffer(BufferDesc *buf) return false; } + if (ENABLE_INCRE_CKPT) { + for (int i = 0; i < g_instance.ckpt_cxt_ctl->pgwr_procs.num; i++) { + if (g_instance.pid_cxt.PageWriterPID[i] == 0) { + g_instance.pid_cxt.PageWriterPID[i] = initialize_util_thread(PAGEWRITER_THREAD); + } + } + } + if (LWLockConditionalAcquire(buf->content_lock, LW_SHARED)) { if (dw_enabled() && pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->current_page_writer_count) > 0) { if (!free_space_enough(buf->buf_id)) { @@ -1174,45 +1190,6 @@ void DmsReleaseBuffer(int buffer, bool is_seg) } } -bool SSRequestPageInOndemandRealtimeBuild(BufferTag *bufferTag, XLogRecPtr recordLsn, XLogRecPtr *pageLsn) -{ - Buffer buffer = SSReadBuffer(bufferTag, RBM_FOR_ONDEMAND_REALTIME_BUILD); - if (BufferIsInvalid(buffer)) { - WaitUntilRealtimeBuildStatusToFailoverAndUpdatePrunePtr(); - ereport(DEBUG1, (errmodule(MOD_DMS), - errmsg("[On-demand] standby node request page failed in ondemand realtime build, step readbuffer, " - "spc/db/rel/bucket fork-block: %u/%u/%u/%d %d-%u, ondemand realtime build status %d", - bufferTag->rnode.spcNode, bufferTag->rnode.dbNode, bufferTag->rnode.relNode, bufferTag->rnode.bucketNode, - bufferTag->forkNum, bufferTag->blockNum, g_instance.dms_cxt.SSRecoveryInfo.ondemand_realtime_build_status))); - return false; - } - - LockBuffer(buffer, BUFFER_LOCK_SHARE); - - dms_buf_ctrl_t *buf_ctrl = GetDmsBufCtrl(buffer - 1); - if (buf_ctrl->state & BUF_READ_MODE_ONDEMAND_REALTIME_BUILD) { - buf_ctrl->state &= ~BUF_READ_MODE_ONDEMAND_REALTIME_BUILD; - buf_ctrl->state |= BUF_IS_ONDEMAND_REALTIME_BUILD_PINNED; - - if (pageLsn != NULL) { - *pageLsn = PageGetLSN(BufferGetPage(buffer)); - } - } else { - DmsReleaseBuffer(buffer, IsSegmentPhysicalRelNode(bufferTag->rnode)); - WaitUntilRealtimeBuildStatusToFailoverAndUpdatePrunePtr(); - ereport(DEBUG1, (errmodule(MOD_DMS), - errmsg("[On-demand] standby node request page failed in ondemand realtime build, step lockbuffer, " - "spc/db/rel/bucket fork-block: %u/%u/%u/%d %d-%u, ondemand realtime build status %d", - bufferTag->rnode.spcNode, bufferTag->rnode.dbNode, bufferTag->rnode.relNode, bufferTag->rnode.bucketNode, - bufferTag->forkNum, bufferTag->blockNum, g_instance.dms_cxt.SSRecoveryInfo.ondemand_realtime_build_status))); - return false; - } - - LockBuffer(buffer, BUFFER_LOCK_UNLOCK); - DmsReleaseBuffer(buffer, IsSegmentPhysicalRelNode(bufferTag->rnode)); - return true; -} - bool SSNeedTerminateRequestPageInReform(dms_buf_ctrl_t *buf_ctrl) { if (AmDmsReformProcProcess() && dms_reform_failed()) { diff --git a/src/gausskernel/ddes/adapter/ss_dms_callback.cpp b/src/gausskernel/ddes/adapter/ss_dms_callback.cpp index 8b8d1272fae911c11b8051d5cf1948a02c15b09d..85a86eb936fe9d632715bb70ff26083b3f36be43 100644 --- a/src/gausskernel/ddes/adapter/ss_dms_callback.cpp +++ b/src/gausskernel/ddes/adapter/ss_dms_callback.cpp @@ -447,6 +447,7 @@ static int CBSwitchoverPromote(void *db_handle, unsigned char origPrimaryId) if (ntries >= WAIT_PROMOTE || dms_reform_failed()) { ereport(WARNING, (errmodule(MOD_DMS), errmsg("[SS switchover] Standby promote timeout, please try again later."))); + SSWaitStartupExit(); return DMS_ERROR; } ntries = 0; @@ -713,7 +714,7 @@ static unsigned char CBPageDirty(dms_buf_ctrl_t *buf_ctrl) return 0; } BufferDesc *buf_desc = GetBufferDescriptor(buf_ctrl->buf_id); - bool is_dirty = (pg_atomic_read_u64(&buf_desc->state) & (BM_DIRTY | BM_JUST_DIRTIED)) > 0; + bool is_dirty = SSBufferIsDirty(buf_desc); return (unsigned char)is_dirty; } @@ -1279,57 +1280,29 @@ static void CBSetDmsStatus(void *db_handle, int dms_status) g_instance.dms_cxt.dms_status = (dms_status_t)dms_status; } -static bool SSCheckBufferIfCanGoRebuild(BufferDesc* buf_desc, uint64 buf_state) +static int32 SSBufRebuildOneDrcInternal(BufferDesc *buf_desc, unsigned char thread_index) { - bool ret = false; dms_buf_ctrl_t *buf_ctrl = GetDmsBufCtrl(buf_desc->buf_id); - if ((buf_state & BM_VALID) && (buf_ctrl->lock_mode != (unsigned char)DMS_LOCK_NULL)) { - ret = true; - } else if ((buf_state & BM_TAG_VALID) && (buf_ctrl->lock_mode != (unsigned char)DMS_LOCK_NULL) && !(buf_ctrl->state | BUF_IS_EXTEND)) { - if (LWLockConditionalAcquire(buf_desc->io_in_progress_lock, LW_SHARED)) { - ret = true; - } else { - /* - * In the condition of (Phase1)readbuffer_common->(Phase2)dms_request_page->(Phase3)seg_read->(Phase4)lock - * seg_head buffer, and stuck in Phase4 as reform happened. It will block the request of data pase as the - * lock mode of dms_buf_ctrl was already set to DMS_LOCK_EXCLUSIVE and IO is still in process. - * In order to get rid of this dilemma, we force set the lock mode back to null and don't rebuild this - * page. The stucked process will request the page again when it add content lock and the reformer will - * become owner when it request the page. - */ - ereport(WARNING, (errmsg("[%u/%u/%u/%d/0 %d-%u] Set lock mode to NULL, desc state:%lu, ctrl state:%u, lock mode:%d.", - buf_desc->tag.rnode.spcNode, buf_desc->tag.rnode.dbNode, buf_desc->tag.rnode.relNode, - buf_desc->tag.rnode.bucketNode, buf_desc->tag.forkNum, buf_desc->tag.blockNum, buf_state, buf_ctrl->state, buf_ctrl->lock_mode))); - buf_ctrl->lock_mode = DMS_LOCK_NULL; - } - } - - return ret; -} - -static int32 SSRebuildBuf(BufferDesc *buf_desc, unsigned char thread_index) -{ #ifdef USE_ASSERT_CHECKING if (IsSegmentPhysicalRelNode(buf_desc->tag.rnode)) { SegNetPageCheckDiskLSN(buf_desc, RBM_NORMAL, NULL); } else { SmgrNetPageCheckDiskLSN(buf_desc, RBM_NORMAL, NULL); } -#endif - - dms_buf_ctrl_t *buf_ctrl = GetDmsBufCtrl(buf_desc->buf_id); + Assert(buf_ctrl != NULL); Assert(buf_ctrl->is_edp != 1); Assert(XLogRecPtrIsValid(g_instance.dms_cxt.ckptRedo)); +#endif dms_context_t dms_ctx; InitDmsBufContext(&dms_ctx, buf_desc->tag); dms_ctrl_info_t ctrl_info = { 0 }; ctrl_info.ctrl = *buf_ctrl; ctrl_info.lsn = (unsigned long long)BufferGetLSN(buf_desc); - ctrl_info.is_dirty = (buf_desc->state & (BM_DIRTY | BM_JUST_DIRTIED)) > 0 ? true : false; + ctrl_info.is_dirty = SSBufferIsDirty(buf_desc); int ret = dms_buf_res_rebuild_drc_parallel(&dms_ctx, &ctrl_info, thread_index); if (ret != DMS_SUCCESS) { - ereport(WARNING, (errmsg("Failed to rebuild page, rel:%u/%u/%u/%d, forknum:%d, blocknum:%u.", + ereport(WARNING, (errmsg("[%u/%u/%u/%d %d-%u][SS reform] rebuild page failed.", buf_desc->tag.rnode.spcNode, buf_desc->tag.rnode.dbNode, buf_desc->tag.rnode.relNode, buf_desc->tag.rnode.bucketNode, buf_desc->tag.forkNum, buf_desc->tag.blockNum))); return ret; @@ -1337,45 +1310,53 @@ static int32 SSRebuildBuf(BufferDesc *buf_desc, unsigned char thread_index) return DMS_SUCCESS; } -static int32 CBDrcBufRebuildInternal(int begin, int len, unsigned char thread_index) +static int SSBufRebuildOneDrc(int index, unsigned char thread_index) { - uint64 buf_state; - Assert(begin >= 0 && len > 0 && (begin + len) <= TOTAL_BUFFER_NUM); - for (int i = begin; i < begin + len; i++) { - BufferDesc *buf_desc = GetBufferDescriptor(i); - bool need_rebuild = true; - if (LWLockConditionalAcquire(buf_desc->content_lock, LW_EXCLUSIVE)) { - buf_state = LockBufHdr(buf_desc); - if ((buf_state & BM_VALID) && !(buf_state & BM_DIRTY)) { - dms_buf_ctrl_t *buf_ctrl = GetDmsBufCtrl(buf_desc->buf_id); + BufferDesc *buf_desc = GetBufferDescriptor(index); + dms_buf_ctrl_t *buf_ctrl = GetDmsBufCtrl(index); + (void)SSPinBuffer(buf_desc); + bool need_rebuild = true; + LWLockAcquire((LWLock*)buf_ctrl->ctrl_lock, LW_EXCLUSIVE); + bool is_owner = DMS_BUF_CTRL_IS_OWNER(buf_ctrl); + LWLockRelease((LWLock*)buf_ctrl->ctrl_lock); + if (is_owner) { + if (LWLockConditionalAcquire(buf_desc->content_lock, LW_SHARED)) { + if (!SSBufferIsDirty(buf_desc)) { + LWLockAcquire((LWLock*)buf_ctrl->ctrl_lock, LW_EXCLUSIVE); buf_ctrl->lock_mode = DMS_LOCK_NULL; + LWLockRelease((LWLock*)buf_ctrl->ctrl_lock); need_rebuild = false; + ereport(DEBUG5, (errmsg("[%u/%u/%u/%d %d-%u][SS reform] no need rebuild, set lock_mode NULL.", + buf_desc->tag.rnode.spcNode, buf_desc->tag.rnode.dbNode, buf_desc->tag.rnode.relNode, + buf_desc->tag.rnode.bucketNode, buf_desc->tag.forkNum, buf_desc->tag.blockNum))); } - UnlockBufHdr(buf_desc, buf_state); - LWLockRelease(buf_desc->content_lock); - } - - if (need_rebuild) { - buf_state = LockBufHdr(buf_desc); - if (SSCheckBufferIfCanGoRebuild(buf_desc, buf_state)) { - int ret = SSRebuildBuf(buf_desc, thread_index); - if (ret != DMS_SUCCESS) { - if (LWLockHeldByMe(buf_desc->io_in_progress_lock)) { - LWLockRelease(buf_desc->io_in_progress_lock); - } - UnlockBufHdr(buf_desc, buf_state); - return ret; - } - } - if (LWLockHeldByMe(buf_desc->io_in_progress_lock)) { - LWLockRelease(buf_desc->io_in_progress_lock); - } - UnlockBufHdr(buf_desc, buf_state); + LWLockRelease(buf_desc->content_lock); + } + } else { + need_rebuild = false; + } + SSUnPinBuffer(buf_desc); + + if (need_rebuild) { + int ret = SSBufRebuildOneDrcInternal(buf_desc, thread_index); + return ret; + } + return DMS_SUCCESS; +} + +static int32 CBBufRebuildDrcInternal(int begin, int len, unsigned char thread_index) +{ + Assert(begin >= 0 && len > 0 && (begin + len) <= TOTAL_BUFFER_NUM); + int end = begin + len - 1; + for (int i = begin; i <= end; i++) { + int ret = SSBufRebuildOneDrc(i, thread_index); + if (ret != DMS_SUCCESS) { + return ret; } } ereport(LOG, (errmodule(MOD_DMS), errmsg("[SS reform] rebuild buf thread_index:%d, buf_if start from:%d to:%d, max_buf_id:%d", - (int)thread_index, begin, (begin + len - 1), (TOTAL_BUFFER_NUM - 1)))); + (int)thread_index, begin, end, (TOTAL_BUFFER_NUM - 1)))); return GS_SUCCESS; } @@ -1388,7 +1369,7 @@ static int32 CBDrcBufRebuildInternal(int begin, int len, unsigned char thread_in */ const int dms_invalid_thread_index = 255; const int dms_invalid_thread_num = 255; -static int32 CBDrcBufRebuildParallel(void* db_handle, unsigned char thread_index, unsigned char thread_num) +static int32 CBBufRebuildDrcParallel(void* db_handle, unsigned char thread_index, unsigned char thread_num) { Assert((thread_index == dms_invalid_thread_index && thread_num == dms_invalid_thread_num) || (thread_index != dms_invalid_thread_index && thread_num != dms_invalid_thread_num && @@ -1403,7 +1384,7 @@ static int32 CBDrcBufRebuildParallel(void* db_handle, unsigned char thread_index buf_begin = 0; buf_num = TOTAL_BUFFER_NUM; } - return CBDrcBufRebuildInternal(buf_begin, buf_num, thread_index); + return CBBufRebuildDrcInternal(buf_begin, buf_num, thread_index); } static int32 CBDrcBufValidate(void *db_handle) @@ -1720,17 +1701,6 @@ static void ReformCleanBackends() } while (true) { - int ticks = 0; - if (g_instance.pid_cxt.StartupPID != 0) { - if (ticks++ > REFORM_START_CLEAN_TICKS) { - ereport(WARNING, (errmodule(MOD_DMS), - errmsg("[SS reform] StartupXLOG debris sigterm timeout 10s, exit now"))); - _exit(0); - } - pg_usleep(REFORM_WAIT_LONG); - continue; - } - if (dms_reform_failed()) { ereport(WARNING, (errmodule(MOD_DMS), errmsg("[SS reform]reform failed during caneling backends"))); return; @@ -1864,7 +1834,7 @@ static void CBReformStartNotify(void *db_handle, dms_reform_start_context_t *rs_ ereport(LOG, (errmsg("[SS Reform] starts, pmState=%d, SSClusterState=%d, demotion=%d-%d, rec=%d", pmState, g_instance.dms_cxt.SSClusterState, g_instance.demotion, t_thrd.walsender_cxt.WalSndCtl->demotion, t_thrd.xlog_cxt.InRecovery))); - + SSHandleStartupWhenReformStart(); ss_reform_info_t *reform_info = &g_instance.dms_cxt.SSReformInfo; reform_info->is_hashmap_constructed = false; reform_info->reform_type = rs_cxt->reform_type; @@ -1881,13 +1851,16 @@ static void CBReformStartNotify(void *db_handle, dms_reform_start_context_t *rs_ reform_info->bitmap_reconnect = rs_cxt->bitmap_reconnect; reform_info->dms_role = rs_cxt->role; SSXminInfoPrepare(); + reform_info->reform_ver = reform_info->reform_start_time; reform_info->in_reform = true; char reform_type_str[reform_type_str_len] = {0}; ReformTypeToString(reform_info->reform_type, reform_type_str); ereport(LOG, (errmodule(MOD_DMS), - errmsg("[SS reform] dms reform start, role:%d, reform type:SS %s, standby scenario:%d", - reform_info->dms_role, reform_type_str, SSPerformingStandbyScenario()))); + errmsg("[SS reform] reform start, role:%d, reform type:SS %s, standby scenario:%d, " + "reform_ver:%llu.", + reform_info->dms_role, reform_type_str, SSPerformingStandbyScenario(), + reform_info->reform_ver))); if (reform_info->dms_role == DMS_ROLE_REFORMER) { SSGrantDSSWritePermission(); } @@ -2156,7 +2129,7 @@ void DmsInitCallback(dms_callback_t *callback) callback->opengauss_recovery_primary = CBRecoveryPrimary; callback->get_dms_status = CBGetDmsStatus; callback->set_dms_status = CBSetDmsStatus; - callback->dms_reform_rebuild_parallel = CBDrcBufRebuildParallel; + callback->dms_reform_rebuild_parallel = CBBufRebuildDrcParallel; callback->dms_thread_init = DmsCallbackThreadShmemInit; callback->confirm_owner = CBConfirmOwner; callback->confirm_converting = CBConfirmConverting; diff --git a/src/gausskernel/ddes/adapter/ss_dms_recovery.cpp b/src/gausskernel/ddes/adapter/ss_dms_recovery.cpp index 9b1238c527ef6a82d7a9aca6df2bdd24a8884a0d..68eebafb8d1217d793e423d262c89058c8a88a9c 100644 --- a/src/gausskernel/ddes/adapter/ss_dms_recovery.cpp +++ b/src/gausskernel/ddes/adapter/ss_dms_recovery.cpp @@ -60,33 +60,6 @@ void SSSavePrimaryInstId(int id) LWLockRelease(ControlFileLock); } -void SSWaitStartupExit() -{ - if (g_instance.pid_cxt.StartupPID == 0) { - return; - } - - if (SS_STANDBY_FAILOVER && !g_instance.dms_cxt.SSRecoveryInfo.restart_failover_flag) { - g_instance.dms_cxt.SSRecoveryInfo.startup_need_exit_normally = true; - } - SendPostmasterSignal(PMSIGNAL_DMS_TERM_STARTUP); - int err_level = g_instance.dms_cxt.SSRecoveryInfo.startup_need_exit_normally ? LOG : WARNING; - ereport(err_level, (errmodule(MOD_DMS), errmsg("[SS reform] reform failed, startup thread need exit"))); - - while (true) { - if (g_instance.pid_cxt.StartupPID == 0) { - break; - } - - if (g_instance.dms_cxt.SSRecoveryInfo.recovery_trapped_in_page_request) { - ereport(WARNING, (errmodule(MOD_DMS), errmsg("[SS reform] pageredo or startup thread are trapped " - "in page request during recovery phase, need exit"))); - _exit(0); - } - pg_usleep(5000L); - } -} - /** * find reform failed in recovery phase, maybe other node restart * pageredo or startup thread may trapped in LockBuffer for page request @@ -148,10 +121,6 @@ bool SSRecoveryNodes() bool SSRecoveryApplyDelay() { - if (!ENABLE_REFORM) { - return false; - } - if (SS_DISASTER_STANDBY_CLUSTER) { return true; } @@ -288,24 +257,6 @@ void ss_failover_dw_init() g_instance.dms_cxt.dw_init = true; } -/* In serial switchover scenario, prevent this promoting node from reinitializing dw. */ -void ss_switchover_promoting_dw_init() -{ - for (int i = 0; i < g_instance.ckpt_cxt_ctl->pgwr_procs.num; i++) { - if (g_instance.pid_cxt.PageWriterPID[i] != 0) { - signal_child(g_instance.pid_cxt.PageWriterPID[i], SIGTERM, -1); - } - } - ckpt_shutdown_pagewriter(); - - dw_exit(true); - dw_exit(false); - dw_ext_init(); - dw_init(); - g_instance.dms_cxt.dw_init = true; - ereport(LOG, (errmodule(MOD_DMS), errmsg("[SS switchover] dw init finished"))); -} - XLogRecPtr SSOndemandRequestPrimaryCkptAndGetRedoLsn() { XLogRecPtr primaryRedoLsn = InvalidXLogRecPtr; @@ -354,7 +305,13 @@ void OndemandRealtimeBuildHandleFailover() Assert(SS_ONDEMAND_REALTIME_BUILD_NORMAL); SSReadControlFile(SSGetPrimaryInstId()); - ss_failover_dw_init(); + if (u_sess->storage_cxt.pendingOps == NULL) { + InitSync(); + ss_failover_dw_init(); + EnableSyncRequestForwarding(); + } else { + ss_failover_dw_init(); + } StartupOndemandRecovery(); StartupReplicationSlots(); restoreTwoPhaseData(); diff --git a/src/gausskernel/ddes/adapter/ss_init.cpp b/src/gausskernel/ddes/adapter/ss_init.cpp index 24491faebdf03f6a6de936aa01152026c775fce1..7b26d7d4e43ef6112f1e9d13d0d2a971f21ae341 100644 --- a/src/gausskernel/ddes/adapter/ss_init.cpp +++ b/src/gausskernel/ddes/adapter/ss_init.cpp @@ -393,7 +393,6 @@ static void setDMSProfile(dms_profile_t* profile) setScrlConfig(profile); SetOckLogPath(dms_attr, profile->ock_log_path); profile->inst_map = 0; - profile->enable_reform = (unsigned char)dms_attr->enable_reform; profile->parallel_thread_num = dms_attr->parallel_thread_num; profile->max_wait_time = DMS_MSG_MAX_WAIT_TIME; @@ -462,12 +461,6 @@ void DMSInit() } rc = memset_s(g_instance.dms_cxt.conninfo, MAXCONNINFO, '\0', MAXCONNINFO); securec_check(rc, "", ""); - -#ifdef USE_ASSERT_CHECKING - if (!ENABLE_REFORM && SS_NORMAL_STANDBY) { - SSStandbySetLibpqswConninfo(); - } -#endif } void GetSSLogPath(char *sslog_path) @@ -582,10 +575,22 @@ bool DMSWaitInitStartup() void StartupWaitReform() { + ss_reform_info_t *reform_info = &g_instance.dms_cxt.SSReformInfo; + TimestampTz wait_ver = reform_info->reform_ver_startup_wait; + Assert(wait_ver != 0); while (g_instance.dms_cxt.SSReformInfo.in_reform) { + if (wait_ver != reform_info->reform_ver) { + ereport(LOG, (errmodule(MOD_DMS), + errmsg("[SS reform] startup no need wait for reform finish, cause new reform has begun. " + "current reform version:%llu,startup wait reform version:%llu", + reform_info->reform_ver, wait_ver))); + break; + } + if (dms_reform_failed() || dms_reform_last_failed()) { if (g_instance.dms_cxt.SSReformInfo.in_reform) { - ereport(LOG, (errmsg("[SS reform] reform failed, startup no need wait."))); + ereport(LOG, (errmodule(MOD_DMS), + errmsg("[SS reform] reform failed, startup no need wait reform finish."))); break; } } diff --git a/src/gausskernel/ddes/adapter/ss_reform_common.cpp b/src/gausskernel/ddes/adapter/ss_reform_common.cpp index 4166c557ca0ede70c3621aeb30e40dc80a28b7c3..c65b46c2d9baa2a4a5cf1bc04e2c242e06fe07a2 100644 --- a/src/gausskernel/ddes/adapter/ss_reform_common.cpp +++ b/src/gausskernel/ddes/adapter/ss_reform_common.cpp @@ -562,3 +562,92 @@ bool SSBackendNeedExitScenario() return true; } + +static void SSProcessForceExit() +{ + int log_level = WARNING; +#ifdef USE_ASSERT_CHECKING + log_level = PANIC; +#endif + ereport(log_level, (errmodule(MOD_DMS), + errmsg("exit now"))); + _exit(0); +} + +void SSWaitStartupExit(bool send_signal) +{ + if (g_instance.pid_cxt.StartupPID == 0) { + return; + } + + if (send_signal) { + if ((SS_STANDBY_FAILOVER && !g_instance.dms_cxt.SSRecoveryInfo.restart_failover_flag) || + SS_STANDBY_PROMOTING) { + g_instance.dms_cxt.SSRecoveryInfo.startup_need_exit_normally = true; + pg_memory_barrier(); + } + SendPostmasterSignal(PMSIGNAL_DMS_TERM_STARTUP); + } + + + if (SS_IN_REFORM && dms_reform_failed()) { + ereport(WARNING, (errmodule(MOD_DMS), + errmsg("[SS reform] reform failed"))); + } + + long rto_limit = SS_RTO_LIMIT; + ereport(LOG, (errmodule(MOD_DMS), + errmsg("[SS reform] wait startup thread exit until RTO limit time:%d sec", + rto_limit / (1000 * 1000)))); + + long wait_time = 0; + while (true) { + if (g_instance.pid_cxt.StartupPID == 0) { + break; + } + + if (g_instance.dms_cxt.SSRecoveryInfo.recovery_trapped_in_page_request) { + ereport(WARNING, (errmodule(MOD_DMS), + errmsg("[SS reform] pageredo or startup thread are trapped in page request " + "during recovery phase, need exit"))); + _exit(0); + } + if (wait_time > rto_limit) { + SSProcessForceExit(); + } + pg_usleep(REFORM_WAIT_TIME); + wait_time += REFORM_WAIT_TIME; + } +} + +void SSHandleStartupWhenReformStart() +{ + if (g_instance.pid_cxt.StartupPID == 0) { + return; + } + + if (ENABLE_ONDEMAND_RECOVERY && ENABLE_ONDEMAND_REALTIME_BUILD) { + ereport(LOG, (errmodule(MOD_DMS), + errmsg("[SS reform][On-demand] start phase, on_demand real time build is enable " + "no need wait startup thread exit."))); + return; + } + + if (SS_DISASTER_MAIN_STANDBY_NODE) { + ereport(LOG, (errmodule(MOD_DMS), + errmsg("[SS reform] start phase, standby cluster main node " + "no need wait startup thread exit."))); + return; + } + + ss_reform_info_t *reform_info = &g_instance.dms_cxt.SSReformInfo; + if (reform_info->reform_ver == reform_info->reform_ver_startup_wait && + reform_info->reform_ver_startup_wait != 0) { + SSWaitStartupExit(false); + } else { + ereport(WARNING, (errmodule(MOD_DMS), + errmsg("[SS reform] start phase, last round reform version:%llu, startup wait version:%llu", + reform_info->reform_ver, reform_info->reform_ver_startup_wait))); + SSProcessForceExit(); + } +} \ No newline at end of file diff --git a/src/gausskernel/ddes/adapter/ss_transaction.cpp b/src/gausskernel/ddes/adapter/ss_transaction.cpp index 67ca5a9bfe340f84972c9d13d4c988edc3068f17..c2cbcaaadf06ec5ac956f07ed798e73345404e1a 100644 --- a/src/gausskernel/ddes/adapter/ss_transaction.cpp +++ b/src/gausskernel/ddes/adapter/ss_transaction.cpp @@ -67,6 +67,11 @@ static Snapshot SSGetSnapshotDataFromMaster(Snapshot snapshot) if (AM_WAL_SENDER && SS_IN_REFORM) { return NULL; } + + if (SSBackendNeedExitScenario() && + (t_thrd.role == WORKER || t_thrd.role == THREADPOOL_WORKER || t_thrd.role == STREAM_WORKER)) { + return NULL; + } pg_usleep(USECS_PER_SEC); } while (true); @@ -476,9 +481,19 @@ void SSSendLatestSnapshotToStandby(TransactionId xmin, TransactionId xmax, Commi latest_snapshot.xmax = xmax; latest_snapshot.csn = csn; latest_snapshot.type = BCAST_SEND_SNAPSHOT; + dms_broadcast_info_t dms_broad_info = { + .data = (char *)&latest_snapshot, + .len = sizeof(SSBroadcastSnapshot), + .output = NULL, + .output_len = NULL, + .scope = DMS_BROADCAST_ONLINE_LIST, + .inst_map = 0, + .timeout = SS_BROADCAST_WAIT_ONE_SECOND, + .handle_recv_msg = (unsigned char)false, + .check_session_kill = (unsigned char)true + }; do { - ret = dms_broadcast_msg(&dms_ctx, (char *)&latest_snapshot, sizeof(SSBroadcastSnapshot), - (unsigned char)false, SS_BROADCAST_WAIT_ONE_SECOND); + ret = dms_broadcast_msg(&dms_ctx, &dms_broad_info); if (ret == DMS_SUCCESS) { return; @@ -556,9 +571,19 @@ bool SSCheckDbBackendsFromAllStandby(Oid dbid) SSBroadcastDbBackends backends_data; backends_data.type = BCAST_CHECK_DB_BACKENDS; backends_data.dbid = dbid; - - int ret = dms_broadcast_msg(&dms_ctx, (char *)&backends_data, sizeof(SSBroadcastDbBackends), - (unsigned char)true, SS_BROADCAST_WAIT_FIVE_SECONDS); + dms_broadcast_info_t dms_broad_info = { + .data = (char *)&backends_data, + .len = sizeof(SSBroadcastDbBackends), + .output = NULL, + .output_len = NULL, + .scope = DMS_BROADCAST_ONLINE_LIST, + .inst_map = 0, + .timeout = SS_BROADCAST_WAIT_FIVE_SECONDS, + .handle_recv_msg = (unsigned char)true, + .check_session_kill = (unsigned char)true + }; + + int ret = dms_broadcast_msg(&dms_ctx, &dms_broad_info); if (ret != DMS_NO_RUNNING_BACKENDS) { return true; } @@ -572,9 +597,19 @@ void SSRequestAllStandbyReloadReformCtrlPage() int ret; SSBroadcastCmdOnly ssmsg; ssmsg.type = BCAST_RELOAD_REFORM_CTRL_PAGE; + dms_broadcast_info_t dms_broad_info = { + .data = (char *)&ssmsg, + .len = sizeof(SSBroadcastCmdOnly), + .output = NULL, + .output_len = NULL, + .scope = DMS_BROADCAST_ONLINE_LIST, + .inst_map = 0, + .timeout = SS_BROADCAST_WAIT_ONE_SECOND, + .handle_recv_msg = (unsigned char)false, + .check_session_kill = (unsigned char)true + }; do { - ret = dms_broadcast_msg(&dms_ctx, (char *)&ssmsg, sizeof(SSBroadcastCmdOnly), - (unsigned char)false, SS_BROADCAST_WAIT_ONE_SECOND); + ret = dms_broadcast_msg(&dms_ctx, &dms_broad_info); if (ret == DMS_SUCCESS) { return; @@ -734,8 +769,18 @@ void SSUpdateSegDropTimeline(uint32 seg_drop_timeline) ssmsg.seg_drop_timeline = seg_drop_timeline; int output_backup = t_thrd.postgres_cxt.whereToSendOutput; t_thrd.postgres_cxt.whereToSendOutput = DestNone; - int ret = dms_broadcast_msg(&dms_ctx, (char *)&ssmsg, sizeof(SSBroadcastSegDropTL), (unsigned char)false, - SS_BROADCAST_WAIT_FIVE_SECONDS); + dms_broadcast_info_t dms_broad_info = { + .data = (char *)&ssmsg, + .len = sizeof(SSBroadcastSegDropTL), + .output = NULL, + .output_len = NULL, + .scope = DMS_BROADCAST_ONLINE_LIST, + .inst_map = 0, + .timeout = SS_BROADCAST_WAIT_FIVE_SECONDS, + .handle_recv_msg = (unsigned char)false, + .check_session_kill = (unsigned char)true + }; + int ret = dms_broadcast_msg(&dms_ctx, &dms_broad_info); if (ret != DMS_SUCCESS) { ereport(DEBUG1, (errmsg("SS broadcast seg_drop_timeline failed!"))); } diff --git a/src/gausskernel/ddes/ddes_commit_id b/src/gausskernel/ddes/ddes_commit_id index 8e9d9f4f32cf6cab4a84bda0e1cebf6591e031c8..73bca88038b656aa6bb25a875ba71da88289506f 100644 --- a/src/gausskernel/ddes/ddes_commit_id +++ b/src/gausskernel/ddes/ddes_commit_id @@ -1,3 +1,3 @@ -dms_commit_id=fd17887cf2ad385ffbf2c7f12333f052fb3199ef -dss_commit_id=84da99c33980ef7b94008e389637850f19ca5079 -cbb_commit_id=ca5419cd63969d5d174bb1ddbaee629986ec774f \ No newline at end of file +dms_commit_id=bab6de2189a9022f282f6331ce93427db7c30bed +dss_commit_id=eee3cd7bfe8b0f3b4a11b77a890ca2aa08ac1dc8 +cbb_commit_id=b6c918a4262833c44e66f898e1e32f4e34dd9f6c \ No newline at end of file diff --git a/src/gausskernel/optimizer/commands/dbcommands.cpp b/src/gausskernel/optimizer/commands/dbcommands.cpp index 45d0a25bc56048439a582e6b60dbe163c9faac98..1ccb6fa92b52b7810b3cbc59e3e881fcfc366d34 100644 --- a/src/gausskernel/optimizer/commands/dbcommands.cpp +++ b/src/gausskernel/optimizer/commands/dbcommands.cpp @@ -810,11 +810,8 @@ void check_encoding_locale_matches(int encoding, const char* collate, const char int ctype_encoding; int collate_encoding; - AutoMutexLock localeLock(&gLocaleMutex); - localeLock.lock(); ctype_encoding = pg_get_encoding_from_locale(ctype, true); collate_encoding = pg_get_encoding_from_locale(collate, true); - localeLock.unLock(); if (!(ctype_encoding == encoding || ctype_encoding == PG_SQL_ASCII || ctype_encoding == -1 || #ifdef WIN32 diff --git a/src/gausskernel/optimizer/commands/dropcmds.cpp b/src/gausskernel/optimizer/commands/dropcmds.cpp index 9efe0095d7c0d66aa99d4ef7d8d54cba03bc5b81..f68c705630fa57cf4a64a7322394bd6b8e45b67e 100644 --- a/src/gausskernel/optimizer/commands/dropcmds.cpp +++ b/src/gausskernel/optimizer/commands/dropcmds.cpp @@ -79,7 +79,7 @@ static void DropExtensionInListIsSupported(List* objname) "postgis", "packages", "ndpplugin", - "vector", + "datavec", #ifndef ENABLE_MULTIPLE_NODES "mysql_fdw", "oracle_fdw", @@ -92,6 +92,7 @@ static void DropExtensionInListIsSupported(List* objname) "db_pg_parser", "hdfs_fdw", "age", + "gms_profiler" #endif }; int len = lengthof(supportList); diff --git a/src/gausskernel/optimizer/commands/functioncmds.cpp b/src/gausskernel/optimizer/commands/functioncmds.cpp index a62451b94170e16e23e4edbaff4b21f5fc326a6f..d69de2aa5a24d83148e3883ae42910272d6bfbe3 100644 --- a/src/gausskernel/optimizer/commands/functioncmds.cpp +++ b/src/gausskernel/optimizer/commands/functioncmds.cpp @@ -1080,6 +1080,13 @@ ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, if (HeapTupleIsValid(tuple)) { Form_gs_package pkgform = (Form_gs_package)GETSTRUCT(tuple); namespaceId = pkgform->pkgnamespace; + if (schemaname != NULL) { + Oid func_namespaceid = get_namespace_oid(schemaname, true); + if (namespaceId != func_namespaceid) { + ereport(ERROR, (errcode(ERRCODE_INVALID_SCHEMA_NAME), + errmsg("The namespace of functions or procedures within a package needs to be consistent with the package it belongs."))); + } + } } else { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PACKAGE), errmsg("package not found"))); } @@ -1632,7 +1639,7 @@ void RemoveFunctionById(Oid funcOid) #ifndef ENABLE_MULTIPLE_NODES GsDependObjDesc func_head_obj; - if (t_thrd.proc->workingVersionNum >= SUPPORT_GS_DEPENDENCY_VERSION_NUM) { + if (enable_plpgsql_gsdependency_guc()) { Oid pro_namespace = procedureStruct->pronamespace; bool is_null; Datum pro_package_id_datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_packageid, &is_null); @@ -1681,7 +1688,7 @@ void RemoveFunctionById(Oid funcOid) pfree_ext(funcName); #endif #ifndef ENABLE_MULTIPLE_NODES - if (t_thrd.proc->workingVersionNum >= SUPPORT_GS_DEPENDENCY_VERSION_NUM) { + if (enable_plpgsql_gsdependency_guc()) { CommandCounterIncrement(); func_head_obj.type = GSDEPEND_OBJECT_TYPE_PROCHEAD; gsplsql_remove_dependencies_object(&func_head_obj); diff --git a/src/gausskernel/optimizer/commands/lockcmds.cpp b/src/gausskernel/optimizer/commands/lockcmds.cpp index 66e4e4681a7e97b9ee4d6465dfcad62ac4b153c1..cd4a11ecf0440ccf1edc4f79bef5f8acb53500ac 100644 --- a/src/gausskernel/optimizer/commands/lockcmds.cpp +++ b/src/gausskernel/optimizer/commands/lockcmds.cpp @@ -57,7 +57,18 @@ void LockTableCommand(LockStmt* lockstmt) * Iterate over the list and process the named relations one at a time */ foreach (p, lockstmt->relations) { - RangeVar* rv = (RangeVar*)lfirst(p); + RangeVar* rv = NULL; + List* rv_lockmode = NULL; + if (u_sess->attr.attr_sql.dolphin && lockstmt->mode == NoLock){ + // here p is a [releation,lock_mode] list + rv_lockmode = (List*)lfirst(p); + rv = (RangeVar*)linitial(rv_lockmode); + int *mode = (int*)lsecond(rv_lockmode); + lockstmt->mode = *mode; + } else { + rv = (RangeVar*)lfirst(p); + } + bool recurse = interpretInhOption(rv->inhOpt); Oid reloid; diff --git a/src/gausskernel/optimizer/commands/prepare.cpp b/src/gausskernel/optimizer/commands/prepare.cpp index 63076ab368c1f5bb7c6cec5fd496fd3af8870127..78ae86ca49261de0ece230d5ebb34a12290a1cae 100755 --- a/src/gausskernel/optimizer/commands/prepare.cpp +++ b/src/gausskernel/optimizer/commands/prepare.cpp @@ -199,6 +199,7 @@ void PrepareQuery(PrepareStmt* stmt, const char* queryString) int nargs; Query* query = NULL; List* query_list = NIL; + bool fixed_result = FORCE_VALIDATE_PLANCACHE_RESULT; int i; /* @@ -324,7 +325,7 @@ void PrepareQuery(PrepareStmt* stmt, const char* queryString) NULL, NULL, 0, /* default cursor options */ - true, /* fixed result */ + fixed_result, /* fixed result */ stmt->name); /* @@ -376,9 +377,9 @@ void ExecuteQuery(ExecuteStmt* stmt, IntoClause* intoClause, const char* querySt t_thrd.postgres_cxt.cur_command_tag = transform_node_tag(psrc->raw_parse_tree); /* Shouldn't find a non-fixed-result cached plan */ - if (!entry->plansource->fixed_result) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("EXECUTE does not support variable-result cached plans"))); + if (!entry->plansource->fixed_result && FORCE_VALIDATE_PLANCACHE_RESULT) + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("EXECUTE does not support variable-result cached plans"))); /* Evaluate parameters, if any */ if (entry->plansource->num_params > 0) { @@ -1087,10 +1088,16 @@ bool HaveActiveCoordinatorPreparedStatement(const char* stmt_name) TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt) { /* - * Since we don't allow prepared statements' result tupdescs to change, - * there's no need to worry about revalidating the cached plan here. + * User are allowed to change the result type of plan cache + * on the fly, so make sure to revalidate the descriptor + * before we pass it to the portal. */ - Assert(stmt->plansource->fixed_result); + if (FORCE_VALIDATE_PLANCACHE_RESULT) { + Assert(stmt->plansource->fixed_result); + } else { + RevalidateCachedQuery(stmt->plansource); + } + if (stmt->plansource->resultDesc) return CreateTupleDescCopy(stmt->plansource->resultDesc); else @@ -1414,11 +1421,9 @@ CachedPlanSource* GetCachedPlanSourceFromExplainExecute(const char* stmt_name) Assert(psrc != NULL); /* Shouldn't find a non-fixed-result cached plan */ - if (!psrc->fixed_result) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("EXPLAIN EXECUTE does not support variable-result cached plans"))); - } + if (!psrc->fixed_result && FORCE_VALIDATE_PLANCACHE_RESULT) + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("EXPLAIN EXECUTE does not support variable-result cached plans"))); return psrc; } diff --git a/src/gausskernel/optimizer/commands/sequence/sequence.cpp b/src/gausskernel/optimizer/commands/sequence/sequence.cpp index 13c0b537b9d793d68c771307d1d346d6788e95c2..7c101598d08c5e44d7195e12ca67530de53de26c 100644 --- a/src/gausskernel/optimizer/commands/sequence/sequence.cpp +++ b/src/gausskernel/optimizer/commands/sequence/sequence.cpp @@ -1451,8 +1451,7 @@ int128 nextval_internal(Oid relid) TrForbidAccessRbObject(RelationRelationId, relid, RelationGetRelationName(seqrel)); - if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK && - pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK) + if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE | ACL_UPDATE) != ACLCHECK_OK) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied for sequence %s", RelationGetRelationName(seqrel)))); @@ -1524,8 +1523,7 @@ Datum currval_oid(PG_FUNCTION_ARGS) TrForbidAccessRbObject(RelationRelationId, relid, RelationGetRelationName(seqrel)); - if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK && - pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK) + if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT | ACL_USAGE) != ACLCHECK_OK) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied for sequence %s", RelationGetRelationName(seqrel)))); @@ -1570,8 +1568,7 @@ Datum lastval(PG_FUNCTION_ARGS) /* nextval() must have already been called for this sequence */ Assert(u_sess->cmd_cxt.last_used_seq->last_valid); - if (pg_class_aclcheck(u_sess->cmd_cxt.last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK && - pg_class_aclcheck(u_sess->cmd_cxt.last_used_seq->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK) + if (pg_class_aclcheck(u_sess->cmd_cxt.last_used_seq->relid, GetUserId(), ACL_SELECT | ACL_USAGE) != ACLCHECK_OK) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied for sequence %s", RelationGetRelationName(seqrel)))); diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index fc06c37d5fe761d93aaae7dc9d389e72eeb1fe3f..9e59aa6cf6259cb3c2eaf77322cd2064b8d55f5e 100755 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -681,6 +681,7 @@ static void ATExecUnusableIndex(Relation rel); static void ATUnusableGlobalIndex(Relation rel); static void ATExecUnusableAllIndexOnPartition(Relation rel, const char* partition_name); static void ATExecVisibleIndex(Relation rel, char* index_name, bool visible); +static void ATExecVisibleIndexDirect(Relation rel, bool visible); static void ATExecModifyRowMovement(Relation rel, bool rowMovement); static void ATExecTruncatePartition(Relation rel, AlterTableCmd* cmd); static void ATExecTruncateSubPartition(Relation rel, AlterTableCmd* cmd); @@ -829,6 +830,8 @@ inline static bool CStoreSupportATCmd(AlterTableType cmdtype) #endif case AT_VisibleIndex: case AT_InvisibleIndex: + case AT_InvisibleIndexDirect: + case AT_VisibleIndexDirect: ret = true; break; default: @@ -2979,6 +2982,7 @@ ObjectAddress DefineRelation(CreateStmt* stmt, char relkind, Oid ownerId, Object ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Only support segment storage type while parameter enable_segment is ON."))); } + CheckSegmentCompressOption(stmt->options, relkind, storage_type, storeChar); /* * Create the relation. Inherited defaults and constraints are passed in @@ -8431,6 +8435,8 @@ static void ATPrepCmd(List** wqueue, Relation rel, AlterTableCmd* cmd, bool recu case AT_ReplaceRelOptions: /* reset them all, then set just these */ case AT_InvisibleIndex: case AT_VisibleIndex: + case AT_InvisibleIndexDirect: + case AT_VisibleIndexDirect: ATSimplePermissions(rel, ATT_TABLE | ATT_INDEX | ATT_VIEW); /* This command never recurses */ /* No command-specific prep needed */ @@ -9059,6 +9065,12 @@ static void ATExecCmd(List** wqueue, AlteredTableInfo* tab, Relation rel, AlterT case AT_VisibleIndex: ATExecVisibleIndex(rel, cmd->name, true); break; + case AT_InvisibleIndexDirect: + ATExecVisibleIndexDirect(rel, false); + break; + case AT_VisibleIndexDirect: + ATExecVisibleIndexDirect(rel, true); + break; case AT_AddIndex: /* ADD INDEX */ address = ATExecAddIndex(tab, rel, (IndexStmt*)cmd->def, false, lockmode); break; @@ -19617,8 +19629,8 @@ static void copy_relation_data(Relation rel, SMgrRelation* dstptr, ForkNumber fo /* We should not remove the data to the limited tablespace under segment mode. */ if (u_sess->cmd_cxt.l_isLimit) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmodule(MOD_SEGMENT_PAGE), - errmsg("Dont support relation movement to limited tablespace segment-page storage!"), - errdetail("Segment-page storage doest not support limited tablespace \"%s\"", get_tablespace_name(newFileNode.spcNode)), + errmsg("Don't support moving relation to limited tablespace in segment-page storage!"), + errdetail("Segment-page storage does not support limited tablespace \"%s\"", get_tablespace_name(newFileNode.spcNode)), errhint("use default or unlimited user defined tablespace before using segment-page storage."))); } } else { @@ -25222,6 +25234,8 @@ static void ATUnusableGlobalIndex(Relation rel) CacheInvalidateRelcache(rel); CommandCounterIncrement(); } + + ereport(NOTICE, (errmsg("Command without UPDATE GLOBAL INDEX will disable global index"))); } /* @@ -25422,6 +25436,18 @@ static void ATExecVisibleIndex(Relation rel, char* index_name, bool visible) } } +static void ATExecVisibleIndexDirect(Relation rel, bool visible) +{ + if (RelationIsIndex(rel) && OidIsValid(rel->rd_id)) { + ATExecSetIndexVisibleState(rel->rd_id, visible); + } else { + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("can not set visible for relation %s, as it is not a index", + RelationGetRelationName(rel)))); + } +} + /* * @@GaussDB@@ * Target : data partition @@ -33060,7 +33086,6 @@ static void ATExecAlterModifyColumn(AlteredTableInfo* tab, Relation rel, AlterTa pg_attr->attcollation = collid; pg_attr->attnotnull = def->is_not_null; pg_attr->attislocal = def->is_local; - pg_attr->attkvtype = def->kvtype; pg_attr->attinhcount = def->inhcount; pg_attr->atthasdef = false; ReleaseSysCache(type_tuple); diff --git a/src/gausskernel/optimizer/commands/trigger.cpp b/src/gausskernel/optimizer/commands/trigger.cpp index 0503f1e87550123b72ab4a9cc3e23feb437304b6..6b86257f46aa6cda21accb199a8f3548c0c72322 100644 --- a/src/gausskernel/optimizer/commands/trigger.cpp +++ b/src/gausskernel/optimizer/commands/trigger.cpp @@ -85,6 +85,11 @@ (bms_union(exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->updatedCols, \ exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->extraUpdatedCols)) +#define B_TRIGGER_INLINE_STR "inlinefunc" +#define B_TRIGGER_INLINE_LENGTH 10 +#define B_TRIGGER_ID_LENGTH 8 /* for 65535 max = 5 chars, 3 '_' length total 8 */ +#define B_TRIGGER_ID_MAX 65530 /* max id search time we will report error */ + /* Local function prototypes */ static void ConvertTriggerToFK(CreateTrigStmt* stmt, Oid funcoid); static void SetTriggerFlags(TriggerDesc* trigdesc, const Trigger* trigger); @@ -96,6 +101,7 @@ static HeapTuple ExecCallTriggerFunc( static void AfterTriggerSaveEvent(EState* estate, ResultRelInfo* relinfo, uint32 event, bool row_trigger, Oid oldPartitionOid, Oid newPartitionOid, int2 bucketid, HeapTuple oldtup, HeapTuple newtup, List* recheckIndexes, Bitmapset* modifiedCols); +static char* rebuild_funcname_for_b_trigger(char* trigname, char* relname); #ifdef PGXC static bool pgxc_should_exec_triggers( Relation rel, uint16 tgtype_event, int16 tgtype_level, int16 tgtype_timing, EState* estate = NULL); @@ -537,10 +543,10 @@ ObjectAddress CreateTrigger(CreateTrigStmt* stmt, const char* queryString, Oid r n->isPrivate = false; n->replace = false; n->definer = stmt->definer; - size_t funcNameLen = strlen(stmt->trigname) + strlen(stmt->relation->relname) + strlen("__inlinefunc") + 1; - char* funcNameTmp = (char*)palloc(funcNameLen); - ret = snprintf_s(funcNameTmp,funcNameLen, funcNameLen-1, "%s_%s_inlinefunc",stmt->trigname,stmt->relation->relname); - securec_check_ss(ret, "\0", "\0"); + char* trigname = pstrdup(stmt->trigname); + char* relname = pstrdup(stmt->relation->relname); + /* means we need to rebuild the function name */ + char* funcNameTmp = rebuild_funcname_for_b_trigger(trigname, relname); n->funcname = list_make1(makeString(funcNameTmp)); n->parameters = NULL; n->returnType = makeTypeName("trigger"); @@ -6319,3 +6325,54 @@ void ResetTrigShipFlag() } } +/* build a function name for b format trigger */ +static char* rebuild_funcname_for_b_trigger(char* trigname, char* relname) +{ + uint16 uid = 0; + char* funcname = NULL; + int ret = 0; + size_t funcNameLen = strlen(trigname) + strlen(relname) + B_TRIGGER_INLINE_LENGTH + B_TRIGGER_ID_LENGTH + 1; + size_t halfPos = (NAMEDATALEN - B_TRIGGER_INLINE_LENGTH - B_TRIGGER_ID_LENGTH) / 2 - 1; + /* reset overflow length */ + if (funcNameLen >= NAMEDATALEN) { + /* we have to reduce name string for oversize */ + if (strlen(trigname) > halfPos) { + trigname[halfPos - 1] = '\0'; + } + + if (strlen(relname) > halfPos) { + relname[halfPos - 1] = '\0'; + } + funcNameLen = strlen(trigname) + strlen(relname) + B_TRIGGER_INLINE_LENGTH + B_TRIGGER_ID_LENGTH + 1; + } + funcname = (char*)palloc0(sizeof(char) * funcNameLen); + CatCList* catlist = NULL; + do { + if (uid++ > B_TRIGGER_ID_MAX) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("You cannot create the trigger function because there are too many name conflicts."), + errdetail("We need to build a function internal, please rename the trigger."))); + } + ret = snprintf_s(funcname, funcNameLen, funcNameLen - 1, "%s_%s_%s_%hu", trigname, relname, B_TRIGGER_INLINE_STR, uid); + securec_check_ss(ret, "\0", "\0"); + if (t_thrd.proc->workingVersionNum < 92470) { + catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname)); + } else { + catlist = SearchSysCacheList1(PROCALLARGS, CStringGetDatum(funcname)); + } + if (catlist != NULL) { + if (catlist->n_members > 0) + ReleaseSysCacheList(catlist); + else { + ReleaseSysCacheList(catlist); + break; + } + } else { + break; + } + + } while (true); + + return funcname; +} \ No newline at end of file diff --git a/src/gausskernel/optimizer/commands/typecmds.cpp b/src/gausskernel/optimizer/commands/typecmds.cpp index 099778782bd196be4c5c413de4cba6b2413f8558..c4c792ea3ceab4f0ef6eb15f0eaeda147d350075 100644 --- a/src/gausskernel/optimizer/commands/typecmds.cpp +++ b/src/gausskernel/optimizer/commands/typecmds.cpp @@ -649,7 +649,7 @@ void RemoveTypeById(Oid typeOid) { #ifndef ENABLE_MULTIPLE_NODES GsDependObjDesc ref_obj; - if (t_thrd.proc->workingVersionNum >= SUPPORT_GS_DEPENDENCY_VERSION_NUM) { + if (enable_plpgsql_gsdependency_guc()) { gsplsql_init_gs_depend_obj_desc(&ref_obj); char relkind = get_rel_relkind(typeOid); if (relkind == RELKIND_COMPOSITE_TYPE || relkind == '\0') { @@ -700,29 +700,26 @@ void RemoveTypeById(Oid typeOid) heap_close(relation, RowExclusiveLock); #ifndef ENABLE_MULTIPLE_NODES - if (t_thrd.proc->workingVersionNum >= SUPPORT_GS_DEPENDENCY_VERSION_NUM && NULL != ref_obj.name) { + if (enable_plpgsql_gsdependency_guc() && NULL != ref_obj.name) { CommandCounterIncrement(); + (void)gsplsql_remove_ref_dependency(&ref_obj); ref_obj.refPosType = GSDEPEND_REFOBJ_POS_IN_TYPE; - gsplsql_remove_type_gs_dependency(&ref_obj); - if (enable_plpgsql_gsdependency_guc()) { - ref_obj.type = GSDEPEND_OBJECT_TYPE_TYPE; - (void)gsplsql_remove_ref_dependency(&ref_obj); - Oid pkg_oid = GetTypePackageOid(typeOid); - if (OidIsValid(pkg_oid)) { - bool invalid_pkg = true; - if (NULL != u_sess->plsql_cxt.curr_compile_context && - NULL != u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package) { - invalid_pkg = pkg_oid == - u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_oid; - } - if (invalid_pkg) { - bool is_spec = ref_obj.name[0] != '$'; - SetPgObjectValid(pkg_oid, is_spec ? OBJECT_TYPE_PKGSPEC : OBJECT_TYPE_PKGBODY, false); - if (is_spec) { - SetPgObjectValid(pkg_oid, OBJECT_TYPE_PKGBODY, false); - } - gsplsql_set_pkg_func_status(GetPackageNamespace(pkg_oid), pkg_oid, false); + (void)gsplsql_remove_gs_dependency(&ref_obj); + Oid pkg_oid = GetTypePackageOid(typeOid); + if (OidIsValid(pkg_oid)) { + bool invalid_pkg = true; + if (NULL != u_sess->plsql_cxt.curr_compile_context && + NULL != u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package) { + invalid_pkg = pkg_oid == + u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_oid; + } + if (invalid_pkg) { + bool is_spec = ref_obj.name[0] != '$'; + SetPgObjectValid(pkg_oid, is_spec ? OBJECT_TYPE_PKGSPEC : OBJECT_TYPE_PKGBODY, false); + if (is_spec) { + SetPgObjectValid(pkg_oid, OBJECT_TYPE_PKGBODY, false); } + gsplsql_set_pkg_func_status(GetPackageNamespace(pkg_oid), pkg_oid, false); } } pfree_ext(ref_obj.schemaName); diff --git a/src/gausskernel/optimizer/path/allpaths.cpp b/src/gausskernel/optimizer/path/allpaths.cpp index cb7b1221f4fa534e5a875714a8d1f5d0dcb8e953..e1ee3151252fa0695dd35fe96ad105a926b6c685 100755 --- a/src/gausskernel/optimizer/path/allpaths.cpp +++ b/src/gausskernel/optimizer/path/allpaths.cpp @@ -68,7 +68,7 @@ const int max_parallel_maintenance_workers = 32; static bool check_func_walker(Node* node, bool* found); static bool check_func(Node* node); -static void set_base_rel_pathlists(PlannerInfo* root); +static void set_base_rel_pathlists(PlannerInfo* root, Relids non_keypreserved); static void set_correlated_rel_pathlist(PlannerInfo* root, RelOptInfo* rel); static void set_rel_pathlist(PlannerInfo* root, RelOptInfo* rel, Index rti, RangeTblEntry* rte); static void set_plain_rel_size(PlannerInfo* root, RelOptInfo* rel, RangeTblEntry* rte); @@ -183,7 +183,7 @@ static inline void updateRelOptInfoMinSecurity(RelOptInfo* rel) * Finds all possible access paths for executing a query, returning a * single rel that represents the join of all base rels in the query. */ -RelOptInfo* make_one_rel(PlannerInfo* root, List* joinlist) +RelOptInfo* make_one_rel(PlannerInfo* root, List* joinlist, Relids non_keypreserved) { RelOptInfo* rel = NULL; int rti; @@ -283,7 +283,7 @@ RelOptInfo* make_one_rel(PlannerInfo* root, List* joinlist) u_sess->opt_cxt.op_work_mem = Min(root->glob->estiopmem, OPT_MAX_OP_MEM); Assert(u_sess->opt_cxt.op_work_mem > 0); } - set_base_rel_pathlists(root); + set_base_rel_pathlists(root, non_keypreserved); u_sess->opt_cxt.op_work_mem = work_mem_orig; root->glob->estiopmem = esti_op_mem_orig; @@ -459,11 +459,16 @@ static Path *make_predpush_subpath(PlannerInfo* root, RelOptInfo* rel, Path *pat * Sequential scan and any available indices are considered. * Each useful path is attached to its relation's 'pathlist' field. */ -static void set_base_rel_pathlists(PlannerInfo* root) +static void set_base_rel_pathlists(PlannerInfo* root, Relids non_keypreserved) { int rti; - - for (rti = 1; rti < root->simple_rel_array_size; rti++) { + TableSampleClause* tsc= NULL; + bool needTablesample = root->simple_rel_array[1] == NULL && root->simple_rte_array[1]->tablesample != NULL; + int pos = bms_first_member(non_keypreserved); + if (needTablesample) { + tsc = root->simple_rte_array[1]->tablesample; + } + for (rti = root->simple_rel_array_size - 1; rti >= 1; rti--) { RelOptInfo* rel = root->simple_rel_array[rti]; RangeTblEntry* rte = root->simple_rte_array[rti]; @@ -476,7 +481,10 @@ static void set_base_rel_pathlists(PlannerInfo* root) /* ignore RTEs that are "other rels" */ if (rel->reloptkind != RELOPT_BASEREL) continue; - + if ((pos == -1 || pos == rti) && needTablesample && !rte->tablesample) { + rte->tablesample = tsc; + pos = 0; + } set_rel_pathlist(root, rel, rti, root->simple_rte_array[rti]); /* diff --git a/src/gausskernel/optimizer/plan/initsplan.cpp b/src/gausskernel/optimizer/plan/initsplan.cpp index 21a407fa0561f3643a46d1b7bab2702213845db4..0a280203d122a7ef9fe67e074433123532e609e3 100644 --- a/src/gausskernel/optimizer/plan/initsplan.cpp +++ b/src/gausskernel/optimizer/plan/initsplan.cpp @@ -34,6 +34,8 @@ #include "parser/parsetree.h" #include "rewrite/rewriteManip.h" #include "utils/lsyscache.h" +#include "catalog/index.h" +#include "catalog/pg_amop.h" /* Elements of the postponed_qual_list used during deconstruct_recurse */ typedef struct PostponedQual @@ -43,7 +45,7 @@ typedef struct PostponedQual } PostponedQual; static void extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex); static List* deconstruct_recurse( - PlannerInfo* root, Node* jtnode, bool below_outer_join, Relids* qualscope, Relids* inner_join_rels, List **postponed_qual_list); + PlannerInfo* root, Node* jtnode, bool below_outer_join, Relids* qualscope, Relids* inner_join_rels, List **postponed_qual_list, Relids* non_keypreserved = NULL); static SpecialJoinInfo* make_outerjoininfo( PlannerInfo* root, Relids left_rels, Relids right_rels, Relids inner_join_rels, JoinType jointype, List* clause); static bool check_outerjoin_delay(PlannerInfo* root, Relids* relids_p, Relids* nullable_relids_p, bool is_pushed_down); @@ -462,7 +464,7 @@ void add_lateral_info(PlannerInfo *root, Index rhs, Relids lhs) * clauses appearing above it. This forces those clauses to be delayed until * application of the outer join (or maybe even higher in the join tree). */ -List* deconstruct_jointree(PlannerInfo* root) +List* deconstruct_jointree(PlannerInfo* root, Relids* non_keypreserved) { List *result = NIL; Relids qualscope = NULL; @@ -474,7 +476,7 @@ List* deconstruct_jointree(PlannerInfo* root) root->parse->jointree != NULL && IsA(root->parse->jointree, FromExpr), MOD_OPT, "From expression is required."); result = deconstruct_recurse(root, (Node *) root->parse->jointree, false, - &qualscope, &inner_join_rels, &postponed_qual_list); + &qualscope, &inner_join_rels, &postponed_qual_list, non_keypreserved); /* Shouldn't be any leftover quals */ Assert(postponed_qual_list == NIL); @@ -529,6 +531,228 @@ static void process_security_barrier_quals( Assert(security_level <= root->qualSecurityLevel); } +#define JATTR_TAB_HASH_SIZE 64 + +typedef struct JoinAttrEntry { + Index relidx; + Bitmapset* attrs; +} JoinAttrEntry; + +static bool is_equals_operator(int operid) +{ + bool result = false; + CatCList* catlist = NULL; + int i; + /* + * Search pg_amop to see if the operid is registered as the "=" + */ + catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(operid)); + for (i = 0; i < catlist->n_members; i++) { + HeapTuple tuple = t_thrd.lsc_cxt.FetchTupleFromCatCList(catlist, i); + Form_pg_amop aform = (Form_pg_amop)GETSTRUCT(tuple); + if (aform->amopstrategy == BTEqualStrategyNumber) { + result = true; + break; + } + } + ReleaseSysCacheList(catlist); + return result; + +} + +static bool rel_is_member_of_non_keypreserved(PlannerInfo* root, Index relidx, Relids non_keypreserved) +{ + Relids tmpset = bms_copy(non_keypreserved); + int x = 0; + Oid relid = root->simple_rte_array[relidx]->relid; + while ((x = bms_first_member(tmpset)) >= 0) { + if (relid == root->simple_rte_array[x]->relid) { + bms_free_ext(tmpset); + return true; + } + } + bms_free_ext(tmpset); + return false; +} + +static void find_non_keypreservered_rels(PlannerInfo* root, HTAB* htab, Relids* non_keypreserved, + JoinType type, RangeTblRef* leftpart, RangeTblRef* rightpart) +{ + HASH_SEQ_STATUS status; + JoinAttrEntry *entry = NULL; + hash_seq_init(&status, htab); + bool left_is_key_preserved = true; + bool right_is_key_preserved = true; + while ((entry = (JoinAttrEntry *) hash_seq_search(&status)) != NULL) { + if (bms_num_members(*non_keypreserved) > 1) { + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("Cannot sample a join view without a key-preserved table"))); + } + Index relidx = entry->relidx; + Oid relid = root->simple_rte_array[relidx]->relid; + Relids jattrs = entry->attrs; + Relation relation = relation_open(relid, AccessShareLock); + Assert(!RelationIsBucket(relation) && !RelationIsPartition(relation)); + /* Fast path if definitely no indexes */ + if (!RelationGetForm(relation)->relhasindex) { + *non_keypreserved = bms_add_member(*non_keypreserved, relidx); + relation_close(relation, AccessShareLock); + continue; + } + List* indexoidlist = NIL; + ListCell* l = NULL; + Oid relpkindex; + bool is_key_preserved = false; + /* Get cached list of index OIDs */ + indexoidlist = RelationGetIndexList(relation); + /* Fall out if no indexes (but relhasindex was set) */ + if (indexoidlist == NIL) { + *non_keypreserved = bms_add_member(*non_keypreserved, relidx); + relation_close(relation, AccessShareLock); + continue; + } + relpkindex = relation->rd_pkindex; + foreach (l, indexoidlist) { + Oid indexOid = lfirst_oid(l); + Relation indexDesc; + IndexInfo* indexInfo = NULL; + int i; + bool isKey = false; /* candidate key */ + bool isPK; /* primary key */ + Bitmapset* uindexattrs = NULL; + Bitmapset* pkindexattrs = NULL; /* columns in the primary index */ + indexDesc = index_open(indexOid, AccessShareLock); + /* Extract index key information from the index's pg_index row */ + indexInfo = BuildIndexInfo(indexDesc); + /* Is this a primary key? */ + isPK = (indexOid == relpkindex); + /* Can this index be referenced by a foreign key? */ + isKey = indexInfo->ii_Unique && indexInfo->ii_Expressions == NIL && indexInfo->ii_Predicate == NIL; + if (!isPK && !isKey) { + index_close(indexDesc, AccessShareLock); + continue; + } + /* Collect simple attribute references */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) { + int attrnum = indexInfo->ii_KeyAttrNumbers[i]; + if (attrnum != 0) { + if (isKey && i < indexInfo->ii_NumIndexKeyAttrs) { + uindexattrs = bms_add_member(uindexattrs, attrnum); + } + if (isPK) { + pkindexattrs = bms_add_member(pkindexattrs, attrnum); + } + } + } + index_close(indexDesc, AccessShareLock); + if ((!bms_is_empty(uindexattrs) && bms_is_subset(uindexattrs, jattrs)) || + (!bms_is_empty(pkindexattrs) && bms_is_subset(pkindexattrs, jattrs))) { /* the rel is key-preserved*/ + is_key_preserved = true; + break; + } + } + if (leftpart && !is_key_preserved && relidx == leftpart->rtindex) { + left_is_key_preserved = false; + } + if (rightpart && !is_key_preserved && relidx == rightpart->rtindex) { + right_is_key_preserved = false; + } + if ((!is_key_preserved && rel_is_member_of_non_keypreserved(root, relidx, *non_keypreserved)) || + (type == JOIN_LEFT && !right_is_key_preserved) || + (type == JOIN_INNER && !right_is_key_preserved && !left_is_key_preserved)) { + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("Cannot sample a join view without a key-preserved table"))); + } + if (!is_key_preserved) { + *non_keypreserved = bms_add_member(*non_keypreserved, relidx); + } + relation_close(relation, AccessShareLock); + } +} + +static void handle_join_view_operand(PlannerInfo* root, Var* operand, HTAB* htab, RangeTblRef* rtref) +{ + if (!rtref) { + return; + } + Index varno = ((Var*)operand)->varno; + AttrNumber varattno = ((Var*)operand)->varattno; + RangeTblEntry* rte = root->simple_rte_array[varno]; + JoinAttrEntry* attrentry = NULL; + Bitmapset* attrs; + Assert(rte->rtekind == RTE_RELATION); + bool found = false; + /* Lookup current element in hashtable, adding it if new */ + attrentry = (JoinAttrEntry*)hash_search(htab, &varno, HASH_ENTER, &found); + if (found) { + attrs = attrentry->attrs; + attrs = bms_add_member(attrs, varattno); + } else { + attrs = bms_make_singleton(varattno); + attrentry->attrs = attrs; + } +} + +static void check_join_view_quals(PlannerInfo* root, List* quals, Relids* non_keypreserved, + JoinType type, RangeTblRef* leftpart, RangeTblRef* rightpart) +{ + HASHCTL ctl; + HTAB* htab = NULL; + errno_t rc = EOK; + rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); + securec_check(rc, "\0", "\0"); + MemoryContext tmp_hash_context = AllocSetContextCreate(CurrentMemoryContext, + "hashtable temporary context", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + ctl.keysize = sizeof(Index); + ctl.entrysize = sizeof(JoinAttrEntry); + ctl.hash = oid_hash; + ctl.hcxt = tmp_hash_context; + htab = hash_create( + "table's attrs of quals", JATTR_TAB_HASH_SIZE, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + ListCell* l; + foreach (l, quals) { + Node* qual = (Node*)lfirst(l); + Node* left_operand; + Node* right_operand; + VariableStatData leftvar; + VariableStatData rightvar; + /* If it's a binary opclause, check operator and operand*/ + if (is_opclause(qual) && list_length(((OpExpr*)qual)->args) == 2) { + Oid opno = ((OpExpr*)qual)->opno; + left_operand = get_leftop((Expr*)qual); + right_operand = get_rightop((Expr*)qual); + examine_variable(root, left_operand, 0, &leftvar); + examine_variable(root, right_operand, 0, &rightvar); + if (is_equals_operator(opno)) { /* equal operator */ + if (IsA(leftvar.var, Var) && IsA(rightvar.var, Var)) { + handle_join_view_operand(root, (Var*)leftvar.var, htab, leftpart); + handle_join_view_operand(root, (Var*)rightvar.var, htab, rightpart); + } else if (IsA(leftvar.var, Var) && IsA(rightvar.var, Const)) { + handle_join_view_operand(root, (Var*)leftvar.var, htab, leftpart); + } else if (IsA(rightvar.var, Var) && IsA(leftvar.var, Const)) { + handle_join_view_operand(root, (Var*)rightvar.var, htab, rightpart); + } else { + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("Cannot sample a join view without a key-preserved table"))); + } + } + } + ReleaseVariableStats(leftvar); + ReleaseVariableStats(rightvar); + } + /* Check if at most one of the tables associated with the current join is non-key-prereserved */ + find_non_keypreservered_rels(root, htab, non_keypreserved, type, leftpart, rightpart); + if (bms_num_members(*non_keypreserved) > 1) { + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("Cannot sample a join view without a key-preserved table"))); + } + /* Done with the hash table. */ + hash_destroy(htab); +} + /* * deconstruct_recurse * One recursion level of deconstruct_jointree processing. @@ -550,7 +774,7 @@ static void process_security_barrier_quals( */ static List* deconstruct_recurse(PlannerInfo* root, Node* jtnode, bool below_outer_join, Relids* qualscope, - Relids* inner_join_rels, List **postponed_qual_list) + Relids* inner_join_rels, List **postponed_qual_list, Relids* non_keypreserved) { List* joinlist = NIL; @@ -592,7 +816,7 @@ static List* deconstruct_recurse(PlannerInfo* root, Node* jtnode, int sub_members; sub_joinlist = deconstruct_recurse(root, (Node*)lfirst(l), below_outer_join, - &sub_qualscope, inner_join_rels, &child_postponed_quals); + &sub_qualscope, inner_join_rels, &child_postponed_quals, non_keypreserved); *qualscope = bms_add_members(*qualscope, sub_qualscope); sub_members = list_length(sub_joinlist); remaining--; @@ -665,10 +889,10 @@ static List* deconstruct_recurse(PlannerInfo* root, Node* jtnode, case JOIN_INNER: leftjoinlist = deconstruct_recurse(root, j->larg, below_outer_join, &leftids, &left_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); rightjoinlist = deconstruct_recurse(root, j->rarg, below_outer_join, &rightids, &right_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); *qualscope = bms_union(leftids, rightids); *inner_join_rels = *qualscope; /* Inner join adds no restrictions for quals */ @@ -679,10 +903,10 @@ static List* deconstruct_recurse(PlannerInfo* root, Node* jtnode, case JOIN_LEFT_ANTI_FULL: leftjoinlist = deconstruct_recurse(root, j->larg, below_outer_join, &leftids, &left_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); rightjoinlist = deconstruct_recurse(root, j->rarg, true, &rightids, &right_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); *qualscope = bms_union(leftids, rightids); *inner_join_rels = bms_union(left_inners, right_inners); nonnullable_rels = leftids; @@ -690,10 +914,10 @@ static List* deconstruct_recurse(PlannerInfo* root, Node* jtnode, case JOIN_SEMI: leftjoinlist = deconstruct_recurse(root, j->larg, below_outer_join, &leftids, &left_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); rightjoinlist = deconstruct_recurse(root, j->rarg, below_outer_join, &rightids, &right_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); *qualscope = bms_union(leftids, rightids); *inner_join_rels = bms_union(left_inners, right_inners); /* Semi join adds no restrictions for quals */ @@ -702,10 +926,10 @@ static List* deconstruct_recurse(PlannerInfo* root, Node* jtnode, case JOIN_FULL: leftjoinlist = deconstruct_recurse(root, j->larg, true, &leftids, &left_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); rightjoinlist = deconstruct_recurse(root, j->rarg, true, &rightids, &right_inners, - &child_postponed_quals); + &child_postponed_quals, non_keypreserved); *qualscope = bms_union(leftids, rightids); *inner_join_rels = bms_union(left_inners, right_inners); /* each side is both outer and inner */ @@ -723,6 +947,11 @@ static List* deconstruct_recurse(PlannerInfo* root, Node* jtnode, leftjoinlist = rightjoinlist = NIL; } break; } + if (root->simple_rel_array[1] == NULL && root->simple_rte_array[1]->tablesample != NULL) { + Node* leftpart = (list_length(leftjoinlist) == 1) ? (Node*)linitial(leftjoinlist) : NULL; + Node* rightpart = (list_length(rightjoinlist) == 1) ? (Node*)linitial(rightjoinlist) : NULL; + check_join_view_quals(root, (List*)j->quals, non_keypreserved, j->jointype, (RangeTblRef*)leftpart, (RangeTblRef*)rightpart); + } /* * For an OJ, form the SpecialJoinInfo now, because we need the OJ's diff --git a/src/gausskernel/optimizer/plan/planmain.cpp b/src/gausskernel/optimizer/plan/planmain.cpp index 1410b7a7cddcb20ea58e910778067eaaa41b0b3e..4da32633f042a5532b53b1156e1fa73cb263d970 100755 --- a/src/gausskernel/optimizer/plan/planmain.cpp +++ b/src/gausskernel/optimizer/plan/planmain.cpp @@ -79,6 +79,7 @@ RelOptInfo* query_planner(PlannerInfo* root, List* tlist, RelOptInfo* final_rel = NULL; Index rti; double total_pages; + Relids non_keypreserved = NULL; /* * Init planner lists to empty. @@ -180,7 +181,7 @@ RelOptInfo* query_planner(PlannerInfo* root, List* tlist, find_lateral_references(root); - joinlist = deconstruct_jointree(root); + joinlist = deconstruct_jointree(root, &non_keypreserved); process_security_clause_appendrel(root); @@ -276,7 +277,8 @@ RelOptInfo* query_planner(PlannerInfo* root, List* tlist, /* * Ready to do the primary planning. */ - final_rel = make_one_rel(root, joinlist); + final_rel = make_one_rel(root, joinlist, non_keypreserved); + bms_free(non_keypreserved); if (final_rel == NULL || final_rel->cheapest_total_path == NIL) { ereport(ERROR, diff --git a/src/gausskernel/optimizer/plan/planner.cpp b/src/gausskernel/optimizer/plan/planner.cpp index 1e649184bf03eabc066581207b771031d91aef1b..fff992a9e6ebd924528509ce3cc8604eebe96aeb 100755 --- a/src/gausskernel/optimizer/plan/planner.cpp +++ b/src/gausskernel/optimizer/plan/planner.cpp @@ -142,7 +142,7 @@ extern List* reassign_nodelist(RangeTblEntry* rte, List* ori_node_list); extern Node* preprocess_expression(PlannerInfo* root, Node* expr, int kind); static Plan* inheritance_planner(PlannerInfo* root); -static Plan* grouping_planner(PlannerInfo* root, double tuple_fraction); +extern Plan* grouping_planner(PlannerInfo* root, double tuple_fraction); static void preprocess_rowmarks(PlannerInfo* root); static double preprocess_limit(PlannerInfo* root, double tuple_fraction, int64* offset_est, int64* count_est); static void process_sort(Query* parse, PlannerInfo* root, PlannerTargets* plannerTargets, Plan** resultPlan, @@ -1957,10 +1957,19 @@ Plan* subquery_planner(PlannerGlobal* glob, Query* parse, PlannerInfo* parent_ro List* rowMarks = NIL; Relation mainRel = NULL; Oid taleOid = rt_fetch(linitial_int(parse->resultRelations), parse->rtable)->relid; - bool partKeyUpdated = targetListHasPartitionKey(parse->targetList, taleOid); + bool partKeyUpdated; + bool isPartitioned; + mainRel = RelationIdGetRelation(taleOid); + isPartitioned = RELATION_IS_PARTITIONED(mainRel); RelationClose(mainRel); + if (isPartitioned) { + partKeyUpdated = targetListHasPartitionKey(parse->targetList, taleOid); + } else { + partKeyUpdated = false; + } + /* * Set up the WITH CHECK OPTION and RETURNING lists-of-lists, if * needed. @@ -2761,8 +2770,8 @@ static void process_sort(Query* parse, PlannerInfo* root, PlannerTargets* planne */ if (parse->sortClause) { if (parse->is_flt_frame && parse->hasTargetSRFs) { - List* sortInputTarget = build_plan_tlist(root, plannerTargets->final_target); - (*resultPlan)->targetlist = sortInputTarget; + tlist = build_plan_tlist(root, plannerTargets->final_target); + (*resultPlan)->targetlist = tlist; } /* @@ -2848,8 +2857,12 @@ static void process_rowMarks(Query* parse, Plan** resultPlan, PlannerInfo* root, * actual output ordering of the plan (in pathkey format). * -------------------- */ -static Plan* grouping_planner(PlannerInfo* root, double tuple_fraction) +extern Plan* grouping_planner(PlannerInfo* root, double tuple_fraction) { + if(u_sess->hook_cxt.groupingplannerHook != NULL) { + return ((grouping_plannerFunc)(u_sess->hook_cxt.groupingplannerHook))(root, tuple_fraction); + } + Query* parse = root->parse; List* tlist = parse->targetList; int64 offset_est = 0; @@ -3661,13 +3674,11 @@ static Plan* grouping_planner(PlannerInfo* root, double tuple_fraction) wflists, &needSecondLevelAgg, collectiveGroupExpr); -#ifdef ENABLE_MULTIPLE_NODES /* * grouping_tlist was modified by build_groupingsets_plan, * we have to change tlist at the same time. */ tlist = grouping_tlist; -#endif /* Delete eq class expr after grouping */ delete_eq_member(root, tlist, collectiveGroupExpr); diff --git a/src/gausskernel/optimizer/plan/planstartwith.cpp b/src/gausskernel/optimizer/plan/planstartwith.cpp index 086ed2dfff21732dc2eae1261cf68132382eebd1..274e999ada8772d5835557cd8f623e6d843359ae 100644 --- a/src/gausskernel/optimizer/plan/planstartwith.cpp +++ b/src/gausskernel/optimizer/plan/planstartwith.cpp @@ -1306,6 +1306,9 @@ static bool PullUpConnectByFuncVarsWalker(Node *node, PullUpConnectByFuncVarCont prcType == SWCOL_ISCYCLE || prcType == SWCOL_ROWNUM) { MarkPRCNotSkip(context->swplan, prcType); } + } else if (IsA(node, PriorExpr)) { + Var* var = (Var*)((PriorExpr*)node)->node; + context->pullupVars = lappend(context->pullupVars, var); } return expression_tree_walker(node, diff --git a/src/gausskernel/optimizer/plan/streamwalker.cpp b/src/gausskernel/optimizer/plan/streamwalker.cpp index ee5c8be2ee561a3e20432da855ea92c49fa738e3..f85b6615d588f1c63d4d27d351b4c30e90903621 100755 --- a/src/gausskernel/optimizer/plan/streamwalker.cpp +++ b/src/gausskernel/optimizer/plan/streamwalker.cpp @@ -445,6 +445,11 @@ static void stream_walker_query(Query* query, shipping_context *cxt) /* mark shippable flag based on rte shippbility */ stream_walker_finalize_cxt(query, cxt); + if (list_length(query->resultRelations) > 1) { + /* turn off push for multiple modify */ + cxt->current_shippable = false; + } + /* Mark query's can_push and global_shippable flag. */ query->can_push = cxt->current_shippable; cxt->global_shippable = cxt->global_shippable && cxt->current_shippable; diff --git a/src/gausskernel/optimizer/plan/subselect.cpp b/src/gausskernel/optimizer/plan/subselect.cpp index 0e581faafca7d11b121fa02b716592afb54c25e6..67ea14296cf5706a0e28e91672d3c7703b21ee14 100644 --- a/src/gausskernel/optimizer/plan/subselect.cpp +++ b/src/gausskernel/optimizer/plan/subselect.cpp @@ -6283,8 +6283,6 @@ convert_OREXPR_to_join(PlannerInfo *root, BoolExpr *or_clause, Query *subQuery = NULL; List *EqualExprList = NULL; Node *joinQual = NULL; - Node *notNullTest = NULL; - Node *filterNode = NULL; JoinExpr *result = NULL; RangeTblEntry *rte = NULL; RangeTblRef *rtr = NULL; @@ -6302,7 +6300,7 @@ convert_OREXPR_to_join(PlannerInfo *root, BoolExpr *or_clause, expr_sublink->subselect = (Node *)subQuery; if (get_pullUp_equal_expr((Node*)subQuery->jointree, &EqualExprList) && EqualExprList) { - joinQual = transform_equal_expr(root, subQuery, EqualExprList, ¬NullTest, false, isnull); + joinQual = transform_equal_expr(root, subQuery, EqualExprList, NULL, false, isnull); /* * Upper-level vars in subquery will now be one level closer to their @@ -6343,7 +6341,6 @@ convert_OREXPR_to_join(PlannerInfo *root, BoolExpr *or_clause, result = makeNode(JoinExpr); result->jointype = JOIN_LEFT; result->quals = joinQual; - filterNode = make_and_qual(notNullTest, clause); /* * This op_expr already be pull up as current left join's join quals. @@ -6379,7 +6376,7 @@ convert_OREXPR_to_join(PlannerInfo *root, BoolExpr *or_clause, mark_parent_child_pushdown_flag(root->parse, subQuery); list_free_ext(EqualExprList); - return filterNode; + return clause; } else { diff --git a/src/gausskernel/optimizer/prep/prepnonjointree.cpp b/src/gausskernel/optimizer/prep/prepnonjointree.cpp index 328cdfe512a37e0c8d6df8db7d7f9d1e7501623e..5f4eaf6301ef2928f38a558f706076c7419a0734 100755 --- a/src/gausskernel/optimizer/prep/prepnonjointree.cpp +++ b/src/gausskernel/optimizer/prep/prepnonjointree.cpp @@ -2202,7 +2202,8 @@ static void reduce_orderby_final(RangeTblEntry* rte, bool reduce) { /* Reduce orderby clause in subquery for join or from clause of more than one rte */ if (rte->rtekind == RTE_SUBQUERY) { - if (reduce && rte->subquery->sortClause && !rte->subquery->limitOffset && !rte->subquery->limitCount) { + if (reduce && rte->subquery->sortClause && !rte->subquery->limitOffset + && !rte->subquery->limitCount && !rte->subquery->hasDistinctOn) { pfree_ext(rte->subquery->sortClause); rte->subquery->sortClause = NULL; } diff --git a/src/gausskernel/optimizer/util/clauses.cpp b/src/gausskernel/optimizer/util/clauses.cpp index b9073a7f4b85707bf20b0bd3e20a6d1c221953cd..642ed7753d29bc20d6c749a448c55d8f90e34ac7 100644 --- a/src/gausskernel/optimizer/util/clauses.cpp +++ b/src/gausskernel/optimizer/util/clauses.cpp @@ -33,6 +33,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" +#include "nodes/supportnodes.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" #include "optimizer/planmain.h" @@ -3761,23 +3762,34 @@ Expr* simplify_function(Oid funcid, Oid result_type, int32 result_typmod, Oid re if (newexpr == NULL && allow_non_const && OidIsValid(func_form->protransform)) { /* - * Build a dummy FuncExpr node containing the simplified arg list. We - * use this approach to present a uniform interface to the transform - * function regardless of how the function is actually being invoked. + * Build a SupportRequestSimplify node to pass to the support + * function, pointing to a dummy FuncExpr node containing the + * simplified arg list. We use this approach to present a uniform + * interface to the support function regardless of how the target + * function is actually being invoked. */ + SupportRequestSimplify req; FuncExpr fexpr; fexpr.xpr.type = T_FuncExpr; fexpr.funcid = funcid; fexpr.funcresulttype = result_type; fexpr.funcretset = func_form->proretset; + fexpr.funcvariadic = false; fexpr.funcformat = COERCE_DONTCARE; fexpr.funccollid = result_collid; fexpr.inputcollid = input_collid; fexpr.args = args; fexpr.location = -1; - newexpr = (Expr*)DatumGetPointer(OidFunctionCall1(func_form->protransform, PointerGetDatum(&fexpr))); + req.type = T_SupportRequestSimplify; + req.root = context->root; + req.fcall = &fexpr; + + newexpr = (Expr*)DatumGetPointer(OidFunctionCall1(func_form->protransform, PointerGetDatum(&req))); + + /* catch a possible API misunderstanding */ + Assert(newexpr != (Expr *) &fexpr); } if (newexpr == NULL && allow_non_const) @@ -4845,6 +4857,13 @@ Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result } const_val = ExecEvalExprSwitchContext(exprstate, econtext, &const_is_null); + if (IsA(exprstate, FuncExprState)) { + FunctionCallInfo fcinfo = &((FuncExprState*)exprstate)->fcinfo_data; + if (fcinfo->context && IsA(fcinfo->context, FunctionScanState)) { + pfree_ext(fcinfo->context); + } + } + /* Get info needed about result datatype */ get_typlenbyval(result_type, &resultTypLen, &resultTypByVal); diff --git a/src/gausskernel/optimizer/util/dataskew.cpp b/src/gausskernel/optimizer/util/dataskew.cpp index c2d7cd7be23e0fa4017ad1105654fec7d89da1bc..1e7fdccbd92a6fdf0d3880ca5b2ecb3ed1c84287 100755 --- a/src/gausskernel/optimizer/util/dataskew.cpp +++ b/src/gausskernel/optimizer/util/dataskew.cpp @@ -725,17 +725,20 @@ List* SkewInfo::getSingleColumnStatistics(Node* node) &nvalues, &numbers, &nnumbers); - - ret = findMcvValue(vardata.var, nvalues, values, numbers); - - /* find null fraction */ - if (cal_skew_ratio(stats->stanullfrac, u_sess->opt_cxt.query_dop) > SKEW_RATIO_LIMIT) { - ColSkewInfo* csinfo = (ColSkewInfo*)palloc0(sizeof(ColSkewInfo)); - csinfo->var = vardata.var; - csinfo->value = NULL; - csinfo->mcv_ratio = stats->stanullfrac; - csinfo->is_null = true; - ret = lappend(ret, (void*)csinfo); + if (have_mcvs) { + ret = findMcvValue(vardata.var, nvalues, values, numbers); + + free_attstatsslot(vardata.atttype, values, nvalues, numbers, nnumbers); + + /* find null fraction */ + if (cal_skew_ratio(stats->stanullfrac, u_sess->opt_cxt.query_dop) > SKEW_RATIO_LIMIT) { + ColSkewInfo* csinfo = (ColSkewInfo*)palloc0(sizeof(ColSkewInfo)); + csinfo->var = vardata.var; + csinfo->value = NULL; + csinfo->mcv_ratio = stats->stanullfrac; + csinfo->is_null = true; + ret = lappend(ret, (void*)csinfo); + } } } diff --git a/src/gausskernel/po/zh_CN.po b/src/gausskernel/po/zh_CN.po index 02c4a3b95f47ea6387ba3becc072009422173c4b..346f2d28f2c5130a63fcbe58bddc8c5f83d4ecd5 100644 --- a/src/gausskernel/po/zh_CN.po +++ b/src/gausskernel/po/zh_CN.po @@ -103040,14 +103040,14 @@ msgstr "无法重命名旧的事务日志文件\"%s\":%m" #: storage/replication/walrcvwriter.cpp:1395 #, c-format -msgid "walRcvUwalTruncate truncate not in fullSync" -msgstr "walRcvUwalTruncate截断不在fullSync中" +msgid "WalRcvUwalTruncate truncate not in fullSync" +msgstr "WalRcvUwalTruncate截断不在fullSync中" # #: storage/replication/walrcvwriter.cpp:1401 #, c-format -msgid "walRcvUwalTruncate failed retCode: %d" -msgstr "walRcvUwalTruncate失败, 返回码 = %d" +msgid "WalRcvUwalTruncate failed retCode: %d" +msgstr "WalRcvUwalTruncate失败, 返回码 = %d" #: storage/replication/walrcvwriter.cpp:1442 #, c-format diff --git a/src/gausskernel/process/main/main.cpp b/src/gausskernel/process/main/main.cpp index 42ec8ff6fb0e27f154bc810dc51e522a84b8eb82..998c8e08e1b719d1a7385409f3a53778b3214632 100755 --- a/src/gausskernel/process/main/main.cpp +++ b/src/gausskernel/process/main/main.cpp @@ -109,7 +109,7 @@ int main(int argc, char* argv[]) ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); - + g_instance.comm_cxt.comm_global_mem_cxt = AllocSetContextCreate(g_instance.instance_context, "CommunnicatorGlobalMemoryContext", ALLOCSET_DEFAULT_MINSIZE, @@ -132,6 +132,76 @@ int main(int argc, char* argv[]) */ MemoryContextInit(); + /* + * Set up locale information from environment. Note that LC_CTYPE and + * LC_COLLATE will be overridden later from pg_control if we are in an + * already-initialized database. We set them here so that they will be + * available to fill pg_control during initdb. LC_MESSAGES will get set + * later during GUC option processing, but we set it here to allow startup + * error messages to be localized. + */ + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("gaussdb")); + +#ifdef WIN32 + + /* + * Windows uses codepages rather than the environment, so we work around + * that by querying the environment explicitly first for LC_COLLATE and + * LC_CTYPE. We have to do this because initdb passes those values in the + * environment. If there is nothing there we fall back on the codepage. + */ + { + char* env_locale = NULL; + + if ((env_locale = gs_getenv_r("LC_COLLATE")) != NULL) { + check_backend_env(env_locale); + pg_perm_setlocale(LC_COLLATE, env_locale); + } else + pg_perm_setlocale(LC_COLLATE, ""); + + if ((env_locale = gs_getenv_r("LC_CTYPE")) != NULL) { + check_backend_env(env_locale); + pg_perm_setlocale(LC_CTYPE, env_locale); + } else + pg_perm_setlocale(LC_CTYPE, ""); + } +#else + pg_perm_setlocale(LC_COLLATE, ""); + pg_perm_setlocale(LC_CTYPE, ""); +#endif + + /* + * LC_MESSAGES will get set later during GUC option processing, but we set + * it here to allow startup error messages to be localized. + */ +#if defined(ENABLE_NLS) && defined(LC_MESSAGES) + pg_perm_setlocale(LC_MESSAGES, ""); +#endif + + /* + * We keep these set to "C" always, except transiently in pg_locale.c; see + * that file for explanations. + */ + pg_perm_setlocale(LC_MONETARY, "C"); + pg_perm_setlocale(LC_NUMERIC, "C"); + pg_perm_setlocale(LC_TIME, "C"); + + /* + * Now that we have absorbed as much as we wish to from the locale + * environment, remove any LC_ALL setting, so that the environment + * variables installed by pg_perm_setlocale have force. + */ + (void)unsetenv("LC_ALL"); + + /* + * The code after this point prohibits the call to pg_perm_setlocale, + * because it is only used to set process's locale information, and + * if you want to modify thread's locale information, instead call + * gs_perm_setlocale_r. + * NB: This must be done before calling knl_thread_init() so that + * duplocale() can inherit the process's locale information. + */ + PmTopMemoryContext = t_thrd.top_mem_cxt; knl_thread_init(MASTER_THREAD); @@ -147,6 +217,17 @@ int main(int argc, char* argv[]) progname = get_progname(argv[0]); + /* + * Use the right encoding in translated messages. Under ENABLE_NLS, let + * pg_bind_textdomain_codeset() figure it out. Under !ENABLE_NLS, message + * format strings are ASCII, but database-encoding strings may enter the + * message via %s. This makes the overall message encoding equal to the + * database encoding. + */ +#ifdef ENABLE_NLS + pg_bind_textdomain_codeset(textdomain(NULL)); +#endif + #ifdef PROFILE_PID_DIR { char* gmon_env = NULL; @@ -197,67 +278,6 @@ int main(int argc, char* argv[]) pgwin32_install_crashdump_handler(); #endif - /* - * Set up locale information from environment. Note that LC_CTYPE and - * LC_COLLATE will be overridden later from pg_control if we are in an - * already-initialized database. We set them here so that they will be - * available to fill pg_control during initdb. LC_MESSAGES will get set - * later during GUC option processing, but we set it here to allow startup - * error messages to be localized. - */ - set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("gaussdb")); - -#ifdef WIN32 - - /* - * Windows uses codepages rather than the environment, so we work around - * that by querying the environment explicitly first for LC_COLLATE and - * LC_CTYPE. We have to do this because initdb passes those values in the - * environment. If there is nothing there we fall back on the codepage. - */ - { - char* env_locale = NULL; - - if ((env_locale = gs_getenv_r("LC_COLLATE")) != NULL) { - check_backend_env(env_locale); - pg_perm_setlocale(LC_COLLATE, env_locale); - } else - pg_perm_setlocale(LC_COLLATE, ""); - - if ((env_locale = gs_getenv_r("LC_CTYPE")) != NULL) { - check_backend_env(env_locale); - pg_perm_setlocale(LC_CTYPE, env_locale); - } else - pg_perm_setlocale(LC_CTYPE, ""); - } -#else - pg_perm_setlocale(LC_COLLATE, ""); - pg_perm_setlocale(LC_CTYPE, ""); -#endif - - /* - * LC_MESSAGES will get set later during GUC option processing, but we set - * it here to allow startup error messages to be localized. - */ -#if defined(ENABLE_NLS) && defined(LC_MESSAGES) - pg_perm_setlocale(LC_MESSAGES, ""); -#endif - - /* - * We keep these set to "C" always, except transiently in pg_locale.c; see - * that file for explanations. - */ - pg_perm_setlocale(LC_MONETARY, "C"); - pg_perm_setlocale(LC_NUMERIC, "C"); - pg_perm_setlocale(LC_TIME, "C"); - - /* - * Now that we have absorbed as much as we wish to from the locale - * environment, remove any LC_ALL setting, so that the environment - * variables installed by pg_perm_setlocale have force. - */ - (void)unsetenv("LC_ALL"); - /* * Catch standard options before doing much else */ diff --git a/src/gausskernel/process/postmaster/autovacuum.cpp b/src/gausskernel/process/postmaster/autovacuum.cpp index c72cf3c24eb2ebb214f2de53b2fb519c140f2057..167bb8d8f35981982093bef63de6c6d90831f774 100755 --- a/src/gausskernel/process/postmaster/autovacuum.cpp +++ b/src/gausskernel/process/postmaster/autovacuum.cpp @@ -3433,7 +3433,7 @@ static void autovacuum_local_vac_analyze(autovac_table* tab, BufferAccessStrateg autovac_report_activity(tab); WaitStatePhase oldPhase = pgstat_report_waitstatus_phase(PHASE_AUTOVACUUM); DEBUG_MOD_START_TIMER(MOD_AUTOVAC); - vacuum(&vacstmt, tab->at_relid, false, bstrategy, true); + vacuum(&vacstmt, tab->at_relid, u_sess->attr.attr_storage.handle_toast_in_autovac, bstrategy, true); tab->at_gpivacuumed = vacstmt.gpi_vacuumed; DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: %s", tab->at_relname); pgstat_report_waitstatus_phase(oldPhase); diff --git a/src/gausskernel/process/postmaster/pagewriter.cpp b/src/gausskernel/process/postmaster/pagewriter.cpp index ea99fe12eb89c1ed79eb6ed2fe6757620b58ca5b..787c374e705eb1d733153a2b421136695363fad8 100755 --- a/src/gausskernel/process/postmaster/pagewriter.cpp +++ b/src/gausskernel/process/postmaster/pagewriter.cpp @@ -2072,26 +2072,19 @@ static void incre_ckpt_pgwr_flush_dirty_queue(WritebackContext *wb_context) ResourceOwnerEnlargeBuffers(t_thrd.utils_cxt.CurrentResourceOwner); - if (ENABLE_DMS) { + /* Double write can only handle at most DW_DIRTY_PAGE_MAX at one time. */ + for (int i = 0; i < runs; i++) { + /* Last batch, take the rest of the buffers */ + int offset = i * dw_batch_page_max; + int batch_num = (i == runs - 1) ? (need_flush_num - offset) : dw_batch_page_max; + uint32 flush_num; + pgwr->thrd_dw_cxt.is_new_relfilenode = is_new_relfilenode; pgwr->thrd_dw_cxt.dw_page_idx = -1; - num_actual_flush = incre_ckpt_pgwr_flush_dirty_page(wb_context, dirty_buf_list, 0, need_flush_num); + dw_perform_batch_flush(batch_num, dirty_buf_list + offset, thread_id, &pgwr->thrd_dw_cxt); + flush_num = incre_ckpt_pgwr_flush_dirty_page(wb_context, dirty_buf_list, offset, batch_num); pgwr->thrd_dw_cxt.dw_page_idx = -1; - } else { - /* Double write can only handle at most DW_DIRTY_PAGE_MAX at one time. */ - for (int i = 0; i < runs; i++) { - /* Last batch, take the rest of the buffers */ - int offset = i * dw_batch_page_max; - int batch_num = (i == runs - 1) ? (need_flush_num - offset) : dw_batch_page_max; - uint32 flush_num; - - pgwr->thrd_dw_cxt.is_new_relfilenode = is_new_relfilenode; - pgwr->thrd_dw_cxt.dw_page_idx = -1; - dw_perform_batch_flush(batch_num, dirty_buf_list + offset, thread_id, &pgwr->thrd_dw_cxt); - flush_num = incre_ckpt_pgwr_flush_dirty_page(wb_context, dirty_buf_list, offset, batch_num); - pgwr->thrd_dw_cxt.dw_page_idx = -1; - num_actual_flush += flush_num; - } + num_actual_flush += flush_num; } (void)pg_atomic_fetch_add_u64(&g_instance.ckpt_cxt_ctl->page_writer_actual_flush, num_actual_flush); @@ -2116,27 +2109,21 @@ static void incre_ckpt_pgwr_flush_dirty_list(WritebackContext *wb_context, uint3 qsort(dirty_buf_list, need_flush_num, sizeof(CkptSortItem), ckpt_buforder_comparator); ResourceOwnerEnlargeBuffers(t_thrd.utils_cxt.CurrentResourceOwner); - if (ENABLE_DMS) { + /* Double write can only handle at most DW_DIRTY_PAGE_MAX at one time. */ + for (int i = 0; i < runs; i++) { + /* Last batch, take the rest of the buffers */ + int offset = i * dw_batch_page_max; + int batch_num = (i == runs - 1) ? (need_flush_num - offset) : dw_batch_page_max; + uint32 flush_num; + pgwr->thrd_dw_cxt.is_new_relfilenode = is_new_relfilenode; pgwr->thrd_dw_cxt.dw_page_idx = -1; - num_actual_flush = incre_ckpt_pgwr_flush_dirty_page(wb_context, dirty_buf_list, 0, need_flush_num); + dw_perform_batch_flush(batch_num, dirty_buf_list + offset, thread_id, &pgwr->thrd_dw_cxt); + flush_num = incre_ckpt_pgwr_flush_dirty_page(wb_context, dirty_buf_list, offset, batch_num); pgwr->thrd_dw_cxt.dw_page_idx = -1; - } else { - /* Double write can only handle at most DW_DIRTY_PAGE_MAX at one time. */ - for (int i = 0; i < runs; i++) { - /* Last batch, take the rest of the buffers */ - int offset = i * dw_batch_page_max; - int batch_num = (i == runs - 1) ? (need_flush_num - offset) : dw_batch_page_max; - uint32 flush_num; - - pgwr->thrd_dw_cxt.is_new_relfilenode = is_new_relfilenode; - pgwr->thrd_dw_cxt.dw_page_idx = -1; - dw_perform_batch_flush(batch_num, dirty_buf_list + offset, thread_id, &pgwr->thrd_dw_cxt); - flush_num = incre_ckpt_pgwr_flush_dirty_page(wb_context, dirty_buf_list, offset, batch_num); - pgwr->thrd_dw_cxt.dw_page_idx = -1; - num_actual_flush += flush_num; - } + num_actual_flush += flush_num; } + (void)pg_atomic_fetch_add_u64(&g_instance.ckpt_cxt_ctl->page_writer_actual_flush, num_actual_flush); (void)pg_atomic_fetch_add_u32(&g_instance.ckpt_cxt_ctl->page_writer_last_flush, num_actual_flush); diff --git a/src/gausskernel/process/postmaster/postmaster.cpp b/src/gausskernel/process/postmaster/postmaster.cpp index 2568b552ebc77a1b3a2efaec89197f94c551c69d..f38c4b2b0ca7d8b481c3f6be4c25404690454de1 100644 --- a/src/gausskernel/process/postmaster/postmaster.cpp +++ b/src/gausskernel/process/postmaster/postmaster.cpp @@ -3066,7 +3066,7 @@ int PostmasterMain(int argc, char* argv[]) g_instance.attr.attr_storage.dms_attr.instance_id, src_id))); Assert(src_id >= 0 && src_id <= DMS_MAX_INSTANCE - 1); - if (!SS_OFFICIAL_PRIMARY && g_instance.attr.attr_storage.dms_attr.enable_reform) { + if (!SS_OFFICIAL_PRIMARY) { const long SLEEP_ONE_SEC = 1000000L; while (g_instance.dms_cxt.SSReformerControl.list_stable == 0) { pg_usleep(SLEEP_ONE_SEC); @@ -3118,19 +3118,21 @@ int PostmasterMain(int argc, char* argv[]) if (ret != 0) { ereport(PANIC, (errmsg("uwal primary init notify failed, ret: %d", ret))); } + MoveUwalFile(); } else if (t_thrd.postmaster_cxt.HaShmData->current_mode == STANDBY_MODE || t_thrd.postmaster_cxt.HaShmData->current_mode == PENDING_MODE) { ret = GsUwalStandbyInitNotify(); if (ret != 0) { ereport(PANIC, (errmsg("uwal standby init notify failed, ret: %d", ret))); } + MoveUwalFile(); } } /* init sharestorge(dorado) */ ShareStorageInit(); exrto_standby_read_init(); - if (ENABLE_DMS && ENABLE_REFORM) { + if (ENABLE_DMS) { if (!DMSWaitInitStartup()) { if (g_instance.pid_cxt.StartupPID == 0) { ereport(LOG, (errmsg("[SS reform] Node:%d first startup fail and exit", SS_MY_INST_ID))); @@ -3655,6 +3657,9 @@ static void CheckPgLogDisk(void) char disk_cmd[MAX_COMMAND_LEN] = {0}; char buf[MAX_P_READ_BUF] = {0}; char free_disk[MAX_P_READ_BUF] = {0}; + const int bufSize = 256; + char timeBuf[bufSize] = {0}; + get_time_now(timeBuf, bufSize); int rc = 0; rc = snprintf_s(disk_cmd, MAX_COMMAND_LEN, MAX_COMMAND_LEN - 1, @@ -3663,7 +3668,7 @@ static void CheckPgLogDisk(void) cmd_fp = popen(disk_cmd, "r"); if (NULL == cmd_fp) { - write_stderr("could not open disk free space command.\n"); + write_stderr("%s [postmaster][%lu] ERROR: could not open disk free space command.\n", timeBuf, PostmasterPid); return; } @@ -3676,9 +3681,10 @@ static void CheckPgLogDisk(void) } char* pEnd = NULL; if (free_disk == NULL) { - write_stderr("could not get disk free space.\n"); + write_stderr("%s [postmaster][%lu] ERROR: could not get disk free space.\n", timeBuf, PostmasterPid); } else if (strtol(free_disk, &pEnd, 10) == 0) { - write_stderr("No free space on pg_log disk.\n"); + write_stderr("%s [postmaster][%lu] ERROR: No free space on pg_log disk, the path is: %s.\n", + timeBuf, PostmasterPid, u_sess->attr.attr_common.Log_directory); } pclose(cmd_fp); @@ -3936,8 +3942,7 @@ static int ServerLoop(void) gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); - if (ENABLE_DMS && ENABLE_REFORM && g_instance.dms_cxt.SSRecoveryInfo.startup_reform - && !startup_reform_finish) { + if (ENABLE_DMS && g_instance.dms_cxt.SSRecoveryInfo.startup_reform && !startup_reform_finish) { ereport(LOG, (errmsg("[SS reform] Node:%d first-round reform start wait.", SS_MY_INST_ID))); if (!DMSWaitReform()) { ereport(WARNING, (errmsg("[SS reform] Node:%d first-round reform failed, shutdown now", @@ -8712,7 +8717,7 @@ static void PostmasterStateMachine(void) } } - if (pmState == PM_WAIT_BACKENDS && SS_STANDBY_FAILOVER) { + if (SS_IN_FAILOVER && !g_instance.dms_cxt.SSRecoveryInfo.no_backend_left) { if (CountChildren(BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC) == 0) { g_instance.dms_cxt.SSRecoveryInfo.no_backend_left = true; } @@ -10517,12 +10522,6 @@ static void sigusr1_handler(SIGNAL_ARGS) /* shut down all backends and autovac workers */ (void)SignalSomeChildren(SIGTERM, BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC); - /* avoid panics caused by concurreny between startup processes and recovery */ - if ((!SS_DISASTER_MAIN_STANDBY_NODE) && g_instance.pid_cxt.StartupPID != 0) { - ereport(LOG, (errmsg("[SS Reform] request startup proc exit"))); - signal_child(g_instance.pid_cxt.StartupPID, SIGTERM); - } - /* and the autovac launcher too */ if (g_instance.pid_cxt.AutoVacPID != 0) signal_child(g_instance.pid_cxt.AutoVacPID, SIGTERM); @@ -13974,25 +13973,6 @@ int GaussDbThreadMain(knl_thread_arg* arg) MemoryContextInit(); knl_thread_init(thread_role); - /* - * Set LC_CTYPE for auxiliary threads same as main - * 1.When thread called knl_t_port_init and the pg_perm_setlocale(LC_MESSAGES, "") - * in InitializeGUCOptions, LC_CTYPE will be changed to "C". - * if now LC_MESSAGES is zh_CN.UTF-8, function gettext will return "????". - * 2.Worker thread will call SetEncordingInfo, - * and LC_CTYPE will be overwritten to the encoding of database. - */ -#ifdef ENABLE_NLS - (void) pg_perm_setlocale(LC_CTYPE, ""); - if (thread_role == THREADPOOL_WORKER) { - errno_t rc; - const char* curctype = pg_perm_setlocale(LC_CTYPE, NULL); - /* if cur_datctype is diff from database encoding, LC_CTYPE will be overwritten */ - rc = strncpy_s(NameStr(t_thrd.port_cxt.cur_datctype), NAMEDATALEN, curctype, strlen(curctype)); - securec_check(rc, "\0", "\0"); - } -#endif - #ifdef USE_SPQ if (arg->spq_role == ROLE_QUERY_EXECUTOR) { t_thrd.spq_ctx.spq_role = ROLE_QUERY_EXECUTOR; diff --git a/src/gausskernel/process/tcop/auditfuncs.cpp b/src/gausskernel/process/tcop/auditfuncs.cpp index 1312279fcf49959a6c8a2124b8213682f423928d..c3f8127ae60b85f9ee57d2449ce472ab81507cdb 100644 --- a/src/gausskernel/process/tcop/auditfuncs.cpp +++ b/src/gausskernel/process/tcop/auditfuncs.cpp @@ -1445,7 +1445,14 @@ static void pgaudit_ProcessUtility(processutility_context* processutility_cxt, LockStmt* locktablestmt = (LockStmt*)(parsetree); ListCell* arg = NULL; foreach (arg, locktablestmt->relations) { - RangeVar* rv = (RangeVar*)lfirst(arg); + RangeVar* rv = NULL; + List* rv_lockmode = NULL; + if (u_sess->attr.attr_sql.dolphin && locktablestmt->mode == NoLock){ + rv_lockmode = (List*)lfirst(arg); + rv = (RangeVar*)linitial(rv_lockmode); + } else { + rv = (RangeVar*)lfirst(arg); + } pgaudit_ddl_table(rv->relname, queryString); } } break; diff --git a/src/gausskernel/process/tcop/postgres.cpp b/src/gausskernel/process/tcop/postgres.cpp index fabdf2d53bded616cec8a164bf7faf88ab98040e..94a435fc3681e7e5e23d5eef8c022c808cd70743 100755 --- a/src/gausskernel/process/tcop/postgres.cpp +++ b/src/gausskernel/process/tcop/postgres.cpp @@ -973,6 +973,14 @@ bool IsFileExisted(const char *filename) return file_exists(fullname); } +#define APACEH_AGE "age" +void InitAGESqlPluginHookIfNeeded() +{ + if (get_extension_oid(APACEH_AGE, true) != InvalidOid && IsFileExisted(APACEH_AGE)) { + load_file(APACEH_AGE, !superuser()); + } +} + #define INIT_PLUGIN_OBJECT "init_plugin_object" #define WHALE "whale" #define DOLPHIN "dolphin" @@ -3552,6 +3560,7 @@ static void exec_parse_message(const char* query_string, /* string to execute */ CachedPlanSource* psrc = NULL; bool is_named = false; bool save_log_statement_stats = u_sess->attr.attr_common.log_statement_stats; + bool fixed_result = FORCE_VALIDATE_PLANCACHE_RESULT; char msec_str[PRINTF_DST_MAX]; char* mask_string = NULL; #ifdef ENABLE_MULTIPLE_NODES @@ -3934,8 +3943,9 @@ static void exec_parse_message(const char* query_string, /* string to execute */ /* Finish filling in the CachedPlanSource */ CompleteCachedPlan(psrc, querytree_list, unnamed_stmt_context, paramTypes, paramModes, numParams, NULL, NULL, 0, /* default cursor options */ - true, stmt_name, single_exec_node, - is_read_only); /* fixed result */ + fixed_result, /* fixed result */ + stmt_name, single_exec_node, + is_read_only); /* For ctas query, rewrite is not called in PARSE, so we must set invalidation to revalidate the cached plan. */ if (is_ctas) { @@ -4559,8 +4569,6 @@ static void exec_bind_message(StringInfo input_message) u_sess->parser_cxt.param_info = NULL; u_sess->parser_cxt.param_message = NULL; - StringInfo temp_message = makeStringInfo(); - copyStringInfo(temp_message, input_message); gstrace_entry(GS_TRC_ID_exec_bind_message); /* Instrumentation: PBE - reset unique sql elapsed start time */ @@ -4858,13 +4866,9 @@ static void exec_bind_message(StringInfo input_message) /* Version control for DDL PBE */ if (t_thrd.proc->workingVersionNum >= DDL_PBE_VERSION_NUM) { u_sess->parser_cxt.param_message = makeStringInfo(); - copyStringInfo(u_sess->parser_cxt.param_message, temp_message); - } - if (temp_message != NULL) { - if (temp_message->data != NULL) - pfree_ext(temp_message->data); - pfree_ext(temp_message); + copyStringInfo(u_sess->parser_cxt.param_message, input_message); } + /* Copy the plan's query string into the portal */ query_string = pstrdup(psrc->query_string); @@ -5816,8 +5820,8 @@ void exec_describe_statement_message(const char* stmt_name) Assert(NULL != psrc); - /* Prepared statements shouldn't have changeable result descs */ - Assert(psrc->fixed_result); + /* Prepared statements shouldn't have changeable result descs unless being forced */ + Assert(!FORCE_VALIDATE_PLANCACHE_RESULT || psrc->fixed_result); #ifdef ENABLE_MOT /* set current transaction storage engine */ @@ -7697,13 +7701,7 @@ void LoadSqlPlugin() if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT) && IsFileExisted(DOLPHIN)) { /* start_xact_command will change CurrentResourceOwner, so save it here */ ResourceOwner save = t_thrd.utils_cxt.CurrentResourceOwner; - if (!u_sess->attr.attr_sql.dolphin && -#ifdef ENABLE_LITE_MODE - u_sess->attr.attr_common.upgrade_mode == 0 -#else - !u_sess->attr.attr_common.IsInplaceUpgrade -#endif - ) { + if (!u_sess->attr.attr_sql.dolphin && u_sess->attr.attr_common.upgrade_mode == 0) { Oid userId = GetUserId(); if (userId != INITIAL_USER_ID) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), @@ -7741,6 +7739,11 @@ void LoadSqlPlugin() } else if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(A_FORMAT) && u_sess->attr.attr_sql.whale) { InitASqlPluginHookIfNeeded(); } + + /* load age if the age extension been created and the age.o file exists */ + if(u_sess->proc_cxt.MyDatabaseId != InvalidOid ){ + InitAGESqlPluginHookIfNeeded(); + } } #endif @@ -8302,6 +8305,7 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam /* Since not using PG_TRY, must reset error stack by hand */ u_sess->plsql_cxt.cur_exception_cxt = NULL; + u_sess->plsql_cxt.is_exec_autonomous = false; t_thrd.log_cxt.error_context_stack = NULL; t_thrd.log_cxt.call_stack = NULL; /* reset buffer strategy flag */ @@ -8394,8 +8398,13 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam pfree_ext(t_thrd.wlm_cxt.collect_info->sdetail.msg); } } + gsplsql_unlock_func_pkg_dependency_all(); u_sess->plsql_cxt.pragma_autonomous = false; u_sess->plsql_cxt.curr_compile_context = NULL; + u_sess->plsql_cxt.isCreateFunction = false; + u_sess->plsql_cxt.isCreatePkg = false; + u_sess->plsql_cxt.is_alter_compile_stmt = false; + u_sess->plsql_cxt.during_compile = false; u_sess->pcache_cxt.gpc_in_batch = false; u_sess->pcache_cxt.gpc_in_try_store = false; u_sess->plsql_cxt.have_error = false; @@ -8456,6 +8465,10 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam LWLockReleaseAll(); AbortBufferIO(); +#ifndef ENABLE_MULTIPLE_NODES + gsplsql_unlock_func_pkg_dependency_all(); +#endif + /* We should syncQuit after LWLockRelease to avoid dead lock of LWLocks. */ RESUME_INTERRUPTS(); StreamNodeGroup::syncQuit(STREAM_ERROR); @@ -8468,6 +8481,7 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam clean_up_debug_server(debug_server, false, true); u_sess->plsql_cxt.cur_debug_server = NULL; #endif + u_sess->plsql_cxt.during_compile = false; #ifdef ENABLE_MULTIPLE_NODES /* reset send role flag */ if (InSendingLocalUserIdChange()) { @@ -8633,11 +8647,19 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam /* reset plpgsql compile flag */ u_sess->plsql_cxt.compile_context_list = NULL; u_sess->plsql_cxt.curr_compile_context = NULL; + u_sess->plsql_cxt.compile_status = NONE_STATUS; u_sess->plsql_cxt.func_tableof_index = NULL; u_sess->plsql_cxt.portal_depth = 0; + u_sess->plsql_cxt.isCreateFunction = false; + u_sess->plsql_cxt.isCreatePkg = false; + u_sess->plsql_cxt.is_alter_compile_stmt = false; + u_sess->plsql_cxt.during_compile = false; t_thrd.utils_cxt.STPSavedResourceOwner = NULL; - + if (u_sess->plsql_cxt.depend_mem_cxt != NULL) { + MemoryContextDelete(u_sess->plsql_cxt.depend_mem_cxt); + u_sess->plsql_cxt.depend_mem_cxt = NULL; + } u_sess->statement_cxt.executer_run_level = 0; initStringInfo(&input_message); @@ -12005,8 +12027,8 @@ static void exec_batch_bind_execute(StringInfo input_message) switch (describe_type) { case 'S': { StringInfoData buf; - /* Prepared statements shouldn't have changeable result descs */ - Assert(psrc->fixed_result); + /* Prepared statements shouldn't have changeable result descs unless being forced */ + Assert(!FORCE_VALIDATE_PLANCACHE_RESULT || psrc->fixed_result); /* * First describe the parameters... diff --git a/src/gausskernel/process/tcop/pquery.cpp b/src/gausskernel/process/tcop/pquery.cpp index ee1e2581dc795422a79d228b716fe23090ca6069..d7252a8d5b98c16b89bc6830a6222cdd761bc585 100644 --- a/src/gausskernel/process/tcop/pquery.cpp +++ b/src/gausskernel/process/tcop/pquery.cpp @@ -677,9 +677,6 @@ void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snaps */ portal->strategy = ChoosePortalStrategy(portal->stmts); - // Allocate and initialize scan descriptor - portal->scanDesc = (TableScanDesc)palloc0(SizeofHeapScanDescData + MaxHeapTupleSize); - /* * Fire her up according to the strategy */ @@ -1414,6 +1411,13 @@ static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestRecei */ RemoteQueryState* rqs = (RemoteQueryState*)queryDesc->planstate; + MemoryContext oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); + + // Allocate and initialize scan descriptor + portal->scanDesc = (TableScanDesc)palloc0(SizeofHeapScanDescData + MaxHeapTupleSize); + + MemoryContextSwitchTo(oldContext); + // get the cached scan descriptor in portal rqs->ss.ss_currentScanDesc = (TableScanDesc)portal->scanDesc; // copy snapshot into the scan descriptor diff --git a/src/gausskernel/process/tcop/utility.cpp b/src/gausskernel/process/tcop/utility.cpp index d9008abf9e3a4e1602e3172e7d813a4f0a7f22e3..d128afca4be42f04d157153fd529321cddbd0858 100755 --- a/src/gausskernel/process/tcop/utility.cpp +++ b/src/gausskernel/process/tcop/utility.cpp @@ -3440,9 +3440,11 @@ void standard_ProcessUtility(processutility_context* processutility_cxt, case T_DoStmt: + u_sess->plsql_cxt.need_create_depend = false; /* This change is from PG11 commit/rollback patch */ ExecuteDoStmt((DoStmt*) parse_tree, (!u_sess->SPI_cxt.is_allow_commit_rollback)); + u_sess->plsql_cxt.need_create_depend = true; break; case T_CreatedbStmt: @@ -5367,6 +5369,8 @@ ProcessUtilitySlow(Node *parse_tree, * commands is consistent with the way they are * executed here. */ + EventTriggerAlterTableEnd(); + processutility_context proutility_cxt; proutility_cxt.parse_tree = stmt; proutility_cxt.query_string = query_string; @@ -5394,6 +5398,7 @@ ProcessUtilitySlow(Node *parse_tree, exec_remote_query_4_seq(exec_nodes, drop_seq_string, INVALIDSEQUUID); } #endif + EventTriggerAlterTableEnd(); } else { ereport(NOTICE, (errmsg("relation \"%s\" does not exist, skipping", atstmt->relation->relname))); } diff --git a/src/gausskernel/process/threadpool/knl_instance.cpp b/src/gausskernel/process/threadpool/knl_instance.cpp index 917fdd9a4ec79fdcc3ee63faccd6d8f522845144..a8628b7ff76adc91604549da4e0975a2108b94f7 100755 --- a/src/gausskernel/process/threadpool/knl_instance.cpp +++ b/src/gausskernel/process/threadpool/knl_instance.cpp @@ -188,6 +188,8 @@ static void knl_g_dms_init(knl_g_dms_context *dms_cxt) dms_cxt->SSReformInfo.old_bitmap = 0; dms_cxt->SSReformInfo.new_bitmap = 0; dms_cxt->SSReformInfo.redo_total_bytes = 0; + dms_cxt->SSReformInfo.reform_ver = 0; + dms_cxt->SSReformInfo.reform_ver_startup_wait = 0; dms_cxt->SSClusterState = NODESTATE_NORMAL; dms_cxt->SSRecoveryInfo.recovery_inst_id = INVALID_INSTANCEID; dms_cxt->SSRecoveryInfo.cluster_ondemand_status = CLUSTER_NORMAL; diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index e8d5ea9f25eebd01186f48c277239c8a17a5d720..aea73c2a4073b5770a175031d69e19b1f4d91601 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -1858,11 +1858,16 @@ void set_function_style_pg() u_sess->plsql_cxt.functionStyleType = FUNCTION_STYLE_TYPE_PG; } +void set_is_create_pkg_function(bool is_create_pkg_function) +{ + u_sess->plsql_cxt.isCreatePkgFunction = is_create_pkg_function; +} + bool set_is_create_plsql_type() { if (enable_plpgsql_gsdependency_guc()) { if (u_sess->plsql_cxt.isCreatePkgFunction == true && - u_sess->plsql_cxt.isCreatePkgFunction == false) { + u_sess->plsql_cxt.isCreatePkg == false) { return false; } if (u_sess->plsql_cxt.functionStyleType == FUNCTION_STYLE_TYPE_REFRESH_HEAD) { diff --git a/src/gausskernel/process/threadpool/knl_thread.cpp b/src/gausskernel/process/threadpool/knl_thread.cpp index ad9fc88201a724728848e78b9d38aa56d3d117b6..fbca460e968c190bf1a8117d8ab7f5ec56953fd8 100755 --- a/src/gausskernel/process/threadpool/knl_thread.cpp +++ b/src/gausskernel/process/threadpool/knl_thread.cpp @@ -1456,7 +1456,13 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) static void knl_t_port_init(knl_t_port_context* port_cxt) { port_cxt->thread_is_exiting = false; - port_cxt->save_locale_r = (locale_t)0; + /* + * We can only call setlocale() to modify the process's locale information + * at server startup, so as to avoid the need to acquire locks when thread + * sets its own LC_COLLATE and LC_CTYPE. + * NB: The memory pointed by save_locale_r needs to be freed. + */ + port_cxt->save_locale_r = duplocale(LC_GLOBAL_LOCALE); port_cxt->cur_datcollate.data[0] = '\0'; port_cxt->cur_datctype.data[0] = '\0'; port_cxt->cur_monetary.data[0] = '\0'; diff --git a/src/gausskernel/process/threadpool/threadpool_worker.cpp b/src/gausskernel/process/threadpool/threadpool_worker.cpp index 6bc341d323e1389c8156958ca6327421fa196d04..b664024aae9800e902d54e991154982812c704ce 100644 --- a/src/gausskernel/process/threadpool/threadpool_worker.cpp +++ b/src/gausskernel/process/threadpool/threadpool_worker.cpp @@ -318,7 +318,7 @@ void ThreadPoolWorker::RestoreLocaleInfo() return; } - if (pg_perm_setlocale(LC_COLLATE, NameStr(m_currentSession->mb_cxt.datcollate)) == NULL) { + if (gs_perm_setlocale_r(LC_COLLATE, NameStr(m_currentSession->mb_cxt.datcollate)) == NULL) { ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("database locale is incompatible with operating system"), @@ -328,7 +328,7 @@ void ThreadPoolWorker::RestoreLocaleInfo() errhint("Recreate the database with another locale or install the missing locale."))); } - if (pg_perm_setlocale(LC_CTYPE, NameStr(m_currentSession->mb_cxt.datctype)) == NULL) { + if (gs_perm_setlocale_r(LC_CTYPE, NameStr(m_currentSession->mb_cxt.datctype)) == NULL) { ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("database locale is incompatible with operating system"), @@ -348,10 +348,11 @@ void ThreadPoolWorker::RestoreLocaleInfo() NAMEDATALEN); securec_check(rc, "\0", "\0"); - /* Use the right encoding in translated messages */ -#ifdef ENABLE_NLS - pg_bind_textdomain_codeset(textdomain(NULL)); -#endif + /* + * GNU gettext selects a default encoding for the messages it emits in a + * platform-specific manner; it uses the Windows ANSI code page on Windows + * and follows LC_CTYPE on other platforms. + */ } void ThreadPoolWorker::RestoreSessionVariable() diff --git a/src/gausskernel/runtime/executor/execMain.cpp b/src/gausskernel/runtime/executor/execMain.cpp index 51640e44b5a0c9a6a456e63d17cd49a85d5a7524..b4ff646b9e3f5947a2f15e7b3ba6b1c6e5fb7395 100755 --- a/src/gausskernel/runtime/executor/execMain.cpp +++ b/src/gausskernel/runtime/executor/execMain.cpp @@ -2576,7 +2576,8 @@ static const char *ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *sl return NULL; } -bool ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool skipAutoInc) +bool ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool skipAutoInc, + bool replaceNull) { Relation rel = resultRelInfo->ri_RelationDesc; TupleDesc tupdesc = RelationGetDescr(rel); @@ -2612,7 +2613,7 @@ bool ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState ExecBuildSlotValueDescription(RelationGetRelid(rel), slot, tupdesc, modifiedCols, maxfieldlen); } - bool can_ignore = estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore; + bool can_ignore = (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore) || replaceNull; ereport(can_ignore ? WARNING : ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("null value in column \"%s\" violates not-null constraint", NameStr(tupdesc->attrs[attrChk - 1].attname)), diff --git a/src/gausskernel/runtime/executor/execQual.cpp b/src/gausskernel/runtime/executor/execQual.cpp index 34203833c75ea3ed05f6092020513334abaf8680..1ffb16fd5637791da8534159746c5a820c610de9 100644 --- a/src/gausskernel/runtime/executor/execQual.cpp +++ b/src/gausskernel/runtime/executor/execQual.cpp @@ -156,6 +156,10 @@ static Datum ExecEvalGroupingIdExpr( bool func_has_refcursor_args(Oid Funcid, FunctionCallInfoData* fcinfo); extern struct varlena *heap_tuple_fetch_and_copy(Relation rel, struct varlena *attr, bool needcheck); static void check_huge_clob_paramter(FunctionCallInfoData* fcinfo, bool is_have_huge_clob); +static Datum ExecEvalPriorExpr(ExprState* exprstate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone); +static Datum GetPriorValue(TupleTableSlot *slot, ExprState *exprstate, ExprContext *econtext, AttrNumber origAttnum, + bool *isnull = NULL); +static inline Datum GetResultByType(char* result, Oid typOid, int typmod); THR_LOCAL PLpgSQL_execstate* plpgsql_estate = NULL; @@ -2190,8 +2194,7 @@ void set_result_for_plpgsql_language_function_with_outparam(FuncExprState *fcach if (!IsA(fcache->xprstate.expr, FuncExpr)) { return; } - FuncExpr *func = (FuncExpr *)fcache->xprstate.expr; - if (!is_function_with_plpgsql_language_and_outparam(func->funcid)) { + if (!fcache->is_plpgsql_func_with_outparam) { return; } HeapTupleHeader td = DatumGetHeapTupleHeader(*result); @@ -5895,6 +5898,7 @@ ExprState* ExecInitExprByRecursion(Expr* node, PlanState* parent) fstate->args = (List*)ExecInitExprByRecursion((Expr*)funcexpr->args, parent); fstate->func.fn_oid = InvalidOid; /* not initialized */ + fstate->is_plpgsql_func_with_outparam = is_function_with_plpgsql_language_and_outparam(funcexpr->funcid); fstate->funcReturnsSet = false; state = (ExprState*)fstate; } break; @@ -6427,6 +6431,10 @@ ExprState* ExecInitExprByRecursion(Expr* node, PlanState* parent) state->evalfunc = (ExprStateEvalFunc)ExecEvalUserSetElm; usestate->instate = ExecInitExpr((Expr *)useexpr->val, parent); } break; + case T_PriorExpr: + state = (ExprState*)makeNode(ExprState); + state->evalfunc = ExecEvalPriorExpr; + break; default: ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), @@ -7286,4 +7294,167 @@ bool IsJoinExprNull(List *joinExpr, ExprContext *econtext) return joinkeys_null; } + +static Datum ExecEvalPriorExpr(ExprState* exprstate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone) +{ + PriorExpr* pe = (PriorExpr*)exprstate->expr; + Var* variable = (Var*)pe->node; + TupleTableSlot* slot = NULL; + AttrNumber attnum; + + if (isDone != NULL) + *isDone = ExprSingleResult; + + /* Get the input slot and attribute number we want */ + switch (variable->varno) { + case INNER_VAR: /* get the tuple from the inner node */ + slot = econtext->ecxt_innertuple; + break; + + case OUTER_VAR: /* get the tuple from the outer node */ + slot = econtext->ecxt_outertuple; + break; + + /* INDEX_VAR is handled by default case */ + default: /* get the tuple from the relation being scanned */ + slot = econtext->ecxt_scantuple; + if (u_sess->parser_cxt.in_userset) { + u_sess->parser_cxt.has_set_uservar = true; + } + break; + } + + attnum = variable->varattno; + + /* This was checked by ExecInitExpr */ + Assert(attnum != InvalidAttrNumber); + + RightRefState* refState = econtext->rightRefState; + int index = attnum - 1; + if (refState && refState->values && + ((slot == nullptr && IS_ENABLE_INSERT_RIGHT_REF(refState)) || + (IS_ENABLE_UPSERT_RIGHT_REF(refState) && refState->hasExecs[index] && index < refState->colCnt))) { + *isNull = refState->isNulls[index]; + return refState->values[index]; + } + + if (slot == nullptr) { + ereport(ERROR, (errcode(ERRCODE_INVALID_ATTRIBUTE), errmodule(MOD_EXECUTOR), + errmsg("attribute number %d does not exists.", attnum))); + } + if (attnum > 0) { + TupleDesc slot_tupdesc = slot->tts_tupleDescriptor; + Form_pg_attribute attr; + + if (attnum > slot_tupdesc->natts) /* should never happen */ + ereport(ERROR, + (errcode(ERRCODE_INVALID_ATTRIBUTE), + errmodule(MOD_EXECUTOR), + errmsg("attribute number %d exceeds number of columns %d", attnum, slot_tupdesc->natts))); + + attr = &slot_tupdesc->attrs[attnum - 1]; + + /* can't check type if dropped, since atttypid is probably 0 */ + if (!attr->attisdropped) { + if (variable->vartype != attr->atttypid) + ereport(ERROR, + (errcode(ERRCODE_INVALID_ATTRIBUTE), + errmodule(MOD_EXECUTOR), + errmsg("attribute %d has wrong type", attnum), + errdetail("Table has type %s, but query expects %s.", + format_type_be(attr->atttypid), + format_type_be(variable->vartype)))); + } + } + return GetPriorValue(slot, exprstate, econtext, attnum, isNull); +} + +static AttrNumber GetInternalArrayAttnum(TupleDesc tupDesc, AttrNumber origVarAttno) +{ + NameData arrayAttName; + AttrNumber arrayAttNum = InvalidAttrNumber; + errno_t rc = 0; + + rc = memset_s(arrayAttName.data, NAMEDATALEN, 0, NAMEDATALEN); + securec_check(rc, "\0", "\0"); + rc = sprintf_s(arrayAttName.data, NAMEDATALEN, "array_col_%d", origVarAttno); + securec_check_ss(rc, "\0", "\0"); + + /* find proper internal array to support */ + for (int n = tupDesc->natts - 1; n >= 0 ; n--) { + Form_pg_attribute attr = TupleDescAttr(tupDesc, n); + if (pg_strcasecmp(attr->attname.data, arrayAttName.data) == 0) { + arrayAttNum = n + 1; + break; + } + } + + if (arrayAttNum == InvalidAttrNumber) { + elog(ERROR, "Internal array_col for origVarAttno:%d related internal array is not found", + origVarAttno); + } + + return arrayAttNum; +} + +#define SPLIT_COUNT 2 +static Datum GetPriorValue(TupleTableSlot *slot, ExprState *exprstate, ExprContext *econtext, AttrNumber origAttnum, + bool *isnull) +{ + TupleDesc tupDesc = slot->tts_tupleDescriptor; + bool arrayIsNull = true; + Datum result = (Datum)0; + + /* context check */ + Assert (econtext != NULL && exprstate != NULL && !TupIsNull(slot)); + + AttrNumber arrayColAttnum = GetInternalArrayAttnum(tupDesc , origAttnum); + Datum arrayColDatum = heap_slot_getattr(slot, arrayColAttnum, &arrayIsNull); + Assert (!arrayIsNull && origAttnum != InvalidAttrNumber && + arrayColAttnum != InvalidAttrNumber); + Assert (arrayColAttnum > origAttnum); + char *token_tmp = NULL; + char* arrstr = pstrdup(TextDatumGetCString(arrayColDatum)); + int len = strlen(arrstr); + int count = 0; + int i = len - 1; + for (; i >= 0 && count < SPLIT_COUNT; i--) { + if (arrstr[i] == '/') { + count++; + } + } + + if (count == SPLIT_COUNT) { + Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor, origAttnum - 1); + Oid typOid = attr->atttypid; + int typmod = attr->atttypmod; + result = GetResultByType(strtok_s(&arrstr[i + 1], "/", &token_tmp), typOid, typmod); + } + + /* + * When the number of '/' characters is less than SPLIT_COUNT, + * it means that there is only the current node on the path + * from the root to the current node, that is, the current node + * does not have a parent node, so it should be null at this time. + */ + if (isnull != NULL) { + *isnull = count < SPLIT_COUNT ? true : slot->tts_isnull[origAttnum - 1]; + } + + pfree(arrstr); + return result; +} + +static inline Datum GetResultByType(char* value, Oid typOid, int typmod) +{ + char* input = value; + if (input == NULL) { + input = ""; + } + Oid typeInput; + Oid typeIoParam; + getTypeInputInfo(typOid, &typeInput, &typeIoParam); + Datum result = OidInputFunctionCall(typeInput, input, typeIoParam, typmod); + return result; +} #endif diff --git a/src/gausskernel/runtime/executor/execUtils.cpp b/src/gausskernel/runtime/executor/execUtils.cpp index d47926ffcbe1ff27899fb9247e84a238bf96ff2a..3b0254c6e284a0db8f9d67053b3687a9b5c7a40b 100644 --- a/src/gausskernel/runtime/executor/execUtils.cpp +++ b/src/gausskernel/runtime/executor/execUtils.cpp @@ -1184,6 +1184,82 @@ Partition ExecOpenScanParitition(EState* estate, Relation parent, PartitionIdent return partitionOpen(parent, partoid, lockmode); } +void ExecOpenUnusedIndices(ResultRelInfo* resultRelInfo, bool speculative) +{ + Relation resultRelation = resultRelInfo->ri_RelationDesc; + List* indexoidlist = NIL; + ListCell* l = NULL; + int len, i; + RelationPtr relationDescs; + IndexInfo** indexInfoArray; + + /* fast path if no indexes */ + if (!RelationGetForm(resultRelation)->relhasindex) + return; + + /* + * Get cached list of index OIDs + */ + indexoidlist = RelationGetIndexList(resultRelation, true); + len = list_length(indexoidlist); + if (len == 0) { + return; + } + + /* + * allocate space for result arrays + */ + relationDescs = (RelationPtr)palloc(len * sizeof(Relation)); + indexInfoArray = (IndexInfo**)palloc(len * sizeof(IndexInfo*)); + + resultRelInfo->ri_UnusableIndexRelationDescs = relationDescs; + resultRelInfo->ri_UnusableIndexRelationInfo = indexInfoArray; + + /* + * For each index, open the index relation and save pg_index info. We + * acquire RowExclusiveLock, signifying we will update the index. + * + * Note: we do this even if the index is not IndexIsReady; it's not worth + * the trouble to optimize for the case where it isn't. + */ + i = 0; + foreach (l, indexoidlist) { + Oid indexOid = lfirst_oid(l); + Relation indexDesc; + IndexInfo* ii = NULL; + + indexDesc = index_open(indexOid, RowExclusiveLock); + + if (IndexIsUsable(indexDesc->rd_index) || !IndexIsUnique(indexDesc->rd_index)) { + index_close(indexDesc, RowExclusiveLock); + continue; + } + + /* extract index key information from the index's pg_index info */ + ii = BuildIndexInfo(indexDesc); + + /* + * If the indexes are to be used for speculative insertion, add extra + * information required by unique index entries. + */ + if (speculative) { + BuildSpeculativeIndexInfo(indexDesc, ii); + } + relationDescs[i] = indexDesc; + indexInfoArray[i] = ii; + i++; + } + // remember to set the number of unusable indexes + resultRelInfo->ri_NumUnusableIndices = i; + + if (resultRelInfo->ri_NumUnusableIndices == 0) { + ExecCloseUnsedIndices(resultRelInfo); + } + + list_free_ext(indexoidlist); +} + + /* ---------------------------------------------------------------- * ExecInsertIndexTuples support * ---------------------------------------------------------------- @@ -1209,6 +1285,10 @@ void ExecOpenIndices(ResultRelInfo* resultRelInfo, bool speculative) resultRelInfo->ri_NumIndices = 0; resultRelInfo->ri_ContainGPI = false; + + resultRelInfo->ri_NumUnusableIndices = 0; + resultRelInfo->ri_UnusableIndexRelationDescs = NULL; + resultRelInfo->ri_UnusableIndexRelationInfo = NULL; /* fast path if no indexes */ if (!RelationGetForm(resultRelation)->relhasindex) @@ -1275,9 +1355,38 @@ void ExecOpenIndices(ResultRelInfo* resultRelInfo, bool speculative) // remember to set the number of usable indexes resultRelInfo->ri_NumIndices = i; + if (UPDATE_UNUSABLE_UNIQUE_INDEX_ON_IUD) { + ExecOpenUnusedIndices(resultRelInfo, speculative); + } + list_free_ext(indexoidlist); } +void ExecCloseUnsedIndices(ResultRelInfo* resultRelInfo) +{ + int i; + int numIndices = resultRelInfo->ri_NumUnusableIndices; + RelationPtr indexDescs = resultRelInfo->ri_UnusableIndexRelationDescs; + for (i = 0; i < numIndices; i++) { + if (indexDescs[i] == NULL) + continue; /* shouldn't happen? */ + + /* Drop lock acquired by ExecOpenIndices */ + index_close(indexDescs[i], RowExclusiveLock); + } + pfree_ext(resultRelInfo->ri_UnusableIndexRelationDescs); + + if (resultRelInfo->ri_UnusableIndexRelationInfo) { + for (i = 0; i < numIndices; i++) { + pfree_ext(resultRelInfo->ri_UnusableIndexRelationInfo[i]); + } + pfree_ext(resultRelInfo->ri_UnusableIndexRelationInfo); + } + resultRelInfo->ri_UnusableIndexRelationDescs = NULL; + resultRelInfo->ri_UnusableIndexRelationInfo = NULL; +} + + /* ---------------------------------------------------------------- * ExecCloseIndices * @@ -1308,6 +1417,11 @@ void ExecCloseIndices(ResultRelInfo* resultRelInfo) } pfree_ext(resultRelInfo->ri_IndexRelationInfo); } + + if (UPDATE_UNUSABLE_UNIQUE_INDEX_ON_IUD && resultRelInfo->ri_NumUnusableIndices > 0) { + ExecCloseUnsedIndices(resultRelInfo); + } + } /* @@ -1873,9 +1987,12 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e ResultRelInfo* resultRelInfo = NULL; int i; int numIndices; + int numUnusedIndices; RelationPtr relationDescs; + RelationPtr unusedRelationDescs; Relation heapRelation; IndexInfo** indexInfoArray; + IndexInfo** unusedindexInfoArray; ExprContext* econtext = NULL; Datum values[INDEX_MAX_KEYS]; bool isnull[INDEX_MAX_KEYS]; @@ -1883,6 +2000,7 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e bool ispartitionedtable = false; bool containGPI; List* partitionIndexOidList = NIL; + int totalIndices; /* * Get information from the result relation info structure. @@ -1891,6 +2009,13 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e numIndices = resultRelInfo->ri_NumIndices; relationDescs = resultRelInfo->ri_IndexRelationDescs; indexInfoArray = resultRelInfo->ri_IndexRelationInfo; + + numUnusedIndices = resultRelInfo->ri_NumUnusableIndices; + unusedRelationDescs = resultRelInfo->ri_UnusableIndexRelationDescs; + unusedindexInfoArray = resultRelInfo->ri_UnusableIndexRelationInfo; + + totalIndices = numIndices + numUnusedIndices; + heapRelation = resultRelInfo->ri_RelationDesc; containGPI = resultRelInfo->ri_ContainGPI; @@ -1936,8 +2061,8 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e /* * for each index, form and insert the index tuple */ - for (i = 0; i < numIndices; i++) { - Relation indexRelation = relationDescs[i]; + for (i = 0; i < totalIndices; i++) { + Relation indexRelation = i < numIndices ? relationDescs[i] : unusedRelationDescs[i - numIndices]; IndexInfo* indexInfo = NULL; IndexUniqueCheck checkUnique; bool satisfiesConstraint = false; @@ -1950,7 +2075,7 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e continue; } - indexInfo = indexInfoArray[i]; + indexInfo = i < numIndices ? indexInfoArray[i] : unusedindexInfoArray[i - numIndices]; /* If the index is marked as read-only, ignore it */ if (!indexInfo->ii_ReadyForInserts) { diff --git a/src/gausskernel/runtime/executor/nodeModifyTable.cpp b/src/gausskernel/runtime/executor/nodeModifyTable.cpp index e4e7771439303f13939b213f905a3b27c07ef055..1f221d8a60e1be7ff66a4684301d349d926d8383 100644 --- a/src/gausskernel/runtime/executor/nodeModifyTable.cpp +++ b/src/gausskernel/runtime/executor/nodeModifyTable.cpp @@ -1051,7 +1051,7 @@ extern PartKeyExprResult ComputePartKeyExprTuple(Relation rel, EState *estate, T */ template TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, TupleTableSlot* planSlot, EState* estate, - bool canSetTag, int options, List** partitionList, char* partExprKeyStr) + bool canSetTag, int options, List** partitionList, char* partExprKeyStr, bool replaceNull) { Tuple tuple = NULL; ResultRelInfo* result_rel_info = NULL; @@ -1160,7 +1160,7 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple if (result_rel_info->ri_FdwRoutine->GetFdwType && result_rel_info->ri_FdwRoutine->GetFdwType() == MOT_ORC) { if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = state->mt_insert_constr_slot == NULL ? slot : state->mt_insert_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, false, replaceNull)) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -1204,7 +1204,7 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple } if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = state->mt_insert_constr_slot == NULL ? slot : state->mt_insert_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate, true)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, true, replaceNull)) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -2192,7 +2192,7 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid, if (result_rel_info->ri_FdwRoutine->GetFdwType && result_rel_info->ri_FdwRoutine->GetFdwType() == MOT_ORC) { if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = node->mt_insert_constr_slot == NULL ? slot : node->mt_insert_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, false, CheckPluginReplaceNull())) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -2252,7 +2252,7 @@ lreplace: if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = node->mt_update_constr_slot == NULL ? slot : node->mt_update_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, false, CheckPluginReplaceNull())) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -2488,18 +2488,15 @@ lreplace: bool need_create_file = false; int seqNum = -1; bool can_ignore = estate->es_plannedstmt->hasIgnore; - PartKeyExprResult *partKeyExprResult = NULL; - if (partExprKeyStr) { - PartKeyExprResult exprTuple = ComputePartKeyExprTuple(result_relation_desc, estate, slot, - NULL, partExprKeyStr); - partKeyExprResult = &exprTuple; - } + if (!cross_partition) { row_movement = false; new_partId = oldPartitionOid; } else { if (partExprKeyStr) { - partitionRoutingForTuple(result_relation_desc, (void *) partKeyExprResult, + PartKeyExprResult partKeyExprResult = ComputePartKeyExprTuple(result_relation_desc, estate, + slot, NULL, partExprKeyStr); + partitionRoutingForTuple(result_relation_desc, (void*)&partKeyExprResult, u_sess->exec_cxt.route, can_ignore, false); } else { partitionRoutingForTuple(result_relation_desc, tuple, u_sess->exec_cxt.route, can_ignore, true); @@ -2513,7 +2510,6 @@ lreplace: partitionno, RowExclusiveLock); Relation partRel = partitionGetRelation(result_relation_desc, part); char* subpartExprKeyStr = NULL; - Datum newsubval = 0; bool subpartExprKeyIsNull = PartExprKeyIsNull(partRel, &subpartExprKeyStr); if (!subpartExprKeyIsNull) { PartKeyExprResult partKeyExprTuple = ComputePartKeyExprTuple(result_relation_desc, @@ -3274,13 +3270,15 @@ uint64 GetDeleteLimitCount(ExprContext* econtext, PlanState* scan, Limit *limitP return (uint64)iCount; } -static TupleTableSlot* ExecReplace(EState* estate, ModifyTableState* node, TupleTableSlot* slot, TupleTableSlot* plan_slot, int2 bucketid, int hi_options, List* partition_list, char* partExprKeyStr) +static TupleTableSlot* ExecReplace(EState* estate, ModifyTableState* node, TupleTableSlot* slot, + TupleTableSlot* plan_slot, int2 bucketid, int hi_options, List* partition_list, char* partExprKeyStr, + bool replaceNull) { Form_pg_attribute att_tup; Oid seqOid = InvalidOid; Relation rel = estate->es_result_relation_info->ri_RelationDesc; TupleTableSlot* (*ExecInsert)( - ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*) = NULL; + ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*, bool) = NULL; ExecInsert = ExecInsertT; @@ -3383,7 +3381,7 @@ static TupleTableSlot* ExecReplace(EState* estate, ModifyTableState* node, Tuple node, node->canSetTag); InstrCountFiltered2(&node->ps, 1); } else { - slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, partExprKeyStr); + slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, partExprKeyStr, replaceNull); } } return slot; @@ -3421,7 +3419,7 @@ static TupleTableSlot* ExecModifyTable(PlanState* state) Oid old_partition_oid = InvalidOid; bool part_key_updated = ((ModifyTable*)node->ps.plan)->partKeyUpdated; TupleTableSlot* (*ExecInsert)( - ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*) = NULL; + ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*, bool) = NULL; bool use_heap_multi_insert = false; int hi_options = 0; /* indicates whether it is the first time to insert, delete, update or not. */ @@ -3762,13 +3760,17 @@ static TupleTableSlot* ExecModifyTable(PlanState* state) estate->es_result_delete_remoterel = delete_remote_rel_state; #endif switch (operation) { - case CMD_INSERT: + case CMD_INSERT: { + bool replaceNull = CheckPluginReplaceNull() && !IsA(subPlanState, ResultState); if (!node->isReplace) { - slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, partExprKeyStr); + slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, + partExprKeyStr, replaceNull); } else { - slot = ExecReplace(estate, node, slot, plan_slot, bucketid, hi_options, partition_list, partExprKeyStr); + slot = ExecReplace(estate, node, slot, plan_slot, bucketid, hi_options, partition_list, + partExprKeyStr, replaceNull); } break; + } case CMD_UPDATE: if (!IS_SPQ_RUNNING) { slot = ExecUpdate(tuple_id, diff --git a/src/gausskernel/runtime/executor/nodeSamplescan.cpp b/src/gausskernel/runtime/executor/nodeSamplescan.cpp index 6ed3d360c71c98761f4e334ed362320389622d42..6127d2b393607a4493ed448c777d75465e8ac4bd 100644 --- a/src/gausskernel/runtime/executor/nodeSamplescan.cpp +++ b/src/gausskernel/runtime/executor/nodeSamplescan.cpp @@ -189,6 +189,7 @@ TupleTableSlot* HbktSeqSampleNext(SeqScanState* node) void BaseTableSample::getSeed() { Datum datum; + double input; bool isnull = false; ExprContext* econtext = sampleScanState->ps.ps_ExprContext; ExprState* repeatable = sampleScanState->sampleScanInfo.repeatable; @@ -201,6 +202,11 @@ void BaseTableSample::getSeed() errmsg("TABLESAMPLE REPEATABLE parameter cannot be null"))); } + input = DatumGetFloat8(datum); + if (input < MIN_SEED_ARG || input > MAX_SEED_ARG || isnan(input)) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT), errmsg("sample seed must be in the range [0,4294967295]"))); + } /* * The REPEATABLE parameter has been coerced to float8 by the parser. * The reason for using float8 at the SQL level is that it will @@ -252,11 +258,11 @@ void BaseTableSample::getPercent() ERROR, (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT), errmsg("TABLESAMPLE parameter cannot be null"))); } - percent[i] = DatumGetFloat4(params[i]); + percent[i] = DatumGetFloat8(params[i]); - if (percent[i] < MIN_PERCENT_ARG || percent[i] > MAX_PERCENT_ARG || isnan(percent[i])) { + if (percent[i] < MIN_PERCENT_ARG || percent[i] >= MAX_PERCENT_ARG || isnan(percent[i])) { ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT), errmsg("sample percentage must be between 0 and 100"))); + (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT), errmsg("sample percentage must be in the range [0.000001,100)"))); } i++; diff --git a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp index e3fc9c7dd517469a85aaccbe609abee751fa5e74..1b8159b6a9d6515b41234ceda7715a3690fb5acd 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp @@ -411,7 +411,8 @@ bool InsertFusion::execute(long max_rows, char* completionTag) InitResultRelInfo(result_rel_info, rel, 1, 0); if (result_rel_info->ri_RelationDesc->rd_rel->relhasindex) { - bool speculative = m_c_local.m_estate->es_plannedstmt && m_c_local.m_estate->es_plannedstmt->hasIgnore; + bool speculative = (m_c_local.m_estate->es_plannedstmt && m_c_local.m_estate->es_plannedstmt->hasIgnore) || + (m_global->m_planstmt && m_global->m_planstmt->hasIgnore); ExecOpenIndices(result_rel_info, speculative); } diff --git a/src/gausskernel/runtime/opfusion/opfusion_update.cpp b/src/gausskernel/runtime/opfusion/opfusion_update.cpp index d1777f301f9680a100a69f1b284524a5ee45378f..b9bd1e750e94b8624101002a21fcf82ca916e3e9 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_update.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_update.cpp @@ -396,7 +396,7 @@ lreplace: } if (rel->rd_att->constr) { - if (!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate)) { + if (!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate, CheckPluginReplaceNull())) { if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) { break; } @@ -612,7 +612,8 @@ bool UpdateFusion::execute(long max_rows, char *completionTag) m_c_local.m_estate->es_plannedstmt = m_global->m_planstmt; if (result_rel_info->ri_RelationDesc->rd_rel->relhasindex) { - bool speculative = m_c_local.m_estate->es_plannedstmt && m_c_local.m_estate->es_plannedstmt->hasIgnore; + bool speculative = (m_c_local.m_estate->es_plannedstmt && m_c_local.m_estate->es_plannedstmt->hasIgnore) || + (m_global->m_planstmt && m_global->m_planstmt->hasIgnore); ExecOpenIndices(result_rel_info, speculative); } diff --git a/src/gausskernel/storage/access/common/printtup.cpp b/src/gausskernel/storage/access/common/printtup.cpp index 5d9cf9feea47adb1d368b44bd6b2c32b04e10cb4..ebb0e2abcf32668c6d4e8b7cb4bd05e5187228b1 100644 --- a/src/gausskernel/storage/access/common/printtup.cpp +++ b/src/gausskernel/storage/access/common/printtup.cpp @@ -1194,8 +1194,10 @@ void printtup(TupleTableSlot *slot, DestReceiver *self) */ for (i = 0; i < natts; ++i) { PrinttupAttrInfo *thisState = myState->myinfo + i; - if (thisState->format != 0) + if (thisState->format != 0) { binary = true; + break; + } } /* @@ -1255,12 +1257,26 @@ void printtup(TupleTableSlot *slot, DestReceiver *self) #endif need_free = false; switch (thisState->typoutput) { - case F_INT4OUT: - outputstr = output_int32_to_cstring(DatumGetInt32(attr)); - break; - case F_INT8OUT: - outputstr = output_int64_to_cstring(DatumGetInt64(attr)); - break; + case F_INT4OUT: { + int length32 = 0; + outputstr = pg_ltoa_printtup(DatumGetInt32(attr), &length32); +#ifndef ENABLE_MULTIPLE_NODES + t_thrd.xact_cxt.callPrint = false; +#endif + pq_sendcountedtext_printtup(buf, outputstr, length32, thisState->encoding, + (void *)&thisState->convert_finfo); + continue; + } + case F_INT8OUT: { + int length64 = 0; + outputstr = pg_lltoa_printtup(DatumGetInt64(attr), &length64); +#ifndef ENABLE_MULTIPLE_NODES + t_thrd.xact_cxt.callPrint = false; +#endif + pq_sendcountedtext_printtup(buf, outputstr, length64, thisState->encoding, + (void *)&thisState->convert_finfo); + continue; + } case F_BPCHAROUT: /* support dolphin customizing bpcharout */ if (u_sess->attr.attr_sql.dolphin) { diff --git a/src/gausskernel/storage/access/common/reloptions.cpp b/src/gausskernel/storage/access/common/reloptions.cpp index 50bfd7950116422e4b619d025610214ee248913a..bb73d1190c818750bf0624bb0849690ff2519ea7 100644 --- a/src/gausskernel/storage/access/common/reloptions.cpp +++ b/src/gausskernel/storage/access/common/reloptions.cpp @@ -3137,6 +3137,46 @@ bool CheckSegmentStorageOption(List *options) return result; } +static bool ValidateSegmentOption(List *options) +{ + if (options == NULL) { + return true; + } + + ListCell *opt = NULL; + bool result = true; + foreach (opt, options) { + DefElem *def = (DefElem *)lfirst(opt); + + if (pg_strcasecmp(def->defname, "compresstype") == 0) { + /* + * def->arg is NULL, that means it's a RESET action. ignore it. + * def->arg is not NULL, that means it's a SET action, so check it. + */ + if (def->arg) { + int cmpType = (int)strtol(defGetString(def), NULL, RS_CUSTOM_VALUE_TEN); + if (cmpType != COMPRESS_TYPE_NONE) + result = false; + } + break; + } + } + + return result; +} + +void CheckSegmentCompressOption(List *options, char relkind, StorageType storage_type, char *storeChar) +{ + if (ValidateSegmentOption(options)) { + return; + } + + if (!IsInitdb && (storage_type == SEGMENT_PAGE) && (relkind == RELKIND_RELATION) && + (pg_strcasecmp(storeChar, ORIENTATION_ROW) == 0)) { + ereport(ERROR, (errcode(ERRCODE_INVALID_OPTION), errmsg("compresstype can not be used in segment table."))); + } +} + #ifdef USE_SPQ /* * before check spq reloption, make sure guc params of spq_enable_btbuild is on diff --git a/src/gausskernel/storage/access/heap/heapam.cpp b/src/gausskernel/storage/access/heap/heapam.cpp index d438db80504aff84911d5605c69fa131e0e77854..fc917a05f3e31749af458163a392711388f09f5b 100755 --- a/src/gausskernel/storage/access/heap/heapam.cpp +++ b/src/gausskernel/storage/access/heap/heapam.cpp @@ -1842,7 +1842,7 @@ TableScanDesc heap_beginscan_internal(Relation relation, Snapshot snapshot, int */ if (!RelationIsPartitioned(relation)) { RelationIncrementReferenceCount(relation); - } else { + } else if ((flags & SO_TYPE_SAMPLESCAN) == 0) { /* * If the table is a partition table, the current scan must be used by * bitmapscan to scan tuples using GPI. Therefore, @@ -2511,7 +2511,11 @@ bool heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, S */ if (!skip) { /* If it's visible per the snapshot, we must return it */ - valid = HeapTupleSatisfiesVisibility(heap_tuple, snapshot, buffer, has_cur_xact_write); + if (snapshot->satisfies == SNAPSHOT_MVCC) { + valid = HeapTupleSatisfiesMVCC(heap_tuple, snapshot, buffer, has_cur_xact_write); + } else { + valid = HeapTupleSatisfiesVisibility(heap_tuple, snapshot, buffer, has_cur_xact_write); + } /* We unlock buffer if sync xid to finish and xid base may change, so copy base again */ HeapTupleCopyBaseFromPage(heap_tuple, dp); if (isMySerializableXact) { diff --git a/src/gausskernel/storage/access/heap/heapam_visibility.cpp b/src/gausskernel/storage/access/heap/heapam_visibility.cpp index 2b9d77e1579f70cf3de80a15a580f62e3d58de7d..b2a2bbcb376b25e78043f8f19bf1843a463ac7cd 100644 --- a/src/gausskernel/storage/access/heap/heapam_visibility.cpp +++ b/src/gausskernel/storage/access/heap/heapam_visibility.cpp @@ -1023,8 +1023,8 @@ static bool HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, Buffer bu * basis of the true state of the transaction, even if we then pretend we * can't see it.) */ -static bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer, - bool* has_cur_xact_write = NULL) +bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer, + bool* has_cur_xact_write) { HeapTupleHeader tuple = htup->t_data; Assert(ItemPointerIsValid(&htup->t_self)); diff --git a/src/gausskernel/storage/access/nbtree/nbtinsert.cpp b/src/gausskernel/storage/access/nbtree/nbtinsert.cpp index e65beddd708718049d94dcd73a3f5472b1d83ff6..5638800596e1aadddf3ad3446db74dd2081ea73d 100644 --- a/src/gausskernel/storage/access/nbtree/nbtinsert.cpp +++ b/src/gausskernel/storage/access/nbtree/nbtinsert.cpp @@ -1149,6 +1149,7 @@ static void _bt_insertonpg(Relation rel, BTScanInsert itup_key, Buffer buf, Buff xlmeta.level = metad->btm_level; xlmeta.fastroot = metad->btm_fastroot; xlmeta.fastlevel = metad->btm_fastlevel; + xlmeta.allequalimage = metad->btm_allequalimage; int xl_size; if (t_thrd.proc->workingVersionNum < NBTREE_INSERT_OPTIMIZATION_VERSION_NUM) { @@ -2605,4 +2606,4 @@ bool CheckPartitionIsInvisible(GPIScanDesc gpiScan) } return false; -} \ No newline at end of file +} diff --git a/src/gausskernel/storage/access/transam/double_write.cpp b/src/gausskernel/storage/access/transam/double_write.cpp index 27558a4bf8fc7d0fb475eb2e1499f0703313a418..54ecd845190e119ce743594a21d68e5f1a452c8e 100644 --- a/src/gausskernel/storage/access/transam/double_write.cpp +++ b/src/gausskernel/storage/access/transam/double_write.cpp @@ -997,6 +997,9 @@ static void dw_check_batch_parameter_change(knl_g_dw_context *batch_cxt) void dw_recover_all_partial_write_batch(knl_g_dw_context *batch_cxt) { + if (SS_REFORM_PARTNER) { + return; + } int i; int dw_file_num; dw_batch_file_context* batch_file_cxt; @@ -1310,9 +1313,7 @@ void dw_file_check_rebuild() dw_batch_meta_file batch_meta_file; if (!file_exists(DW_BUILD_FILE_NAME)) { - if (!ENABLE_DMS || (ENABLE_DMS && !g_instance.dms_cxt.finishedRecoverOldPrimaryDWFile)) { - return; - } + return; } ereport(LOG, (errmodule(MOD_DW), errmsg("Double write initializing after build"))); @@ -1660,14 +1661,6 @@ void dw_recover_batch_meta_file(int fd, dw_batch_meta_file *batch_meta_file) void dw_remove_batch_meta_file() { - knl_g_dw_context *dw_cxt = &g_instance.dw_batch_cxt; - if (ENABLE_DSS && dw_cxt->fd > 0) { - int rc = close(dw_cxt->fd); - if (rc == -1) { - ereport(ERROR, (errcode_for_file_access(), errmodule(MOD_DW), errmsg("DW file close failed"))); - } - } - ereport(LOG, (errmodule(MOD_DW), errmsg("start remove dw_batch_meta_file."))); dw_remove_file(DW_META_FILE); } @@ -2078,7 +2071,7 @@ void dw_transfer_phybuffer_addr(const BufferDesc *buf_desc, BufferTag *buf_tag) Assert(buf_desc->extra->seg_fileno <= EXTENT_TYPES && buf_desc->extra->seg_fileno > EXTENT_INVALID); buf_tag->rnode.relNode = buf_desc->extra->seg_fileno; buf_tag->blockNum = buf_desc->extra->seg_blockno; - } else if (ENABLE_REFORM && SS_BEFORE_RECOVERY) { + } else if (SS_BEFORE_RECOVERY) { buf_tag->rnode.relNode = buf_desc->extra->seg_fileno; buf_tag->blockNum = buf_desc->extra->seg_blockno; } else { diff --git a/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp b/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp index 8a52568781e2f8eb103a74f11047d18f12c7b3d6..e05c555f2387060352ca8a39f99fbdc9d8d97b6e 100755 --- a/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp +++ b/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp @@ -51,6 +51,7 @@ #include "utils/palloc.h" #include "utils/guc.h" #include "utils/relmapper.h" +#include "replication/ss_disaster_cluster.h" #include "portability/instr_time.h" @@ -73,6 +74,7 @@ #include "replication/slot.h" #include "replication/walreceiver.h" +#include "replication/ddlmessage.h" #include "gssignal/gs_signal.h" #include "utils/atomic.h" #include "pgstat.h" @@ -94,6 +96,7 @@ namespace extreme_rto { LogDispatcher *g_dispatcher = NULL; static const int XLOG_INFO_SHIFT_SIZE = 4; /* xlog info flag shift size */ +#define FILE_MAX_SIZE 1073741824 /* max size of resource pooling page : 1GB */ static const int32 MAX_PENDING = 1; static const int32 ITEM_QUQUE_SIZE_RATIO = 5; @@ -163,6 +166,7 @@ static bool DispatchUHeap2Record(XLogReaderState* record, List* expectedTLIs, Ti static bool DispatchUHeapUndoRecord(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); static bool DispatchUndoActionRecord(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); static bool DispatchRollbackFinishRecord(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); +static bool DispatchLogicalDDLMsgRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); static inline uint32 GetUndoSpaceWorkerId(int zid); static XLogReaderState *GetXlogReader(XLogReaderState *readerState); @@ -170,6 +174,7 @@ void CopyDataFromOldReader(XLogReaderState *newReaderState, const XLogReaderStat void SendSingalToPageWorker(int signal); #ifdef USE_ASSERT_CHECKING +void GetLsnCheckInfo(uint64 *curPosition, XLogRecPtr *curLsn); bool CheckBufHasSpaceToDispatch(XLogRecPtr endRecPtr); #endif @@ -218,6 +223,8 @@ static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1] = { { DispatchRepOriginRecord, RmgrRecordInfoValid, RM_REPLORIGIN_ID, XLOG_REPLORIGIN_SET, XLOG_REPLORIGIN_DROP }, { DispatchCompresseShrinkRecord, RmgrRecordInfoValid, RM_COMPRESSION_REL_ID, XLOG_CFS_SHRINK_OPERATION, XLOG_CFS_SHRINK_OPERATION }, + { DispatchLogicalDDLMsgRecord, RmgrRecordInfoValid, RM_LOGICALDDLMSG_ID, XLOG_LOGICAL_DDL_MESSAGE, + XLOG_LOGICAL_DDL_MESSAGE }, }; const int REDO_WAIT_SLEEP_TIME = 5000; /* 5ms */ @@ -856,6 +863,24 @@ void DispatchRedoRecordToFile(XLogReaderState *record, List *expectedTLIs, Times #ifdef USE_ASSERT_CHECKING uint64 waitCount = 0; while (!CheckBufHasSpaceToDispatch(record->EndRecPtr)) { + if(SS_DISASTER_MAIN_STANDBY_NODE) { + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + uint64 curPosition; + XLogRecPtr curLsn; + GetLsnCheckInfo(&curPosition, &curLsn); + + XLogRecPtr endPtr = record->EndRecPtr; + if (endPtr % XLogSegSize == 0) { + XLByteAdvance(endPtr, SizeOfXLogLongPHD); + } else if (endPtr % XLOG_BLCKSZ == 0) { + XLByteAdvance(endPtr, SizeOfXLogShortPHD); + } + + uint32 len = (uint32)(endPtr - curLsn); + if (info == XLOG_SWITCH && len < FILE_MAX_SIZE) { + break; + } + } RedoInterruptCallBack(); waitCount++; if ((waitCount & PRINT_ALL_WAIT_COUNT) == PRINT_ALL_WAIT_COUNT) { @@ -1317,6 +1342,12 @@ static bool DispatchCompresseShrinkRecord(XLogReaderState *record, List *expecte return true; } +static bool DispatchLogicalDDLMsgRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) +{ + DispatchTxnRecord(record, expectedTLIs); + return true; +} + static bool DispatchBtreeRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) { uint8 info = (XLogRecGetInfo(record) & (~XLR_INFO_MASK)); diff --git a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp index dd66def71a4ea57767b6524825693c6a39de1e46..587bb095ddc2b9eb3bd471d4e0e87c062316637e 100644 --- a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp +++ b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp @@ -74,6 +74,7 @@ #include "replication/slot.h" #include "replication/walreceiver.h" +#include "replication/ddlmessage.h" #include "gssignal/gs_signal.h" #include "utils/atomic.h" #include "pgstat.h" @@ -167,6 +168,7 @@ static bool DispatchUHeap2Record(XLogReaderState* record, List* expectedTLIs, Ti static bool DispatchUHeapUndoRecord(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); static bool DispatchUndoActionRecord(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); static bool DispatchRollbackFinishRecord(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); +static bool DispatchLogicalDDLMsgRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); static inline uint32 GetUndoSpaceWorkerId(int zid); static XLogReaderState *GetXlogReader(XLogReaderState *readerState); @@ -220,6 +222,8 @@ static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1] = { { DispatchRepOriginRecord, RmgrRecordInfoValid, RM_REPLORIGIN_ID, XLOG_REPLORIGIN_SET, XLOG_REPLORIGIN_DROP }, { DispatchCompresseShrinkRecord, RmgrRecordInfoValid, RM_COMPRESSION_REL_ID, XLOG_CFS_SHRINK_OPERATION, XLOG_CFS_SHRINK_OPERATION }, + { DispatchLogicalDDLMsgRecord, RmgrRecordInfoValid, RM_LOGICALDDLMSG_ID, XLOG_LOGICAL_DDL_MESSAGE, + XLOG_LOGICAL_DDL_MESSAGE }, }; const int REDO_WAIT_SLEEP_TIME = 5000; /* 5ms */ @@ -597,6 +601,7 @@ static void StartPageRedoWorkers(uint32 totalThrdNum, bool inRealtimeBuild) RedoRoleInit(&(g_dispatcher->pageLines[i].batchThd), tmpWorkers[workerCnt++], REDO_BATCH, i, isUndoSpaceWorker); RedoRoleInit(&(g_dispatcher->pageLines[i].managerThd), tmpWorkers[workerCnt++], REDO_PAGE_MNG, i, isUndoSpaceWorker); + g_dispatcher->pageLines[i].managerThd->redoItemHashCtrl = g_instance.comm_cxt.predo_cxt.redoItemHashCtrl[i]; RedoRoleInit(&(g_dispatcher->pageLines[i].htabThd), tmpWorkers[workerCnt++], REDO_HTAB_MNG, i, isUndoSpaceWorker); g_dispatcher->pageLines[i].redoThd = (PageRedoWorker **)palloc(sizeof(PageRedoWorker *) * batchWorkerPerMng); @@ -1288,6 +1293,12 @@ static bool DispatchCompresseShrinkRecord(XLogReaderState *record, List *expecte return true; } +static bool DispatchLogicalDDLMsgRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) +{ + DispatchTxnRecord(record, expectedTLIs); + return true; +} + static bool DispatchBtreeRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) { uint8 info = (XLogRecGetInfo(record) & (~XLR_INFO_MASK)); diff --git a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/page_redo.cpp b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/page_redo.cpp index 2b66d4329fe3d06e90b2ac8c91cfb8921d763078..d7b1b39ee83d347f41108e86079ed0a6f022a893 100644 --- a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/page_redo.cpp +++ b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/page_redo.cpp @@ -140,8 +140,8 @@ void RecordBlockCheck(void *rec, XLogRecPtr curPageLsn, uint32 blockId, bool rep #endif void AddRecordReadBlocks(void *rec, uint32 readblocks); -static void AddTrxnHashmap(void *item); -static void AddSegHashmap(void *item); +static void AddTrxnHashMap(void *item); +static void AddSegHashMap(void *item); static bool checkBlockRedoDoneFromHashMap(LWLock *lock, HTAB *hashMap, RedoItemTag redoItemTag, bool *getSharedLock); static bool tryLockHashMap(LWLock *lock, HTAB *hashMap, RedoItemTag redoItemTag, bool *noNeedRedo); static void PageManagerPruneIfRealtimeBuildFailover(); @@ -267,6 +267,7 @@ PageRedoWorker *CreateWorker(uint32 id, bool inRealtimeBuild) worker->DataDir = t_thrd.proc_cxt.DataDir; worker->RecentXmin = u_sess->utils_cxt.RecentXmin; worker->xlogInvalidPages = NULL; + worker->redoItemHashCtrl = NULL; PosixSemaphoreInit(&worker->phaseMarker, 0); worker->oldCtx = NULL; worker->fullSyncFlag = 0; @@ -1237,36 +1238,6 @@ void OnDemandPageManagerProcSegFullSyncState(XLogRecParseState *parsestate) XLogBlockParseStateRelease(parsestate); } -static void SSProcSegPageRedoInSegPageRedoChildState(XLogRecParseState *redoblockstate) -{ - if (SS_ONDEMAND_REALTIME_BUILD_NORMAL) { - BufferTag bufferTag; - XLogRecPtr pageLsn = InvalidXLogRecPtr; - XLogBlockHeadGetBufferTag(&redoblockstate->blockparse.blockhead, &bufferTag); - if (SSRequestPageInOndemandRealtimeBuild(&bufferTag, redoblockstate->blockparse.blockhead.end_ptr, &pageLsn) || - !SSXLogParseRecordNeedReplayInOndemandRealtimeBuild(redoblockstate)) { -#ifdef USE_ASSERT_CHECKING - bool willinit = (XLogBlockDataGetBlockFlags((XLogBlockDataParse *)&redoblockstate->blockparse.extra_rec) & - BKPBLOCK_WILL_INIT); - DoRecordCheck(redoblockstate, pageLsn, !willinit); -#endif - ereport(DEBUG1, (errmsg("[On-demand] standby node request page success during ondemand realtime build, " - "spc/db/rel/bucket fork-block: %u/%u/%u/%d %d-%u, recordlsn: %X/%X, pagelsn: %X/%X", - bufferTag.rnode.spcNode, bufferTag.rnode.dbNode, bufferTag.rnode.relNode, bufferTag.rnode.bucketNode, - bufferTag.forkNum, bufferTag.blockNum, (uint32)(redoblockstate->blockparse.blockhead.end_ptr >> 32), - (uint32)redoblockstate->blockparse.blockhead.end_ptr, (uint32)(pageLsn >> 32), (uint32)pageLsn))); - XLogBlockParseStateRelease(redoblockstate); - return; - } - ereport(DEBUG1, (errmsg("[On-demand] standby node request page failed during ondemand realtime build, " - "spc/db/rel/bucket fork-block: %u/%u/%u/%d %d-%u, recordlsn: %X/%X, pagelsn: %X/%X", - bufferTag.rnode.spcNode, bufferTag.rnode.dbNode, bufferTag.rnode.relNode, bufferTag.rnode.bucketNode, - bufferTag.forkNum, bufferTag.blockNum, (uint32)(redoblockstate->blockparse.blockhead.end_ptr >> 32), - (uint32)redoblockstate->blockparse.blockhead.end_ptr, (uint32)(pageLsn >> 32), (uint32)pageLsn))); - } - SegPageRedoChildState(redoblockstate); -} - // for less ondmeand recovery memory consume static void SSReleaseRefRecordWithoutReplay(XLogRecParseState *redoblockstate) { @@ -1278,28 +1249,6 @@ static void SSReleaseRefRecordWithoutReplay(XLogRecParseState *redoblockstate) redoblockstate->refrecord = NULL; } -static void SSProcPageRedoInSegPageRedoChildState(XLogRecParseState *redoblockstate) -{ - AddSegHashmap(redoblockstate); -} - -static void SSSegPageRedoChildState(XLogRecParseState *childStateList) -{ - BufferTag bufferTag; - XLogRecParseState *procState = childStateList; - while (procState != NULL) { - XLogRecParseState *redoblockstate = procState; - procState = (XLogRecParseState *)procState->nextrecord; - redoblockstate->nextrecord = NULL; - XLogBlockHeadGetBufferTag(&redoblockstate->blockparse.blockhead, &bufferTag); - if (IsSegmentPhysicalRelNode(bufferTag.rnode)) { - SSProcSegPageRedoInSegPageRedoChildState(redoblockstate); - } else { - SSProcPageRedoInSegPageRedoChildState(redoblockstate); - } - } -} - static void SSProcSegPageCommonRedo(XLogRecParseState *parseState) { uint8 info = XLogBlockHeadGetInfo(&parseState->blockparse.blockhead) & ~XLR_INFO_MASK; @@ -1313,7 +1262,7 @@ static void SSProcSegPageCommonRedo(XLogRecParseState *parseState) { XLogRecParseState *child = (XLogRecParseState *)parseState->blockparse.extra_rec.blocksegfullsyncrec.childState; - SSSegPageRedoChildState(child); + AddSegHashMap(child); break; } case XLOG_SEG_CREATE_EXTENT_GROUP: @@ -1669,7 +1618,6 @@ void RedoPageManagerMain() uint32 eleNum; (void)RegisterRedoInterruptCallBack(HandlePageRedoInterrupts); - g_redoWorker->redoItemHashCtrl = g_instance.comm_cxt.predo_cxt.redoItemHashCtrl[g_redoWorker->slotId]; GetRedoStartTime(g_redoWorker->timeCostList[TIME_COST_STEP_1]); while (SPSCBlockingQueueGetAll(g_redoWorker->queue, &eleArry, &eleNum)) { @@ -1763,7 +1711,7 @@ static void TrxnManagerAddTrxnRecord(RedoItem *item, bool syncRecord) TrxnManagerProcHashMapPrune(); DereferenceRedoItem(item); } else { - AddTrxnHashmap(item); + AddTrxnHashMap(item); } } else { AddPageRedoItem(g_dispatcher->trxnLine.redoThd, item); @@ -2023,17 +1971,9 @@ void RedoPageWorkerCheckPoint(const XLogRecParseState *redoblockstate) static void SegWorkerRedoAllSegBlockRecord() { - RedoTimeCost timeCost1; - RedoTimeCost timeCost2; - while (!SPSCBlockingQueueIsEmpty(g_dispatcher->segQueue)) { XLogRecParseState *segRecord = (XLogRecParseState *)SPSCBlockingQueueTop(g_dispatcher->segQueue); - RedoBufferInfo bufferinfo = {0}; - (void)XLogBlockRedoForExtremeRTO(segRecord, &bufferinfo, false, timeCost1, timeCost2); - if (bufferinfo.pageinfo.page != NULL) { - MarkSegPageRedoChildPageDirty(&bufferinfo); - } - XLogBlockParseStateRelease(segRecord); + SegPageRedoChildState(segRecord); SPSCBlockingQueuePop(g_dispatcher->segQueue); } } @@ -3354,6 +3294,10 @@ void HashMapManagerMain() { (void)RegisterRedoInterruptCallBack(HandlePageRedoInterrupts); + /** + * Each pipelint has a redoItem HashMap linked list. When the size of tail hashmap is up to limit, pageRedoManager + * will init a new redoItem hashMap and put it to the tail of linked List, hashmap manager is used to clean hashmap entry. + */ do { bool pruneMax = false; bool updateStat = true; @@ -3380,15 +3324,27 @@ void HashMapManagerMain() break; } #ifdef USE_ASSERT_CHECKING - DoRecordCheck(segRecord, InvalidXLogRecPtr, false); + XLogRecParseState *procState = segRecord; + while (procState != NULL) { + XLogRecParseState *redoblockstate = procState; + procState = (XLogRecParseState *)procState->nextrecord; + DoRecordCheck(redoblockstate, InvalidXLogRecPtr, false); + } #endif XLogBlockParseStateRelease(segRecord); SPSCBlockingQueuePop(g_dispatcher->segQueue); } - // step2: prune idle hashmap + /** + * step2: prune idle hashmap + * + * If one redoItem hashmap's maxRedoItem < checkkpoint redo point, all entrys + * are no logger useful, so we can free this hashmap. + */ CountAndGetRedoTime(g_redoWorker->timeCostList[TIME_COST_STEP_1], t_thrd.xlog_cxt.timeCost[TIME_COST_STEP_2]); + // the head of redoItem hashmap linked list ondemand_htab_ctrl_t *nextHtabCtrl = g_instance.comm_cxt.predo_cxt.redoItemHashCtrl[g_redoWorker->slotId]; + // the tail of redoItem hashmap linked list ondemand_htab_ctrl_t *targetHtabCtrl = g_dispatcher->pageLines[g_redoWorker->slotId].managerThd->redoItemHashCtrl; while (nextHtabCtrl != targetHtabCtrl) { ondemand_htab_ctrl_t *procHtabCtrl = nextHtabCtrl; @@ -3882,12 +3838,12 @@ void AddPageRedoItem(PageRedoWorker *worker, void *item) SPSCBlockingQueuePut(worker->queue, item); } -static void AddTrxnHashmap(void *item) +static void AddTrxnHashMap(void *item) { SPSCBlockingQueuePut(g_dispatcher->trxnQueue, item); } -static void AddSegHashmap(void *item) +static void AddSegHashMap(void *item) { SPSCBlockingQueuePut(g_dispatcher->segQueue, item); } diff --git a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/redo_utils.cpp b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/redo_utils.cpp index c2f93ea917ff867fddd11e82d2a79a1f4811da65..09b121d7aa09a64319e1294a4f08ab1109d18fe3 100644 --- a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/redo_utils.cpp +++ b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/redo_utils.cpp @@ -577,15 +577,4 @@ XLogRecPtr GetRedoLocInCheckpointRecord(XLogReaderState *record) checkPoint = checkPointUndo.ori_checkpoint; } return checkPoint.redo; -} - -void WaitUntilRealtimeBuildStatusToFailoverAndUpdatePrunePtr() -{ - while (SS_ONDEMAND_REALTIME_BUILD_NORMAL) { - pg_usleep(100000L); /* 100 ms */ - } - RedoInterruptCallBack(); - Assert(SS_ONDEMAND_REALTIME_BUILD_FAILOVER); - ondemand_extreme_rto::g_redoWorker->nextPrunePtr = - pg_atomic_read_u64(&ondemand_extreme_rto::g_dispatcher->ckptRedoPtr); -} +} \ No newline at end of file diff --git a/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp b/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp index 734cf72e192b28c7ae1d01cc98ca11628e7cd578..3aaa52a1434b676db9c90c527bbda575aa9ebecd 100755 --- a/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp +++ b/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp @@ -72,6 +72,7 @@ #include "commands/sequence.h" #include "replication/slot.h" +#include "replication/ddlmessage.h" #include "gssignal/gs_signal.h" #include "utils/atomic.h" #include "pgstat.h" @@ -165,6 +166,7 @@ static bool DispatchUHeap2Record(XLogReaderState *record, List *expectedTLIs, Ti static bool DispatchUHeapUndoRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); static bool DispatchUndoActionRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); static bool DispatchRollbackFinishRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); +static bool DispatchLogicalDDLMsgRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); static uint32 GetUndoSpaceWorkerId(int zid); static void HandleStartupProcInterruptsForParallelRedo(void); static bool timeoutForDispatch(void); @@ -214,6 +216,8 @@ static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1] = { { DispatchRepOriginRecord, RmgrRecordInfoValid, RM_REPLORIGIN_ID, XLOG_REPLORIGIN_SET, XLOG_REPLORIGIN_DROP }, { DispatchCompresseShrinkRecord, RmgrRecordInfoValid, RM_COMPRESSION_REL_ID, XLOG_CFS_SHRINK_OPERATION, XLOG_CFS_SHRINK_OPERATION }, + { DispatchLogicalDDLMsgRecord, RmgrRecordInfoValid, RM_LOGICALDDLMSG_ID, XLOG_LOGICAL_DDL_MESSAGE, + XLOG_LOGICAL_DDL_MESSAGE }, }; /* Run from the dispatcher and txn worker thread. */ @@ -1192,6 +1196,12 @@ static bool DispatchCompresseShrinkRecord(XLogReaderState *record, List *expecte return true; } +static bool DispatchLogicalDDLMsgRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) +{ + DispatchTxnRecord(record, expectedTLIs, recordXTime, false); + return true; +} + static bool DispatchBtreeRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) { uint8 info = (XLogRecGetInfo(record) & (~XLR_INFO_MASK)); diff --git a/src/gausskernel/storage/access/transam/parallel_recovery/page_redo.cpp b/src/gausskernel/storage/access/transam/parallel_recovery/page_redo.cpp index 2ec8b0351d4ded1e7a9d6032ca4af90cac9d70f8..48f79c9f64cf1865d1fb4b130c7895907a2d7d05 100755 --- a/src/gausskernel/storage/access/transam/parallel_recovery/page_redo.cpp +++ b/src/gausskernel/storage/access/transam/parallel_recovery/page_redo.cpp @@ -579,6 +579,8 @@ static void wait_valid_snapshot(XLogReaderState *record) */ while(t_thrd.xact_cxt.ShmemVariableCache->standbyXmin < xlrec->latestRemovedXid && !in_full_sync_dispatch()) { + XLogRecPtr lastReplayedEndRecPtr = 0; + if(cur_transed_lsn == InvalidXLogRecPtr) cur_transed_lsn = getTransedTxnLsn(g_dispatcher->txnWorker); txn_trying_lsn = getTryingTxnLsn(g_dispatcher->txnWorker); @@ -590,16 +592,16 @@ static void wait_valid_snapshot(XLogReaderState *record) * So if all xact record before current vacuum record finished, then avoid wait. * And if startup go fast then here on lsn, it can avoid wait too. */ - if (cur_transed_lsn <= GetXLogReplayRecPtr(NULL) || txn_trying_lsn >= record->EndRecPtr) + lastReplayedEndRecPtr = GetXLogReplayRecPtr(NULL); + if (cur_transed_lsn <= lastReplayedEndRecPtr || txn_trying_lsn >= record->EndRecPtr) return; blockcnt++; if ((blockcnt & OUTPUT_WAIT_COUNT) == OUTPUT_WAIT_COUNT) { - XLogRecPtr LatestReplayedRecPtr = GetXLogReplayRecPtr(NULL); ereport(WARNING, (errmodule(MOD_REDO), errcode(ERRCODE_LOG), errmsg("[REDO_LOG_TRACE]wait_valid_snapshot:recordEndLsn:%lu, blockcnt:%lu, " "Workerid:%u, LatestReplayedRecPtr:%lu", - record->EndRecPtr, blockcnt, g_redoWorker->id, LatestReplayedRecPtr))); + record->EndRecPtr, blockcnt, g_redoWorker->id, lastReplayedEndRecPtr))); } RedoInterruptCallBack(); } diff --git a/src/gausskernel/storage/access/transam/single_double_write.cpp b/src/gausskernel/storage/access/transam/single_double_write.cpp index 25e4aef81499977ce1efe7b127bd3af2aedfca8b..b11c277497c276bd2eb97bf2034ca0e7aab64934 100644 --- a/src/gausskernel/storage/access/transam/single_double_write.cpp +++ b/src/gausskernel/storage/access/transam/single_double_write.cpp @@ -487,6 +487,9 @@ void dw_force_reset_single_file(uint32 dw_version) void dw_recovery_partial_write_single() { + if (SS_REFORM_REFORMER) { + return; + } knl_g_dw_context* single_cxt = &g_instance.dw_single_cxt; ereport(LOG, (errmodule(MOD_DW), errmsg("DW single flush file recovery start."))); diff --git a/src/gausskernel/storage/access/transam/xact.cpp b/src/gausskernel/storage/access/transam/xact.cpp index d51b127e8e22c338037319dea0598bdfb5819dce..fa902c97752077f9a392c7cdf9413d84424bb471 100755 --- a/src/gausskernel/storage/access/transam/xact.cpp +++ b/src/gausskernel/storage/access/transam/xact.cpp @@ -3036,6 +3036,11 @@ static void CommitTransaction(bool STP_commit) #endif AtEOXact_SysDBCache(true); + + if (!STP_commit) { + gsplsql_unlock_func_pkg_dependency_all(); + } + ResourceOwnerRelease(t_thrd.utils_cxt.TopTransactionResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, true, true); /* Check we've released all buffer pins */ @@ -3946,6 +3951,10 @@ static void AbortTransaction(bool PerfectRollback, bool STP_rollback) */ ProcArrayEndTransaction(t_thrd.proc, latestXid, false); + if (!STP_rollback) { + gsplsql_unlock_func_pkg_dependency_all(); + } + /* * Post-abort cleanup. See notes in CommitTransaction() concerning * ordering. We can skip all of it if the transaction failed before diff --git a/src/gausskernel/storage/access/transam/xlog.cpp b/src/gausskernel/storage/access/transam/xlog.cpp index ffacfe272a309fba01112ad589054cfc73a8a9aa..26a09171b1d5c6c8d0132ca40ee3c5ef6a2b93c1 100755 --- a/src/gausskernel/storage/access/transam/xlog.cpp +++ b/src/gausskernel/storage/access/transam/xlog.cpp @@ -379,8 +379,7 @@ static bool UwalAcquire(); static void SetUwalReadInfo(XLogRecPtr targetPagePtr, XLogRecPtr writeUwalOffSet, uint32 targetPageOff); void XlogArchUwal(XLogRecPtr archRqstPtr); int GsUwalCreate(uint64_t startOffset); -int GsUwalWrite(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos); -int GsUwalWriteAsync(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos); +int GsUwalWrite(int nBytes, char *buf, uint64_t writeOffset); int GsUwalRead(UwalId *id, XLogRecPtr targetPagePtr, char *readBuf, uint64_t readlen); int GsUwalQuery(UwalId *id, UwalBaseInfo *info); static void XLogFlushUwal(XLogRecPtr writeRqstPtr); @@ -2975,6 +2974,7 @@ static void XLogWriteUwal(XLogRecPtr UwalWriteRqst) XLogRecPtr lastWrited = InvalidXLogRecPtr; uint32 offset; bool firstUwal = false; + uint64_t targetOffset = 0; int uwalMaxPages = UWAL_OBJ_ALIGN_LEN / XLOG_BLCKSZ; if (g_instance.attr.attr_storage.uwal_async_append_switch) { uwalMaxPages = uwalMaxPages * 4; @@ -3089,32 +3089,16 @@ static void XLogWriteUwal(XLogRecPtr UwalWriteRqst) if (firstUwal) { from = t_thrd.shemem_ptr_cxt.XLogCtl->pages + startidx * (Size)XLOG_BLCKSZ; nbytes = WriteTotal; + targetOffset = lastWrited - offset; } else { from = t_thrd.shemem_ptr_cxt.XLogCtl->pages + startidx * (Size)XLOG_BLCKSZ + offset; nbytes = WriteTotal - offset; + targetOffset = lastWrited; } - UwalNodeInfo *infos = - (UwalNodeInfo *)palloc0(sizeof(UwalNodeInfo) + MAX_GAUSS_NODE * sizeof(UwalNodeStatus)); pgstat_report_waitevent(WAIT_EVENT_WAL_WRITE); INSTR_TIME_SET_CURRENT(startTime); - if (g_instance.attr.attr_storage.uwal_async_append_switch) { - ret = GsUwalWriteAsync(&t_thrd.xlog_cxt.uwalInfo.id, nbytes, from, infos); - while (ret == REPLICA_APPEND_LOG_FAIL || ret == U_CAPACITY_NOT_ENOUGH) { - if (ret == U_CAPACITY_NOT_ENOUGH) { - usleep(UWAL_SLEEP_TIME); - } - ret = GsUwalWriteAsync(&t_thrd.xlog_cxt.uwalInfo.id, nbytes, from, infos); - } - } else { - ret = GsUwalWrite(&t_thrd.xlog_cxt.uwalInfo.id, nbytes, from, infos); - while (ret == REPLICA_APPEND_LOG_FAIL || ret == U_CAPACITY_NOT_ENOUGH) { - if (ret == U_CAPACITY_NOT_ENOUGH) { - usleep(UWAL_SLEEP_TIME); - } - ret = GsUwalWrite(&t_thrd.xlog_cxt.uwalInfo.id, nbytes, from, infos); - } - } + ret = GsUwalWrite(nbytes, from, targetOffset); INSTR_TIME_SET_CURRENT(endTime); INSTR_TIME_SUBTRACT(endTime, startTime); /* when track_activities and enable_instr_track_wait are on, @@ -3139,11 +3123,11 @@ static void XLogWriteUwal(XLogRecPtr UwalWriteRqst) reportRedoWrite((PgStat_Counter)npages, elapsedTime); lastWrited += WriteTotal - offset; + if (ret == 0) { - GsUwalUpdateSenderSyncLsn(lastWrited, infos); + GsUwalUpdateSenderSyncLsn(lastWrited); GsUwalRcvStateUpdate(lastWrited); } - pfree(infos); npages = 0; offset = lastWrited % XLOG_BLCKSZ; @@ -9278,6 +9262,8 @@ void StartupXLOG(void) * not do ReadControlFile() here, but might as well do it to be sure. */ if (ENABLE_DMS && ENABLE_DSS) { + ss_reform_info_t *reform_info = &g_instance.dms_cxt.SSReformInfo; + reform_info->reform_ver_startup_wait = reform_info->reform_ver; int src_id = INVALID_INSTANCEID; SSReadControlFile(REFORM_CTRL_PAGE); if (SS_CLUSTER_ONDEMAND_NOT_NORAML && SS_PRIMARY_MODE) { @@ -9740,8 +9726,8 @@ void StartupXLOG(void) * in SS Switchover, skip dw init since we didn't do ShutdownXLOG */ - if ((ENABLE_REFORM && SS_REFORM_REFORMER && !SS_STANDBY_FAILOVER && !SS_PERFORMING_SWITCHOVER) || - !ENABLE_DMS || !ENABLE_REFORM) { + if ((!SS_STANDBY_FAILOVER && !SS_PERFORMING_SWITCHOVER && + !SS_ONDEMAND_REALTIME_BUILD_READY_TO_BUILD) || !ENABLE_DMS) { /* process assist file of chunk recycling */ dw_ext_init(); dw_init(); @@ -9750,11 +9736,7 @@ void StartupXLOG(void) } } - if (SS_REFORM_REFORMER && SS_STANDBY_PROMOTING) { - ss_switchover_promoting_dw_init(); - } - - if (SS_IN_FAILOVER && SS_REFORM_REFORMER) { + if (SS_STANDBY_FAILOVER) { ss_failover_dw_init(); } @@ -10968,9 +10950,14 @@ void StartupXLOG(void) * If we do checkpoint, nextxid record as a part of runningxacts, and * we may try to access according clog page during recovery. * Just extend it here to avoid this situation. + * + * Standby node of standby cluster can not extend page in SS_DORADO_CLUSTER, + * because a xlog record will be inserted for extending clog page. */ - ExtendCLOG(t_thrd.xact_cxt.ShmemVariableCache->nextXid); - ExtendCSNLOG(t_thrd.xact_cxt.ShmemVariableCache->nextXid); + if (!SS_DORADO_STANDBY_CLUSTER_STANDBY_NODE) { + ExtendCLOG(t_thrd.xact_cxt.ShmemVariableCache->nextXid); + ExtendCSNLOG(t_thrd.xact_cxt.ShmemVariableCache->nextXid); + } /* * All done. Allow backends to write WAL. (Although the bool flag is @@ -11117,7 +11104,7 @@ void StartupXLOG(void) } #endif - if (ENABLE_DMS && ENABLE_REFORM && !SS_PRIMARY_DEMOTED && !SS_DISASTER_STANDBY_CLUSTER) { + if (ENABLE_DMS && !SS_PRIMARY_DEMOTED && !SS_DISASTER_STANDBY_CLUSTER) { StartupWaitReform(); } @@ -16562,15 +16549,19 @@ XLogRecPtr GetXLogReplayRecPtr(TimeLineID *targetTLI, XLogRecPtr *ReplayReadPtr) XLogCtlData *xlogctl = t_thrd.shemem_ptr_cxt.XLogCtl; XLogRecPtr recptr; - SpinLockAcquire(&xlogctl->info_lck); - recptr = xlogctl->lastReplayedEndRecPtr; - if (targetTLI != NULL) { - *targetTLI = xlogctl->RecoveryTargetTLI; - } - if (ReplayReadPtr != NULL) { - *ReplayReadPtr = xlogctl->lastReplayedReadRecPtr; + if (!targetTLI && !ReplayReadPtr) + recptr = pg_atomic_read_u64((volatile uint64*)&xlogctl->lastReplayedEndRecPtr); + else { + SpinLockAcquire(&xlogctl->info_lck); + recptr = xlogctl->lastReplayedEndRecPtr; + if (targetTLI != NULL) { + *targetTLI = xlogctl->RecoveryTargetTLI; + } + if (ReplayReadPtr != NULL) { + *ReplayReadPtr = xlogctl->lastReplayedReadRecPtr; + } + SpinLockRelease(&xlogctl->info_lck); } - SpinLockRelease(&xlogctl->info_lck); return recptr; } @@ -17351,6 +17342,8 @@ retry: if (havedata && targetPagePtr >= t_thrd.xlog_cxt.uwalInfo.info.truncateOffset) { SetUwalReadInfo(targetPagePtr, t_thrd.xlog_cxt.receivedUpto, targetPageOff); goto uwal_buf_read; + } else if (havedata && !GsUwalCheckFileRename(targetPagePtr)) { + goto retry; } } @@ -17701,6 +17694,9 @@ retry: (targetPagePtr + reqLen <= t_thrd.xlog_cxt.uwalInfo.info.writeOffset)) { SetUwalReadInfo(targetPagePtr, t_thrd.xlog_cxt.uwalInfo.info.writeOffset, targetPageOff); goto uwal_buf_read; + } else if (targetPagePtr < t_thrd.xlog_cxt.uwalInfo.info.truncateOffset && + !GsUwalCheckFileRename(targetPagePtr)) { + goto retry; } } @@ -17777,37 +17773,21 @@ retry: if (t_thrd.xlog_cxt.InArchiveRecovery) { sources |= XLOG_FROM_ARCHIVE; } - if (g_instance.attr.attr_storage.enable_uwal && UwalAcquire()) { - if (t_thrd.xlog_cxt.uwalInfo.info.dataSize > 0) { - if (targetPagePtr >= t_thrd.xlog_cxt.uwalInfo.info.truncateOffset) { - if (targetPagePtr + reqLen > t_thrd.xlog_cxt.uwalInfo.info.writeOffset) { - if (0 == GsUwalQuery(&t_thrd.xlog_cxt.uwalInfo.id, &t_thrd.xlog_cxt.uwalInfo.info)) { - if (targetPagePtr + reqLen > t_thrd.xlog_cxt.uwalInfo.info.writeOffset) { - goto next_record_is_invalid; - } - } - } - t_thrd.xlog_cxt.curFileTLI = t_thrd.xlog_cxt.uwalInfo.info.startTimeLine; - t_thrd.xlog_cxt.readLen = XLOG_BLCKSZ; - t_thrd.xlog_cxt.readOff = targetPageOff; - goto uwal_buf_read; - } - } - } - if (g_instance.attr.attr_storage.enable_uwal && UwalAcquire() && - t_thrd.xlog_cxt.uwalInfo.info.dataSize > 0 && - targetPagePtr >= t_thrd.xlog_cxt.uwalInfo.info.truncateOffset) { - if (targetPagePtr + reqLen > t_thrd.xlog_cxt.uwalInfo.info.writeOffset) { - GsUwalQuery(&t_thrd.xlog_cxt.uwalInfo.id, &t_thrd.xlog_cxt.uwalInfo.info); - if (targetPagePtr + reqLen > t_thrd.xlog_cxt.uwalInfo.info.writeOffset) { + t_thrd.xlog_cxt.uwalInfo.info.dataSize > 0) { + if (targetPagePtr >= t_thrd.xlog_cxt.uwalInfo.info.truncateOffset) { + if (targetPagePtr + reqLen > t_thrd.xlog_cxt.uwalInfo.info.writeOffset && + 0 == GsUwalQuery(&t_thrd.xlog_cxt.uwalInfo.id, &t_thrd.xlog_cxt.uwalInfo.info) && + targetPagePtr + reqLen > t_thrd.xlog_cxt.uwalInfo.info.writeOffset) { goto next_record_is_invalid; } + t_thrd.xlog_cxt.curFileTLI = t_thrd.xlog_cxt.uwalInfo.info.startTimeLine; + t_thrd.xlog_cxt.readLen = XLOG_BLCKSZ; + t_thrd.xlog_cxt.readOff = targetPageOff; + goto uwal_buf_read; + } else if (!GsUwalCheckFileRename(targetPagePtr)) { + goto retry; } - t_thrd.xlog_cxt.curFileTLI = t_thrd.xlog_cxt.uwalInfo.info.startTimeLine; - t_thrd.xlog_cxt.readLen = XLOG_BLCKSZ; - t_thrd.xlog_cxt.readOff = targetPageOff; - goto uwal_buf_read; } t_thrd.xlog_cxt.readFile = XLogFileReadAnyTLI(t_thrd.xlog_cxt.readSegNo, emode, sources); @@ -17858,6 +17838,8 @@ retry: } } goto uwal_buf_read; + } else if (!GsUwalCheckFileRename(targetPagePtr)) { + goto retry; } } @@ -20762,6 +20744,9 @@ static bool UwalAcquire() if (GsUwalQueryByUser(tli, false) != 0) { ereport(PANIC, (errcode_for_file_access(), errmsg("uwal query by user failed"))); } + if (t_thrd.xlog_cxt.uwalInfo.info.dataSize > 0) { + GsUwalRenewFileRenamePtr(); + } } if (t_thrd.xlog_cxt.uwalInfo.info.dataSize > 0) { diff --git a/src/gausskernel/storage/buffer/bufmgr.cpp b/src/gausskernel/storage/buffer/bufmgr.cpp index 991ab1d67b797abdd0454341feb684ee886195e6..70cca60c094958f3ad4f7d155a719b40dd41c7b9 100644 --- a/src/gausskernel/storage/buffer/bufmgr.cpp +++ b/src/gausskernel/storage/buffer/bufmgr.cpp @@ -2190,14 +2190,6 @@ static bool ReadBuffer_common_ReadBlock(SMgrRelation smgr, char relpersistence, } } - if (ENABLE_DMS) { - Buffer buf = BlockGetBuffer((char *)bufBlock); - dms_buf_ctrl_t *buf_ctrl = GetDmsBufCtrl(buf - 1); - if (buf_ctrl->lock_mode == DMS_LOCK_NULL) { - ereport(PANIC, (errmsg("It seemd read buffer not across DMS!"))); - } - } - return needputtodirty; } @@ -5887,7 +5879,8 @@ void flush_all_buffers(Relation rel, Oid db_id, HTAB *hashtbl) ReservePrivateRefCountEntry(); buf_state = LockBufHdr(buf_desc); - if (!flush_buffer_match(buf_desc, rel, db_id) || !dw_buf_valid_dirty(buf_state)) { + if (!flush_buffer_match(buf_desc, rel, db_id) || + !(dw_buf_valid_dirty(buf_state) && dw_buf_valid_aio_finished(buf_desc, buf_state))) { UnlockBufHdr(buf_desc, buf_state); continue; } diff --git a/src/gausskernel/storage/cmgr/cache_mgr.cpp b/src/gausskernel/storage/cmgr/cache_mgr.cpp index fa1351c5b553c8dc95873690c17f9f99b97ed945..b58d50f31cc28395a2d5b9c70b5aed26c3cb6a91 100644 --- a/src/gausskernel/storage/cmgr/cache_mgr.cpp +++ b/src/gausskernel/storage/cmgr/cache_mgr.cpp @@ -51,6 +51,7 @@ typedef struct CacheLookupEnt { looped++; \ if (looped > MAX_LOOPS) { \ if (retryNum > MAX_RETRY_NUM) { \ + UnlockSweep(); \ ereport(ERROR, \ (errcode(ERRCODE_OUT_OF_BUFFER), errmodule(MOD_CACHE), \ errmsg("No free Cache Blocks! cstore_buffers maybe too small, scanned=%d," \ diff --git a/src/gausskernel/storage/file/fd.cpp b/src/gausskernel/storage/file/fd.cpp index 67e351ca9e929f39a3ca0613b57f8bbcbfd4682e..a15498bdffc8d5c6ff050497f2b51c323a8b0cb6 100755 --- a/src/gausskernel/storage/file/fd.cpp +++ b/src/gausskernel/storage/file/fd.cpp @@ -2100,9 +2100,7 @@ retry: pgstat_report_waitevent(WAIT_EVENT_END); PROFILING_MDIO_END_READ((uint32)amount, returnCode); - if (returnCode >= 0) - vfdcache[file].seekPos += returnCode; - else { + if (returnCode < 0) { /* * Windows may run out of kernel buffers and return "Insufficient * system resources" error. Wait a bit and retry to solve it. @@ -2138,9 +2136,6 @@ retry: goto retry; } } - - /* Trouble, so assume we don't know the file position anymore */ - vfdcache[file].seekPos = FileUnknownPos; } return returnCode; @@ -2241,11 +2236,11 @@ int FilePWrite(File file, const char* buffer, int amount, off_t offset, uint32 w * immediately anyway, so this is safe at present. */ if (vfdcache[file].fdstate & FD_TEMP_FILE_LIMIT) { - off_t newPos = vfdcache[file].seekPos + amount; + off_t past_write = offset + amount; - if (newPos > vfdcache[file].fileSize) { + if (past_write > vfdcache[file].fileSize) { uint64 newTotal = u_sess->storage_cxt.temporary_files_size; - uint64 incSize = (uint64)(newPos - vfdcache[file].fileSize); + uint64 incSize = (uint64)(past_write - vfdcache[file].fileSize); WLMGeneralParam* g_wlm_params = &u_sess->wlm_cxt->wlm_params; unsigned char state = g_wlm_params->iostate; g_wlm_params->iostate = IOSTATE_WRITE; @@ -2253,7 +2248,7 @@ int FilePWrite(File file, const char* buffer, int amount, off_t offset, uint32 w g_wlm_params->iostate = state; if (u_sess->attr.attr_sql.temp_file_limit >= 0) { - newTotal += newPos - vfdcache[file].fileSize; + newTotal += incSize; if (newTotal > (uint64)(uint32)u_sess->attr.attr_sql.temp_file_limit * (uint64)1024) ereport(ERROR, (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), @@ -2275,15 +2270,13 @@ retry: errno = ENOSPC; if (returnCode >= 0) { - vfdcache[file].seekPos += returnCode; - /* maintain fileSize and temporary_files_size if it's a temp file */ if (vfdcache[file].fdstate & FD_TEMP_FILE_LIMIT) { - off_t newPos = vfdcache[file].seekPos; + off_t past_write = offset + amount; - if (newPos > vfdcache[file].fileSize) { - u_sess->storage_cxt.temporary_files_size += newPos - vfdcache[file].fileSize; - vfdcache[file].fileSize = newPos; + if (past_write > vfdcache[file].fileSize) { + u_sess->storage_cxt.temporary_files_size += past_write - vfdcache[file].fileSize; + vfdcache[file].fileSize = past_write; } } } else { @@ -2318,9 +2311,6 @@ retry: goto retry; } } - - /* Trouble, so assume we don't know the file position anymore */ - vfdcache[file].seekPos = FileUnknownPos; } return returnCode; diff --git a/src/gausskernel/storage/gs_uwal/gs_uwal.cpp b/src/gausskernel/storage/gs_uwal/gs_uwal.cpp index c529efcb9f6a037c815aa72d573185fa2c3e5ead..9b7d2c19f0142327e2bcb517b65019a7e3ffea24 100644 --- a/src/gausskernel/storage/gs_uwal/gs_uwal.cpp +++ b/src/gausskernel/storage/gs_uwal/gs_uwal.cpp @@ -47,16 +47,22 @@ #define UWAL_TIMEOUT "30000" #define UWAL_MIN_PAGES 4 #define UWAL_WORKER_NUM 4 +#define UWAL_RETRY_INTERVAL_US 10000 int64 uwal_size = XLogSegSize; UwalConfig g_uwalConfig; +UwalNodeInfo g_infoList[UWAL_WORKER_NUM]; +UwalAsynCommonCbCtx g_commonCbCtx; +UwalAsyncCbCtx g_cbCtxList[UWAL_WORKER_NUM]; int ock_uwal_init(IN const char *path, IN const UwalCfgElem *elems, IN int cnt, IN const char *ulogPath); void ock_uwal_exit(void); int ock_uwal_create(IN UwalCreateParam *param, OUT UwalVector *uwals); int ock_uwal_delete(IN UwalDeleteParam *param); int ock_uwal_append(IN UwalAppendParam *param, OUT uint64_t *offset, OUT void *result); +int ock_uwal_append_with_offset(IN UwalAppendParam *param, IN uint64_t targetOffset, + OUT uint64_t *offset, OUT void *result); int ock_uwal_read(IN UwalReadParam *param, OUT UwalBufferList *bufferList); int ock_uwal_truncate(IN const UwalId *uwalId, IN uint64_t offset); int ock_uwal_query(IN UwalQueryParam *param, OUT UwalInfo *info); @@ -75,6 +81,37 @@ int GsUwalLoadSymbols() return uwal_init_symbols(); } +static void GsUwalAppendAsyncResetCbCtx() +{ + g_commonCbCtx.opCount = 0; + g_commonCbCtx.curCount = 0; + g_commonCbCtx.ret = 0; + g_commonCbCtx.interrupted = false; + g_commonCbCtx.interruptCount = 0; + + for (int i = 0; i < UWAL_WORKER_NUM; i++) { + g_cbCtxList[i].buf = nullptr; + g_cbCtxList[i].ret = 0; + g_cbCtxList[i].writeOffset = 0; + g_cbCtxList[i].writeLen = 0; + g_cbCtxList[i].processed = false; + } + return; +} + +static void GsUwalInitGlobalVariables() +{ + GsUwalAppendAsyncResetCbCtx(); + pthread_mutex_init(&(g_commonCbCtx.mutex), 0); + pthread_cond_init(&(g_commonCbCtx.cond), 0); + + for (int i = 0; i < UWAL_WORKER_NUM; i++) { + g_cbCtxList[i].index = i; + g_cbCtxList[i].infos = &(g_infoList[i]); + } + return; +} + static X509_CRL *ock_rpc_load_crl_file(const char *file) { BIO *in; @@ -558,6 +595,7 @@ int GsUwalInit(ServerMode serverMode) if (ret != 0) { ereport(LOG, (errmsg("uwal init fail ret code: %d", ret))); } + GsUwalInitGlobalVariables(); return ret; } @@ -595,6 +633,13 @@ void GsUwalNotifyCallback(void *ctx, int ret) int GsUwalSyncNotify(NodeStateList *nodeList) { + ereport(LOG, (errmsg("UwalNotify: nodeNum %d, masterNodeId %d, localNodeId %d", + nodeList->nodeNum, nodeList->masterNodeId, nodeList->localNodeId))); + for (uint16_t i = 0; i < nodeList->nodeNum; i++) { + NodeStateInfo stateInfo = nodeList->nodeList[i]; + ereport(LOG, (errmsg("UwalNotify: nodeId %d, state %d, groupId %d, groupLevel %d", + stateInfo.nodeId, stateInfo.state, stateInfo.groupId, stateInfo.groupLevel))); + } CBParams cbParams = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, false, 0}; pthread_mutex_lock(&cbParams.mutex); int ret = ock_uwal_notify_nodelist_change(nodeList, GsUwalNotifyCallback, (void *)&cbParams); @@ -771,6 +816,8 @@ int GsUwalWalSenderNotify(bool exceptSelf) bool fullSync = true; for (int i = 0; i < count; i++) { unsigned group_index = nodeList->nodeList[i].groupId; + ereport(LOG, (errmsg("SenderNotify: group_index %u, senderGroupLevel %u, senderGroupNumSync %u", + group_index, statSendersGroupLevel[group_index], statSendersGroupNumSync[group_index]))); if (statSendersGroupLevel[group_index] < statSendersGroupNumSync[group_index]) { nodeList->nodeList[i].groupLevel = statSendersGroupLevel[group_index]; fullSync = false; @@ -778,9 +825,10 @@ int GsUwalWalSenderNotify(bool exceptSelf) nodeList->nodeList[i].groupLevel = statSendersGroupNumSync[group_index]; } } - if (!exceptSelf && uwalrcv != NULL) { + // update fullsync to false before notify to avoid truncate + if (exceptSelf && uwalrcv != NULL) { SpinLockAcquire(&uwalrcv->mutex); - uwalrcv->fullSync = fullSync; + uwalrcv->fullSync = false; SpinLockRelease(&uwalrcv->mutex); } @@ -791,6 +839,12 @@ int GsUwalWalSenderNotify(bool exceptSelf) int ret = GsUwalSyncNotify(nodeList); pfree(nodeList); + + if (!exceptSelf && uwalrcv != NULL) { + SpinLockAcquire(&uwalrcv->mutex); + uwalrcv->fullSync = fullSync; + SpinLockRelease(&uwalrcv->mutex); + } return ret; } @@ -869,9 +923,8 @@ int GsUwalStandbyInitNotify() /** * called after uwal append * @param lsn write log success lsn - * @param infos uwalAppend() return UwalNodeInfo */ -void GsUwalUpdateSenderSyncLsn(XLogRecPtr lsn, UwalNodeInfo *infos) +void GsUwalUpdateSenderSyncLsn(XLogRecPtr lsn) { for (int senderIndex = 0; senderIndex < g_instance.attr.attr_storage.max_wal_senders; ++senderIndex) { volatile WalSnd *walSnd = &t_thrd.walsender_cxt.WalSndCtl->walsnds[senderIndex]; @@ -896,6 +949,23 @@ void GsUwalUpdateSenderSyncLsn(XLogRecPtr lsn, UwalNodeInfo *infos) } } +UwalVector *GsUwalGetInitInfo() +{ + UwalInfo *uwalInfos = (UwalInfo *)palloc(sizeof(UwalInfo) * UWAL_MAX_NUM); + UwalUserType user = UWAL_USER_OPENGAUSS; + UwalVector *vec = (UwalVector *)palloc(sizeof(UwalVector)); + vec->uwals = uwalInfos; + int ret = ock_uwal_query_by_user(user, UWAL_ROUTE_LOCAL, vec); + if (ret != 0 || vec->cnt == 0) { + ereport(LOG, (errmsg("Get uwal base info failed, ret: %d, cnt: %lu", ret, vec->cnt))); + pfree(uwalInfos); + pfree(vec); + return nullptr; + } + + return vec; +} + int GsUwalQueryByUser(TimeLineID thisTimeLineID, bool needHistoryList) { int ret; @@ -1009,6 +1079,7 @@ int GsUwalCreate(uint64_t startOffset) t_thrd.xlog_cxt.uwalInfo.info.dataSize = vec->uwals->info.dataSize; t_thrd.xlog_cxt.uwalInfo.info.truncateOffset = vec->uwals->info.truncateOffset; t_thrd.xlog_cxt.uwalInfo.info.writeOffset = vec->uwals->info.writeOffset; + t_thrd.xlog_cxt.uwalFileRenamePtr = vec->uwals->info.truncateOffset; } pfree(uwalInfos); @@ -1016,8 +1087,9 @@ int GsUwalCreate(uint64_t startOffset) return ret; } -int GsUwalWrite(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos) +int GsUwalWriteSync(int nBytes, char *buf, UwalNodeInfo *infos, bool specified, uint64_t targetOffset) { + UwalId *id = &t_thrd.xlog_cxt.uwalInfo.id; UwalBuffer uBuff; UwalBufferList buffList; uint64_t offset; @@ -1032,80 +1104,45 @@ int GsUwalWrite(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos) params.uwalId = id; params.cb = NULL; - int ret = ock_uwal_append(¶ms, &offset, infos); - return ret; -} - -int GsUwalRead(UwalId *id, XLogRecPtr targetPagePtr, char *readBuf, uint64_t readlen) -{ - UwalDataToRead *dataToRead = (UwalDataToRead *)palloc0(sizeof(UwalDataToRead)); - dataToRead->offset = targetPagePtr; - dataToRead->length = readlen; - UwalDataToReadVec *datav = (UwalDataToReadVec *)palloc0(sizeof(UwalDataToReadVec)); - datav->cnt = 1; - datav->dataToRead = dataToRead; - UwalReadParam params = {id, UWAL_ROUTE_LOCAL, datav, NULL}; - - UwalBufferList *bufflist = (UwalBufferList *)palloc0(sizeof(UwalBufferList)); - bufflist->cnt = 1; - UwalBuffer *buffers = (UwalBuffer *)palloc0(sizeof(UwalBuffer)); - buffers->buf = readBuf; - buffers->len = readlen; - bufflist->buffers = buffers; - - int ret = ock_uwal_read(¶ms, bufflist); - - pfree(buffers); - pfree(bufflist); - pfree(dataToRead); - pfree(datav); - return ret; + if (!specified) { + ock_uwal_append(¶ms, &offset, infos); + } + return ock_uwal_append_with_offset(¶ms, targetOffset, &offset, infos); } - void GsUwalWriteAsyncCallBack(void *cbCtx, int retCode) { - UwalSingleAsyncCbCtx *curCbCtx = (UwalSingleAsyncCbCtx *)cbCtx; + UwalAsyncCbCtx *curCbCtx = (UwalAsyncCbCtx *)cbCtx; curCbCtx->ret = retCode; - UwalAsyncAppendCbCtx *commonCbCtx = curCbCtx->commonCbCtx; - pthread_mutex_lock(&(commonCbCtx->mutex)); - if (!commonCbCtx->interrupted) { - // update nodeinfo - if (commonCbCtx->curCount == 0) { - commonCbCtx->ret = curCbCtx->ret; - commonCbCtx->infos->num = curCbCtx->infos->num; - for (uint32_t i = 0; i < curCbCtx->infos->num; i++) { - commonCbCtx->infos->status[i].nodeId = curCbCtx->infos->status[i].nodeId; - commonCbCtx->infos->status[i].ret = curCbCtx->infos->status[i].ret; - } - } else if (commonCbCtx->ret == 0 && curCbCtx->ret != 0) { - commonCbCtx->ret = curCbCtx->ret; - commonCbCtx->infos->num = curCbCtx->infos->num; - for (uint32_t i = 0; i < curCbCtx->infos->num; i++) { - commonCbCtx->infos->status[i].nodeId = curCbCtx->infos->status[i].nodeId; - commonCbCtx->infos->status[i].ret = curCbCtx->infos->status[i].ret; - } - } - commonCbCtx->curCount += 1; - if (commonCbCtx->curCount == commonCbCtx->opCount) { - pthread_cond_signal(&(commonCbCtx->cond)); - pthread_mutex_unlock(&(commonCbCtx->mutex)); + curCbCtx->processed = true; + + pthread_mutex_lock(&(g_commonCbCtx.mutex)); + if (g_commonCbCtx.interrupted) { + g_commonCbCtx.curCount += 1; + if (g_commonCbCtx.curCount == g_commonCbCtx.interruptCount) { + pthread_cond_signal(&(g_commonCbCtx.cond)); + pthread_mutex_unlock(&(g_commonCbCtx.mutex)); } else { - pthread_mutex_unlock(&(commonCbCtx->mutex)); + pthread_mutex_unlock(&(g_commonCbCtx.mutex)); } + return; + } + + if (g_commonCbCtx.curCount == 0 || (g_commonCbCtx.ret == 0 && curCbCtx->ret != 0)) { + g_commonCbCtx.ret = curCbCtx->ret; + } + g_commonCbCtx.curCount += 1; + if (g_commonCbCtx.curCount == g_commonCbCtx.opCount) { + pthread_cond_signal(&(g_commonCbCtx.cond)); + pthread_mutex_unlock(&(g_commonCbCtx.mutex)); } else { - commonCbCtx->curCount += 1; - if (commonCbCtx->curCount == commonCbCtx->interruptCount) { - pthread_cond_signal(&(commonCbCtx->cond)); - pthread_mutex_unlock(&(commonCbCtx->mutex)); - } else { - pthread_mutex_unlock(&(commonCbCtx->mutex)); - } + pthread_mutex_unlock(&(g_commonCbCtx.mutex)); } } -int GsUwalWriteAsync(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos) +int GsUwalWriteAsync(int nBytes, char *buf, uint64_t targetOffset) { + UwalId *id = &t_thrd.xlog_cxt.uwalInfo.id; uint64_t offset; int bufferOffset = 0; int batchIOSize = 0; @@ -1136,59 +1173,143 @@ int GsUwalWriteAsync(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos) } batchLastIOSize = nBytes - (batchIONumber - 1) * batchIOSize; - - UwalAsyncAppendCbCtx cbCtx = {0}; - cbCtx.opCount = batchIONumber; - cbCtx.infos = infos; - pthread_mutex_init(&(cbCtx.mutex), 0); - pthread_cond_init(&(cbCtx.cond), 0); - - UwalNodeInfo uwalInfoList[batchIONumber]; - UwalSingleAsyncCbCtx uwalCbCtxList[batchIONumber]; + GsUwalAppendAsyncResetCbCtx(); + g_commonCbCtx.opCount = batchIONumber; for (int i = 0; i < batchIONumber; i++) { - UwalNodeInfo *uwalInfos = &uwalInfoList[i]; - UwalSingleAsyncCbCtx *uwalCbCtx = &uwalCbCtxList[i]; - UwalBuffer buffers[1] = {{buf + bufferOffset, batchIOSize}}; UwalBufferList bufferList = {1, buffers}; - UwalCallBack uwalCB = {GsUwalWriteAsyncCallBack, uwalCbCtx}; + UwalCallBack uwalCB = {GsUwalWriteAsyncCallBack, &(g_cbCtxList[i])}; UwalAppendParam appendParam = {id, &bufferList, &uwalCB}; + g_cbCtxList[i].writeOffset = targetOffset + bufferOffset; + g_cbCtxList[i].buf = buf + bufferOffset; - uwalCbCtx->commonCbCtx = &cbCtx; - uwalCbCtx->infos = uwalInfos; - uwalCbCtx->ret = 0; - uwalCbCtx->appendParam = &appendParam; if (i == 0) { buffers[0].len = batchLastIOSize; bufferOffset += batchLastIOSize; + g_cbCtxList[i].writeLen = batchLastIOSize; } else { bufferOffset += batchIOSize; + g_cbCtxList[i].writeLen = batchIOSize; } - ret = ock_uwal_append(&appendParam, &offset, (void *)uwalInfos); - if (ret != 0) { - pthread_mutex_lock(&(cbCtx.mutex)); - cbCtx.interrupted = true; - cbCtx.interruptCount = i; - while (cbCtx.interruptCount < cbCtx.curCount) { - pthread_cond_wait(&(cbCtx.cond), &(cbCtx.mutex)); - } - pthread_mutex_unlock(&(cbCtx.mutex)); - pthread_mutex_destroy(&(cbCtx.mutex)); - pthread_cond_destroy(&(cbCtx.cond)); + ret = ock_uwal_append(&appendParam, &offset, (void *)(g_cbCtxList[i].infos)); + if (ret == 0) { + continue; + } + // send request failed, need break + g_cbCtxList[i].ret = ret; + g_cbCtxList[i].processed = true; + pthread_mutex_lock(&(g_commonCbCtx.mutex)); + g_commonCbCtx.interrupted = true; + g_commonCbCtx.interruptCount = i; + while (g_commonCbCtx.interruptCount < g_commonCbCtx.curCount) { + pthread_cond_wait(&(g_commonCbCtx.cond), &(g_commonCbCtx.mutex)); + } + pthread_mutex_unlock(&(g_commonCbCtx.mutex)); + for (i = i + 1; i < batchIONumber; i++) { + g_cbCtxList[i].writeOffset = targetOffset + bufferOffset; + g_cbCtxList[i].buf = buf + bufferOffset; + g_cbCtxList[i].writeLen = batchIOSize; + bufferOffset += batchIOSize; + } + return ret; + } + pthread_mutex_lock(&(g_commonCbCtx.mutex)); + while (g_commonCbCtx.curCount < g_commonCbCtx.opCount) { + pthread_cond_wait(&(g_commonCbCtx.cond), &(g_commonCbCtx.mutex)); + } + pthread_mutex_unlock(&(g_commonCbCtx.mutex)); + + ret = g_commonCbCtx.ret; + return ret; +} + +int GsUwalWriteResHandle(int ret, int nBytes, char *buf, UwalNodeInfo *infos, uint64_t targetOffset) +{ + if (ret == 0 || (ret != REPLICA_APPEND_LOG_FAIL && ret != U_CAPACITY_NOT_ENOUGH)) { + return ret; + } + + while (ret == U_CAPACITY_NOT_ENOUGH) { + usleep(UWAL_RETRY_INTERVAL_US); + ret = GsUwalWriteSync(nBytes, buf, infos); + } + + if (ret == REPLICA_APPEND_LOG_FAIL) { + if (!GsUwalCheckLocalRes(infos)) { + ereport(WARNING, (errmsg("Uwal write remote and local failed"))); return ret; } + ereport(WARNING, (errmsg("Uwal write remote failed, try to rewrite"))); + do { + ret = GsUwalWriteSync(nBytes, buf, infos, true, targetOffset); + } while (ret == REPLICA_APPEND_LOG_FAIL); + } + + return GsUwalWriteResHandle(ret, nBytes, buf, infos, targetOffset); +} + +int GsUwalWrite(int nBytes, char *buf, uint64_t writeOffset) +{ + int ret = 0; + + if (!g_instance.attr.attr_storage.uwal_async_append_switch) { + // sync append + ret = GsUwalWriteSync(nBytes, buf, &(g_infoList[0])); + return GsUwalWriteResHandle(ret, nBytes, buf, &(g_infoList[0]), writeOffset); } - pthread_mutex_lock(&(cbCtx.mutex)); - while (cbCtx.curCount < cbCtx.opCount) { - pthread_cond_wait(&(cbCtx.cond), &(cbCtx.mutex)); + + ret = GsUwalWriteAsync(nBytes, buf, writeOffset); + if (ret == 0 || (ret != REPLICA_APPEND_LOG_FAIL && ret != U_CAPACITY_NOT_ENOUGH)) { + return ret; } - pthread_mutex_unlock(&(cbCtx.mutex)); - pthread_mutex_destroy(&(cbCtx.mutex)); - pthread_cond_destroy(&(cbCtx.cond)); - ret = cbCtx.ret; + for (int i = 0; i < g_commonCbCtx.opCount; i++) { + if (g_cbCtxList[i].processed) { + ret = GsUwalWriteResHandle(g_cbCtxList[i].ret, g_cbCtxList[i].writeLen, + g_cbCtxList[i].buf, g_cbCtxList[i].infos, g_cbCtxList[i].writeOffset); + if (ret != 0) { + return ret; + } + } else { + ret = GsUwalWriteSync(g_cbCtxList[i].writeLen, g_cbCtxList[i].buf, g_cbCtxList[i].infos); + if (ret == 0) { + continue; + } + ret = GsUwalWriteResHandle(ret, g_cbCtxList[i].writeLen, g_cbCtxList[i].buf, + g_cbCtxList[i].infos, g_cbCtxList[i].writeOffset); + if (ret != 0) { + return ret; + } + } + } + return ret; +} + +int GsUwalRead(UwalId *id, XLogRecPtr targetPagePtr, char *readBuf, uint64_t readlen) +{ + UwalDataToRead *dataToRead = (UwalDataToRead *)palloc0(sizeof(UwalDataToRead)); + dataToRead->offset = targetPagePtr; + dataToRead->length = readlen; + UwalDataToReadVec *datav = (UwalDataToReadVec *)palloc0(sizeof(UwalDataToReadVec)); + datav->cnt = 1; + datav->dataToRead = dataToRead; + UwalReadParam params = {id, UWAL_ROUTE_LOCAL, datav, NULL}; + + UwalBufferList *bufflist = (UwalBufferList *)palloc0(sizeof(UwalBufferList)); + bufflist->cnt = 1; + UwalBuffer *buffers = (UwalBuffer *)palloc0(sizeof(UwalBuffer)); + buffers->buf = readBuf; + buffers->len = readlen; + bufflist->buffers = buffers; + + int ret = ock_uwal_read(¶ms, bufflist); + + pfree(buffers); + pfree(bufflist); + pfree(dataToRead); + pfree(datav); return ret; } @@ -1213,9 +1334,9 @@ UwalrcvWriterState *GsGetCurrentUwalRcvState(void) if (walrcv == NULL) { return NULL; } - SpinLockAcquire(&walrcv->mutex); + SpinLockAcquire(&walrcv->uwalMutex); uwalrcv = walrcv->uwalRcvState; - SpinLockRelease(&walrcv->mutex); + SpinLockRelease(&walrcv->uwalMutex); return uwalrcv; } @@ -1239,4 +1360,91 @@ int GsUwalTruncate(UwalId *id, uint64_t offset) ereport(WARNING, (errmsg("GsUwalTruncate return failed ret: %d",ret))); } return ret; +} + +int GsUwalRewind(UwalId *id, uint64_t offset) +{ + int ret = ock_uwal_set_rewind_point(id, offset); + if (ret != 0) { + ereport(WARNING, (errmsg("GsUwalRewind return failed, ret: %d", ret))); + } + ereport(LOG, (errmsg("UwalRewin: Offset %llu", offset))); + return ret; +} + +void GsUwalRenewFileRenamePtr() +{ + XLogRecPtr startWritePtr = t_thrd.xlog_cxt.uwalInfo.info.startWriteOffset; + XLogRecPtr truncatePtr = t_thrd.xlog_cxt.uwalInfo.info.truncateOffset; + TimeLineID tli = t_thrd.xlog_cxt.uwalInfo.info.startTimeLine; + if (truncatePtr / XLogSegSize <= startWritePtr / XLogSegSize + 1) { + t_thrd.xlog_cxt.uwalFileRenamePtr = truncatePtr; + return; + } + + XLogSegNo renamedLSN = truncatePtr / XLogSegSize - 1; + while (renamedLSN > startWritePtr / XLogSegSize) { + char filename[MAXFNAMELEN]; + errno_t errorno = snprintf_s(filename, MAXFNAMELEN, MAXFNAMELEN - 1, "%08X%08X%08X", + tli, (uint32)(renamedLSN / XLogSegmentsPerXLogId), (uint32)(renamedLSN % XLogSegmentsPerXLogId)); + securec_check_ss(errorno, "", ""); + + char path[MAXPGPATH]; + errorno = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", + g_instance.attr.attr_storage.uwal_devices_path, filename); + securec_check_ss(errorno, "", ""); + // If the file exists, move the offset backwards. + if (access(path, F_OK) == 0) { + ereport(WARNING, (errmsg("Truncate file is still in uwal path, lsn %llu", renamedLSN))); + renamedLSN -= 1; + continue; + } + break; + } + t_thrd.xlog_cxt.uwalFileRenamePtr = (renamedLSN + 1) * XLogSegSize; +} + +// Check whether the truncated file is renamed +bool GsUwalCheckFileRename(XLogRecPtr targetPtr) +{ + if (targetPtr < t_thrd.xlog_cxt.uwalFileRenamePtr) { + return true; + } + + XLogRecPtr truncatePtr = t_thrd.xlog_cxt.uwalInfo.info.truncateOffset; + if (targetPtr >= truncatePtr) { + ereport(PANIC, (errmsg("Try to read xlog file which is not truncated by uwal, readPtr %llu, truncatePtr %llu", + targetPtr, truncatePtr))); + } + + GsUwalRenewFileRenamePtr(); + int retryCount = 100; + while (targetPtr >= t_thrd.xlog_cxt.uwalFileRenamePtr && retryCount-- > 0) { + GsUwalRenewFileRenamePtr(); + pg_usleep(UWAL_RETRY_INTERVAL_US); + } + if (targetPtr < t_thrd.xlog_cxt.uwalFileRenamePtr) { + return true; + } + return false; +} + +// Check whether Data is successfully written to the local node +bool GsUwalCheckLocalRes(UwalNodeInfo *infos) +{ + if (infos == nullptr || infos->num == 0) { + return false; + } + uint32_t localUwalId = g_uwalConfig.id; + for (uint32_t i = 0; i < infos->num; i++) { + if (infos->status[i].nodeId != localUwalId) { + continue; + } + if (infos->status[i].ret == U_OK) { + return true; + } + ereport(WARNING, (errmsg("Uwal write local node failed: %d", infos->status[i].ret))); + return false; + } + return false; } \ No newline at end of file diff --git a/src/gausskernel/storage/gs_uwal/gs_uwal_adaptor.cpp b/src/gausskernel/storage/gs_uwal/gs_uwal_adaptor.cpp index 73d9e0c626d885f7b012c7ed0dd485148301454b..e0c5f72a4d523c47f6cd68945da4bc2a6e9459f3 100644 --- a/src/gausskernel/storage/gs_uwal/gs_uwal_adaptor.cpp +++ b/src/gausskernel/storage/gs_uwal/gs_uwal_adaptor.cpp @@ -43,6 +43,7 @@ typedef struct { UwalCreate create; UwalDelete remove; UwalAppend uappend; + UwalAppendWithOffset uappend_with_offset; UwalRead uread; UwalTruncate truncate; UwalQuery query; @@ -61,6 +62,7 @@ uwal_func_t g_uwal_func; ACTION(create, UwalCreate) \ ACTION(remove, UwalDelete) \ ACTION(uappend, UwalAppend) \ + ACTION(uappend_with_offset, UwalAppendWithOffset) \ ACTION(uread, UwalRead) \ ACTION(truncate, UwalTruncate) \ ACTION(query, UwalQuery) \ @@ -161,6 +163,12 @@ int ock_uwal_append(IN UwalAppendParam *param, OUT uint64_t *offset, OUT void* r return g_uwal_func.uappend(param, offset, result); } +int ock_uwal_append_with_offset(IN UwalAppendParam *param, IN uint64_t targetOffset, + OUT uint64_t *offset, OUT void* result) +{ + return g_uwal_func.uappend_with_offset(param, targetOffset, offset, result); +} + int ock_uwal_read(IN UwalReadParam *param, OUT UwalBufferList *bufferList) { return g_uwal_func.uread(param, bufferList); diff --git a/src/gausskernel/storage/ipc/ipci.cpp b/src/gausskernel/storage/ipc/ipci.cpp index dd2c68ecef940a64e1674470405949ccc16f2b95..4f666f4a6da207060dfaad293b43bcdcd93d3d38 100644 --- a/src/gausskernel/storage/ipc/ipci.cpp +++ b/src/gausskernel/storage/ipc/ipci.cpp @@ -89,9 +89,6 @@ #include "executor/node/nodeShareInputScan.h" #endif -/* we use semaphore not LWLOCK, because when thread InitGucConfig, it does not get a t_thrd.proc */ -pthread_mutex_t gLocaleMutex = PTHREAD_MUTEX_INITIALIZER; - extern void SetShmemCxt(void); #ifdef ENABLE_MULTIPLE_NODES extern void InitDisasterCache(); diff --git a/src/gausskernel/storage/lmgr/lmgr.cpp b/src/gausskernel/storage/lmgr/lmgr.cpp index 00570fb5abd3e9d027d93a412c511ce6a8d332d6..9b9a6a003dc07a67d4b37cc5026cc4fe0e4f7e23 100755 --- a/src/gausskernel/storage/lmgr/lmgr.cpp +++ b/src/gausskernel/storage/lmgr/lmgr.cpp @@ -330,6 +330,84 @@ void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode) (void)LockRelease(&tag, lockmode, true); } +/* + * Unlock and Lock Package/Procedure Id For Session + */ +void LockProcedureIdForSession(Oid procId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PROC_OBJECT(tag, dbId, procId); + + (void)LockAcquire(&tag, lockmode, true, false); +} + +void UnlockProcedureIdForSession(Oid procId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PROC_OBJECT(tag, dbId, procId); + + (void)LockRelease(&tag, lockmode, true); +} + +void LockPackageIdForSession(Oid packageId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PKG_OBJECT(tag, dbId, packageId); + + (void)LockAcquire(&tag, lockmode, true, false); +} + +void UnlockPackageIdForSession(Oid packageId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PKG_OBJECT(tag, dbId, packageId); + + (void)LockRelease(&tag, lockmode, true); +} + +/* + * Unlock and Lock Package/Procedure Id For Transaction + */ +void LockProcedureIdForXact(Oid procId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PROC_OBJECT(tag, dbId, procId); + + (void)LockAcquire(&tag, lockmode, false, false); +} + +void UnlockProcedureIdForXact(Oid procId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PROC_OBJECT(tag, dbId, procId); + + (void)LockRelease(&tag, lockmode, false); +} + +void LockPackageIdForXact(Oid packageId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PKG_OBJECT(tag, dbId, packageId); + + (void)LockAcquire(&tag, lockmode, false, false); +} + +void UnlockPackageIdForXact(Oid packageId, Oid dbId, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_PKG_OBJECT(tag, dbId, packageId); + + (void)LockRelease(&tag, lockmode, false); +} + /* * LockRelationForExtension * diff --git a/src/gausskernel/storage/replication/libpqsw.cpp b/src/gausskernel/storage/replication/libpqsw.cpp index 1373ebbb8331295ee9b8cdff137aa06deeb44cf2..ae4bbf7c97ca55afd289d7f4443c2c704e57c62c 100644 --- a/src/gausskernel/storage/replication/libpqsw.cpp +++ b/src/gausskernel/storage/replication/libpqsw.cpp @@ -30,6 +30,9 @@ #include "tcop/tcopprot.h" #include "utils/snapmgr.h" #include "ddes/dms/ss_transaction.h" +#include "knl/knl_thread.h" +#include "storage/lz4_file.h" +#include "libpq/libpq.h" #ifdef HAVE_NETINET_TCP_H #include @@ -46,6 +49,14 @@ #include #endif +typedef struct TempFileContextInfo { + LZ4File* file_handle; + TempFileState file_state; + size_t file_size; + uint32 seq_count; /* count number of PqRecvBuffers */ + StringInfoData crc_buffer; /* store stringinfo with crc header */ +} TempFileContextInfo; + struct pg_conn; typedef int (*libpqsw_transfer_standby_func)(const char* s, size_t len); /* @@ -68,6 +79,61 @@ bool libpqsw_savepoint_command(const char* commandTag); static void libpqsw_check_savepoint(List *query_list, bool *have_savepoint); static bool libpqsw_need_localexec_forSimpleQuery(const char *commandTag, List *query_list, PhaseType ptype); +static inline void pq_disk_create_tempfile(void) +{ + MemoryContext oldcontext; + oldcontext = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_COMMUNICATION)); + + t_thrd.libpq_cxt.PqTempFileContextInfo->file_handle = LZ4FileCreate(true); + t_thrd.libpq_cxt.PqTempFileContextInfo->file_state = TEMPFILE_CREATED; + t_thrd.libpq_cxt.PqTempFileContextInfo->file_size = 0; + t_thrd.libpq_cxt.PqTempFileContextInfo->seq_count = 0; + + initStringInfo(&(t_thrd.libpq_cxt.PqTempFileContextInfo->crc_buffer)); + + (void)MemoryContextSwitchTo(oldcontext); +} + +int internal_putbytes(const char* s, size_t len) +{ + size_t amount; + + while (len > 0) { + /* If buffer is full, then flush it out */ + if (t_thrd.libpq_cxt.PqSendPointer >= t_thrd.libpq_cxt.PqSendBufferSize) { + if (pq_disk_is_temp_file_enabled()) { + /* create temp file to store the result, it is caller's responsibility + * to close the file done */ + if (!t_thrd.libpq_cxt.PqTempFileContextInfo->file_handle) { + pq_disk_create_tempfile(); + } + if ((int)pq_disk_write_tempfile( + t_thrd.libpq_cxt.PqSendBuffer, ((size_t)t_thrd.libpq_cxt.PqSendPointer)) == EOF) { + return EOF; + } + t_thrd.libpq_cxt.PqSendPointer = 0; + } else { + StmtRetrySetFileExceededFlag(); /* once flush data to frontend, can not retry this query anymore */ + pq_set_nonblocking(false); + if (internal_flush()) { + return EOF; + } + } + } + amount = t_thrd.libpq_cxt.PqSendBufferSize - t_thrd.libpq_cxt.PqSendPointer; + if (amount > len) { + amount = len; + } + errno_t rc = memcpy_s(t_thrd.libpq_cxt.PqSendBuffer + t_thrd.libpq_cxt.PqSendPointer, amount, s, amount); + securec_check(rc, "\0", "\0"); + t_thrd.libpq_cxt.PqSendPointer += amount; + s += amount; + len -= amount; + } + + return 0; +} + static void libpqsw_set_already_connected() { get_redirect_manager()->state.already_connected = true; diff --git a/src/gausskernel/storage/replication/logical/snapbuild.cpp b/src/gausskernel/storage/replication/logical/snapbuild.cpp index 2efcda0676cb39fa68f7f6e38ebd1a306cb6695b..25cf5c0e8141f4af9fa54c820ee24a2ad4b56fac 100644 --- a/src/gausskernel/storage/replication/logical/snapbuild.cpp +++ b/src/gausskernel/storage/replication/logical/snapbuild.cpp @@ -1533,6 +1533,9 @@ static void SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) out: ReorderBufferSetRestartPoint(builder->reorder, builder->last_serialized_snapshot); + + if (ondisk) + pfree(ondisk); } static void CheckDiskFile(SnapBuildOnDisk* ondisk, char* path, size_t pathLen) diff --git a/src/gausskernel/storage/replication/logical/tablesync.cpp b/src/gausskernel/storage/replication/logical/tablesync.cpp index 5ea58c2e3a9a9ee852b7c658fdc85d465654f639..388be962913894fbb798b808eb72fbeed32b40b9 100644 --- a/src/gausskernel/storage/replication/logical/tablesync.cpp +++ b/src/gausskernel/storage/replication/logical/tablesync.cpp @@ -660,8 +660,9 @@ static void fetch_remote_table_info(char *nspname, char *relname, LogicalRepRela initStringInfo(&cmd); appendStringInfo(&cmd, "SELECT c.oid, c.relreplident" - " FROM pg_catalog.pg_class c," - " pg_catalog.pg_namespace n" + " FROM pg_catalog.pg_class c" + " INNER JOIN pg_catalog.pg_namespace n" + " ON (c.relnamespace = n.oid)" " WHERE n.nspname = %s" " AND c.relname = %s" " AND c.relkind = 'r'", diff --git a/src/gausskernel/storage/replication/walrcvwriter.cpp b/src/gausskernel/storage/replication/walrcvwriter.cpp index 3d54c80fdcd03de26874057a6489f752434e97ef..08ad4bef286317b459e2a9b30e50660e178c3d9a 100755 --- a/src/gausskernel/storage/replication/walrcvwriter.cpp +++ b/src/gausskernel/storage/replication/walrcvwriter.cpp @@ -79,8 +79,10 @@ static void uwalRcvStateFree(); static void XLogWalRcvWriteFromUwal(WalRcvCtlBlock *walrcb, char *buf, Size nbytes, XLogRecPtr recptr, TimeLineID tli); static int RenameUwalFile(XLogRecPtr recptr, TimeLineID tli); static int RemoveUwalFile(XLogRecPtr recptr, TimeLineID tli); -static int walRcvUwalTruncate(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrcv, UwalInfo *info); -static void RemoveFromUwal(UwalrcvWriterState *uwalrcv); +static int WalRcvUwalTruncate(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrcv, UwalInfo *info); +static void RemoveFromUwal(UwalrcvWriterState *uwalrcv, bool needUpdate); +static void UpdateUwalRcv(UwalrcvWriterState *uwalrcv, UwalInfo *info); +static void RemoveRestFileFromUwal(UwalrcvWriterState *uwalrcv); extern void XlogArchUwal(XLogRecPtr archRqstPtr); void SetWalRcvWriterPID(ThreadId tid) @@ -1019,7 +1021,7 @@ int walRcvWriteUwal(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrcv, UwalInf uwalFreeOffset = recBufferSize - uwalReadOffset; nbytes = Min(MaxReadUwalBytes, Min(uwalFreeOffset, readLen)); if (startPtr / XLogSegSize != t_thrd.xlog_cxt.uwalInfo.info.startWriteOffset / XLogSegSize) { - if (startPtr / XLogSegSize != writePtr / XLogSegSize) { + if (startPtr / XLogSegSize < writePtr / XLogSegSize) { startPtr = (startPtr / XLogSegSize + 1) * XLogSegSize; SpinLockAcquire(&uwalrcv->mutex); uwalrcv->startPtr = startPtr; @@ -1082,13 +1084,17 @@ int walRcvWriteUwal(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrcv, UwalInf int defWalRcvWriteUwal(WalRcvCtlBlock *walrcb) { + UwalrcvWriterState *uwalrcv = GsGetCurrentUwalRcvState(); if (t_thrd.walrcvwriter_cxt.shutdownRequested) { + if (t_thrd.xlog_cxt.uwalInfo.info.dataSize != 0) { + ereport(WARNING, (errmsg("walrcvwriter in shutdown requested, move the rest uwal file"))); + RemoveFromUwal(uwalrcv, true); + } return 0; } int ret = 0; bool needXlogCatchup = false; bool fullSync = true; - UwalrcvWriterState *uwalrcv = GsGetCurrentUwalRcvState(); XLogRecPtr startPtr = InvalidXLogRecPtr; if (t_thrd.xlog_cxt.uwalInfo.info.dataSize == 0) { @@ -1100,6 +1106,7 @@ int defWalRcvWriteUwal(WalRcvCtlBlock *walrcb) if (t_thrd.xlog_cxt.uwalInfo.info.dataSize > 0) { ereport(LOG, (errmsg("walrcvwriter find uwal datasize : %lu", t_thrd.xlog_cxt.uwalInfo.info.dataSize))); uwalRcvStateInit(uwalrcv, t_thrd.xlog_cxt.uwalInfo); + RemoveFromUwal(uwalrcv, false); } else { ereport(LOG, (errmsg("walrcvwriter no uwal detected"))); return 0; @@ -1138,16 +1145,16 @@ int defWalRcvWriteUwal(WalRcvCtlBlock *walrcb) ret = walRcvWriteUwal(walrcb, uwalrcv, &t_thrd.xlog_cxt.uwalInfo); if (t_thrd.postmaster_cxt.HaShmData->current_mode == NORMAL_MODE) { - walRcvUwalTruncate(walrcb, uwalrcv, &t_thrd.xlog_cxt.uwalInfo); - RemoveFromUwal(uwalrcv); + WalRcvUwalTruncate(walrcb, uwalrcv, &t_thrd.xlog_cxt.uwalInfo); + RemoveFromUwal(uwalrcv, false); } else { SpinLockAcquire(&uwalrcv->mutex); fullSync = uwalrcv->fullSync; SpinLockRelease(&uwalrcv->mutex); if (fullSync) { - walRcvUwalTruncate(walrcb, uwalrcv, &t_thrd.xlog_cxt.uwalInfo); - RemoveFromUwal(uwalrcv); + WalRcvUwalTruncate(walrcb, uwalrcv, &t_thrd.xlog_cxt.uwalInfo); } + RemoveFromUwal(uwalrcv, !fullSync); } return ret; } @@ -1162,13 +1169,14 @@ int uwalRcvStateInit(UwalrcvWriterState *uwalrcv, UwalInfo info) uwalrcv->readPtr = info.info.truncateOffset; uwalrcv->renamePtr = info.info.truncateOffset; uwalrcv->needQuery = false; - uwalrcv->fullSync = false; uwalrcv->needXlogCatchup = true; SpinLockRelease(&uwalrcv->mutex); SpinLockAcquire(&uwalrcv->writeMutex); uwalrcv->writePtr = info.info.writeOffset; SpinLockRelease(&uwalrcv->writeMutex); + ereport(LOG, (errmsg("uwalRcvStateInit: truncate %llu, write %llu", + info.info.truncateOffset, info.info.writeOffset))); return 0; } @@ -1187,18 +1195,25 @@ static void uwalRcvStateAlloc() rc = memset_s(buf, sizeof(UwalrcvWriterState), 0, sizeof(UwalrcvWriterState)); securec_check_c(rc, "\0", "\0"); + UwalrcvWriterState *state = (UwalrcvWriterState *)buf; + SpinLockInit(&state->mutex); + SpinLockInit(&state->writeMutex); - t_thrd.walreceiverfuncs_cxt.WalRcv->uwalRcvState = (UwalrcvWriterState *)buf; - SpinLockInit(&t_thrd.walreceiverfuncs_cxt.WalRcv->uwalRcvState->mutex); - SpinLockInit(&t_thrd.walreceiverfuncs_cxt.WalRcv->uwalRcvState->writeMutex); + volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; + SpinLockAcquire(&walrcv->uwalMutex); + walrcv->uwalRcvState = state; + SpinLockRelease(&walrcv->uwalMutex); } static void uwalRcvStateFree() { - if (t_thrd.walreceiverfuncs_cxt.WalRcv->uwalRcvState != NULL) { - pfree(t_thrd.walreceiverfuncs_cxt.WalRcv->uwalRcvState); - t_thrd.walreceiverfuncs_cxt.WalRcv->uwalRcvState = NULL; + volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; + SpinLockAcquire(&walrcv->uwalMutex); + if (walrcv->uwalRcvState != NULL) { + pfree(walrcv->uwalRcvState = NULL); + walrcv->uwalRcvState = NULL; } + SpinLockRelease(&walrcv->uwalMutex); } static void XLogWalRcvWriteFromUwal(WalRcvCtlBlock *walrcb, char *buf, Size nbytes, XLogRecPtr recptr, TimeLineID tli) @@ -1347,7 +1362,7 @@ static int RemoveUwalFile(XLogRecPtr recptr, TimeLineID tli) return 0; } -static int walRcvUwalTruncate(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrcv, UwalInfo *info) +static int WalRcvUwalTruncate(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrcv, UwalInfo *info) { XLogRecPtr flushPtr = InvalidXLogRecPtr; XLogRecPtr truncatePtr = InvalidXLogRecPtr; @@ -1378,15 +1393,18 @@ static int walRcvUwalTruncate(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrc ereport(WARNING, (errmsg("GsUwalQuery return failed"))); return ret; } - - if (info->info.truncateOffset == expectTruncate) { + if (truncatePtr != info->info.truncateOffset) { SpinLockAcquire(&uwalrcv->mutex); - uwalrcv->needQuery = false; uwalrcv->truncatePtr = info->info.truncateOffset; SpinLockRelease(&uwalrcv->mutex); truncatePtr = info->info.truncateOffset; - needQuery = false; - break; + if (info->info.truncateOffset == expectTruncate) { + SpinLockAcquire(&uwalrcv->mutex); + uwalrcv->needQuery = false; + SpinLockRelease(&uwalrcv->mutex); + needQuery = false; + break; + } } pg_usleep(100000); } @@ -1399,13 +1417,13 @@ static int walRcvUwalTruncate(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrc fullSync = uwalrcv->fullSync; SpinLockRelease(&uwalrcv->mutex); if(!fullSync) { - ereport(LOG, (errmsg("walRcvUwalTruncate truncate not in fullSync"))); + ereport(LOG, (errmsg("WalRcvUwalTruncate truncate not in fullSync"))); return 0; } START_CRIT_SECTION(); ret = GsUwalTruncate(&(info->id), startPtr); if (0 != ret) { - ereport(LOG, (errmsg("walRcvUwalTruncate failed retCode: %d", ret))); + ereport(LOG, (errmsg("WalRcvUwalTruncate failed retCode: %d", ret))); END_CRIT_SECTION(); return -1; } @@ -1432,8 +1450,11 @@ static int walRcvUwalTruncate(WalRcvCtlBlock *walrcb, UwalrcvWriterState *uwalrc return 0; } -static void RemoveFromUwal(UwalrcvWriterState *uwalrcv) +static void RemoveFromUwal(UwalrcvWriterState *uwalrcv, bool needUpdate) { + if (needUpdate) { + UpdateUwalRcv(uwalrcv, &t_thrd.xlog_cxt.uwalInfo); + } XLogRecPtr truncatePtr = InvalidXLogRecPtr; XLogRecPtr renamePtr = InvalidXLogRecPtr; TimeLineID tli; @@ -1467,3 +1488,101 @@ static void RemoveFromUwal(UwalrcvWriterState *uwalrcv) SpinLockRelease(&uwalrcv->mutex); return; } + +static void UpdateUwalRcv(UwalrcvWriterState *uwalrcv, UwalInfo *info) +{ + XLogRecPtr truncatePtr = InvalidXLogRecPtr; + SpinLockAcquire(&uwalrcv->mutex); + truncatePtr = uwalrcv->truncatePtr; + SpinLockRelease(&uwalrcv->mutex); + + int ret = GsUwalQuery(&info->id, &(info->info)); + if (ret != 0) { + ereport(WARNING, (errmsg("GsUwalQuery return failed")));; + return; + } + + if (truncatePtr != info->info.truncateOffset) { + SpinLockAcquire(&uwalrcv->mutex); + uwalrcv->truncatePtr = info->info.truncateOffset; + SpinLockRelease(&uwalrcv->mutex); + } +} + +static int MoveNotManagedUwalFile(XLogRecPtr truncatePtr, XLogRecPtr startPtr, TimeLineID tli) +{ + DIR* uwaldir = nullptr; + struct dirent* uwalde = nullptr; + uint32_t xlogFileNameLen = 24; + if ((uwaldir = opendir(UWAL_XLOGDIR)) != nullptr) { + while ((uwalde = readdir(uwaldir)) != nullptr) { + if (!(strlen(uwalde->d_name) == xlogFileNameLen && + strspn(uwalde->d_name, "0123456789ABCDEF") == xlogFileNameLen)) { + continue; + } + TimeLineID xlogTli; + XLogSegNo xlogSegNo; + XLogFromFileName(uwalde->d_name, &xlogTli, &xlogSegNo); + if (tli != xlogTli) { + continue; + } + XLogRecPtr xlogPtr; + XLogSegNoOffsetToRecPtr(xlogSegNo, 0, xlogPtr); + if (xlogPtr / XLogSegSize >= truncatePtr / XLogSegSize || xlogPtr / XLogSegSize <= startPtr / XLogSegSize) { + continue; + } + char path[MAXPGPATH]; + char newpath[MAXPGPATH]; + errno_t errorno = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", UWAL_XLOGDIR, uwalde->d_name); + securec_check_ss(errorno, "", ""); + + errorno = snprintf_s(newpath, MAXPGPATH, MAXPGPATH - 1, "%s/%s", SS_XLOGDIR, uwalde->d_name); + securec_check_ss(errorno, "", ""); + + if (rename(path, newpath) != 0) { + ereport(LOG, (errcode_for_file_access(), + errmsg("Failed to rename old transaction log file \"%s\". The file may have been moved", path))); + } else { + ereport(LOG, (errmsg("MoveNotManagedUwalFile: moved uwal file %s", uwalde->d_name))); + } + } + (void)closedir(uwaldir); + } + return 0; +} + +static void RemoveRestFileFromUwal(UwalrcvWriterState *uwalrcv) +{ + XLogRecPtr truncatePtr = InvalidXLogRecPtr; + XLogRecPtr startPtr = t_thrd.xlog_cxt.uwalInfo.info.startWriteOffset; + TimeLineID tli; + SpinLockAcquire(&uwalrcv->mutex); + truncatePtr = uwalrcv->truncatePtr; + tli = uwalrcv->startTimeLine; + SpinLockRelease(&uwalrcv->mutex); + MoveNotManagedUwalFile(truncatePtr, startPtr, tli); + return; +} + +// Move all files not managed by uwal +void MoveUwalFile(void) +{ + UwalVector *vec = GsUwalGetInitInfo(); + if (vec == nullptr) { + return; + } + + for (uint32_t i = 0; i < vec->cnt; i++) { + XLogRecPtr truncatePtr = vec->uwals[i].info.truncateOffset; + XLogRecPtr startPtr = vec->uwals[i].info.startWriteOffset; + TimeLineID timeLine = vec->uwals[i].info.startTimeLine; + if (MoveNotManagedUwalFile(truncatePtr, startPtr, timeLine) != 0) { + break; + } + } + pfree(vec->uwals); + vec->uwals = nullptr; + pfree(vec); + vec = nullptr; + return; +} diff --git a/src/gausskernel/storage/replication/walreceiver.cpp b/src/gausskernel/storage/replication/walreceiver.cpp index e87c06e85e75f7e65b8bd37e10a583895ba46d91..e82b1cba67ffede3f0f73f1f22bdc1cfa7473291 100755 --- a/src/gausskernel/storage/replication/walreceiver.cpp +++ b/src/gausskernel/storage/replication/walreceiver.cpp @@ -936,6 +936,16 @@ static void WalRcvDie(int code, Datum arg) pg_atomic_write_u32(&t_thrd.walreceiverfuncs_cxt.WalRcv->rcvDoneFromShareStorage, true); } } + + if (g_instance.attr.attr_storage.enable_uwal) { + ereport(WARNING, (errmsg("walreceiver has been shutdown, start notify changed"))); + if (GsUwalWalReceiverNotify(false) != 0) { + ereport(FATAL, (errmsg("uwal standby notify for WalRcvDie() failed."))); + } + SpinLockAcquire(&walrcv->mutex); + walrcv->flagAlreadyNotifyCatchup = false; + SpinLockRelease(&walrcv->mutex); + } /* * Shutdown WalRcvWriter thread, clear the data receive buffer. * Ensure that all WAL records received are flushed to disk. @@ -989,15 +999,6 @@ static void WalRcvDie(int code, Datum arg) 0, sizeof(walrcv->conn_channel)); securec_check_c(rc, "\0", "\0"); - if (g_instance.attr.attr_storage.enable_uwal) { - ereport(LOG, (errmsg("walreceiver has been shut down, start notify changed"))); - if (GsUwalWalReceiverNotify(false) != 0) { - ereport(FATAL, (errmsg("uwal standby notify for WalRcvDie() failed."))); - } - SpinLockAcquire(&walrcv->mutex); - walrcv->flagAlreadyNotifyCatchup = false; - SpinLockRelease(&walrcv->mutex); - } ereport(LOG, (errmsg("walreceiver thread shut down"))); } @@ -1880,7 +1881,7 @@ static void ProcessKeepaliveMessage(PrimaryKeepaliveMessage *keepalive) bool uwal_update_lsn = (g_instance.attr.attr_storage.enable_uwal && walrcv->sender_sent_location < keepalive->walEnd && walrcv->flagAlreadyNotifyCatchup); if (uwal_update_lsn) { - lastReceived = walrcv->receivedUpto; + lastReceived = walrcv->receivedUpto; walrcv->sender_write_location = keepalive->walEnd; walrcv->sender_flush_location = keepalive->walEnd; walrcv->sender_replay_location = keepalive->walEnd; @@ -1901,7 +1902,9 @@ static void ProcessKeepaliveMessage(PrimaryKeepaliveMessage *keepalive) } if (g_instance.attr.attr_storage.enable_uwal && keepalive->uwal_catchup && !walrcv->flagAlreadyNotifyCatchup) { + SpinLockAcquire(&walrcv->mutex); walrcv->flagAlreadyNotifyCatchup = true; + SpinLockRelease(&walrcv->mutex); if (GsUwalWalReceiverNotify() != 0) { ereport(FATAL, (errmsg("uwal standby notify failed."))); proc_exit(1); diff --git a/src/gausskernel/storage/replication/walreceiverfuncs.cpp b/src/gausskernel/storage/replication/walreceiverfuncs.cpp index d0f234b83b9a6c2b96d440a736cec61d938ba386..3d3e19b06d6a8539f232b6ad69011d3fe99c36d9 100755 --- a/src/gausskernel/storage/replication/walreceiverfuncs.cpp +++ b/src/gausskernel/storage/replication/walreceiverfuncs.cpp @@ -301,6 +301,7 @@ void WalRcvShmemInit(void) t_thrd.walreceiverfuncs_cxt.WalRcv->flagAlreadyNotifyCatchup = false; SpinLockInit(&t_thrd.walreceiverfuncs_cxt.WalRcv->mutex); SpinLockInit(&t_thrd.walreceiverfuncs_cxt.WalRcv->exitLock); + SpinLockInit(&t_thrd.walreceiverfuncs_cxt.WalRcv->uwalMutex); } } diff --git a/src/gausskernel/storage/replication/walsender.cpp b/src/gausskernel/storage/replication/walsender.cpp index 5078b4156c5a2971837439f7a9f57914f9618402..4ebad95a222d9083ba2ec9f4cdd5debca4f3df67 100755 --- a/src/gausskernel/storage/replication/walsender.cpp +++ b/src/gausskernel/storage/replication/walsender.cpp @@ -4871,6 +4871,9 @@ retry: if (0 != GsUwalQueryByUser(t_thrd.xlog_cxt.ThisTimeLineID, false)) { ereport(PANIC, (errcode_for_file_access(), errmsg("uwal query by user failed"))); } + if (t_thrd.xlog_cxt.uwalInfo.info.dataSize > 0) { + GsUwalRenewFileRenamePtr(); + } } else { if (0 != GsUwalQuery(&t_thrd.xlog_cxt.uwalInfo.id, &t_thrd.xlog_cxt.uwalInfo.info)) { ereport(LOG, (errmsg("walsender xlogread GsUwalQuery return failed"))); @@ -4889,15 +4892,16 @@ retry: nbytes -= readbytes; p += readbytes; continue; - } else { - if (0 == GsUwalQuery(&t_thrd.xlog_cxt.uwalInfo.id, &t_thrd.xlog_cxt.uwalInfo.info)) { - ereport(LOG, (errmsg("GsUwalQuery return success, goto retry"))); - continue; - } else { - ereport(LOG, (errmsg("walsender xlogread GsUwalQuery return failed"))); - return; - } } + + if (0 == GsUwalQuery(&t_thrd.xlog_cxt.uwalInfo.id, &t_thrd.xlog_cxt.uwalInfo.info)) { + ereport(LOG, (errmsg("GsUwalQuery return success, goto retry"))); + continue; + } + ereport(LOG, (errmsg("walsender xlogread GsUwalQuery return failed"))); + return; + } else if (!GsUwalCheckFileRename(recptr)) { + continue; } } } @@ -5583,6 +5587,13 @@ static void XLogSendUwalLSN(char* xlogPath) keepalive_message.sendTime = GetCurrentTimestamp(); keepalive_message.replyRequested = false; keepalive_message.catchup = (t_thrd.walsender_cxt.MyWalSnd->state == WALSNDSTATE_CATCHUP); + keepalive_message.uwal_catchup = (t_thrd.walsender_cxt.MyWalSnd->state == WALSNDSTATE_UWALCATCHUP); + UwalrcvWriterState *uwalrcv = GsGetCurrentUwalRcvState(); + if (uwalrcv != NULL) { + SpinLockAcquire(&uwalrcv->mutex); + keepalive_message.fullSync = uwalrcv->fullSync; + SpinLockRelease(&uwalrcv->mutex); + } ereport(DEBUG2, (errmsg("sending wal replication keepalive"))); t_thrd.walsender_cxt.walSndCaughtUp = true; t_thrd.walsender_cxt.catchup_threshold = 0; diff --git a/src/gausskernel/storage/smgr/md.cpp b/src/gausskernel/storage/smgr/md.cpp index c1733e05e9fab22ab4be84e4fd510e91054cff70..52271578686f348fce2df308e3fb3031e9a9a7a3 100644 --- a/src/gausskernel/storage/smgr/md.cpp +++ b/src/gausskernel/storage/smgr/md.cpp @@ -483,6 +483,37 @@ static void mdcleanrepairfile(char *segpath) pfree(temppath); } +/* + * Truncate a file to release disk space. + */ +static int +do_truncate(char *path) +{ + int save_errno; + int ret; + int fd; + + /* truncate(2) would be easier here, but Windows hasn't got it */ + fd = BasicOpenFile(path, O_RDWR | PG_BINARY, 0); + if (fd >= 0) { + ret = ftruncate(fd, 0); + save_errno = errno; + (void)close(fd); + errno = save_errno; + } else + ret = -1; + + /* Log a warning here to avoid repetition in callers. */ + if (ret < 0 && !FILE_POSSIBLY_DELETED(errno)) { + save_errno = errno; + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not truncate file \"%s\": %m", path))); + errno = save_errno; + } + + return ret; +} static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bool isRedo) { @@ -504,12 +535,15 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo Assert(IsHeapFileNode(rnode.node)); if (isRedo || u_sess->attr.attr_common.IsInplaceUpgrade || forkNum != MAIN_FORKNUM || RelFileNodeBackendIsTemp(rnode) || ENABLE_DMS) { - /* First, forget any pending sync requests for the first segment */ if (!RelFileNodeBackendIsTemp(rnode)) { + /* Prevent other backends' fds from holding on to the disk space */ + (void)do_truncate(openFilePath); + + /* Forget any pending sync requests for the first segment */ md_register_forget_request(rnode.node, forkNum, 0 /* first segment */); } - /* Next unlink the file */ + /* Next unlink the file, unless it was already found to be missing */ ret = unlink(openFilePath); if (ret < 0 && !FILE_POSSIBLY_DELETED(errno)) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not remove file \"%s\": ", openFilePath))); @@ -518,22 +552,8 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo mdcleanrepairfile(openFilePath); } } else { - /* truncate(2) would be easier here, but Windows hasn't got it */ - int fd; - - fd = BasicOpenFile(openFilePath, O_RDWR | PG_BINARY, 0); - if (fd >= 0) { - int save_errno; - ret = ftruncate(fd, 0); - save_errno = errno; - (void)close(fd); - errno = save_errno; - } else { - ret = -1; - } - if (ret < 0 && !FILE_POSSIBLY_DELETED(errno)) { - ereport(WARNING, (errcode_for_file_access(), errmsg("could not truncate file \"%s\": %m", openFilePath))); - } + /* Prevent other backends' fds from holding on to the disk space */ + ret = do_truncate(openFilePath); /* Register request to unlink first segment later */ register_unlink_segment(rnode, forkNum, 0); @@ -571,6 +591,17 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo break; } if (!RelFileNodeBackendIsTemp(rnode)) { + /* + * Prevent other backends' fds from holding on to the disk + * space. + */ + if (do_truncate(segpath) < 0 && errno == ENOENT) + break; + + /* + * Forget any pending sync requests for this segment before we + * try to unlink. + */ md_register_forget_request(rnode.node, forkNum, segno); } } diff --git a/src/include/access/double_write.h b/src/include/access/double_write.h index d50d354b5cf0bd88b5c437fe570373739048417c..8455919ad816b1bd7184511f38e0848870f35404 100644 --- a/src/include/access/double_write.h +++ b/src/include/access/double_write.h @@ -271,9 +271,6 @@ void dw_ext_init(); */ inline bool dw_enabled() { - if (ENABLE_DSS) { - return false; - } return (ENABLE_INCRE_CKPT && g_instance.attr.attr_storage.enable_double_write); } diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 994a09996429cc2f5cbb85e2bbe8835146835c5b..c42129994b6938f38fee72a08953e4dcc2ec154a 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -437,6 +437,8 @@ extern Size SyncScanShmemSize(void); extern void PushHeapPageToDataQueue(Buffer buffer); +extern bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer, bool *has_cur_xact_write = NULL); + /* * HeapTupleSatisfiesVisibility * True iff heap tuple satisfies a time qual. diff --git a/src/include/access/ondemand_extreme_rto/page_redo.h b/src/include/access/ondemand_extreme_rto/page_redo.h index d5af1845a2a6294304612d9439346e83a45d17f1..a379a11bc343617e9b53ba3907f933c57bea6753 100644 --- a/src/include/access/ondemand_extreme_rto/page_redo.h +++ b/src/include/access/ondemand_extreme_rto/page_redo.h @@ -191,7 +191,7 @@ struct PageRedoWorker { PosixSemaphore phaseMarker; MemoryContext oldCtx; - ondemand_htab_ctrl_t *redoItemHashCtrl; + ondemand_htab_ctrl_t *redoItemHashCtrl; // The tail of redoItem hashmap, while is actually in use. TimeLineID recoveryTargetTLI; bool ArchiveRecoveryRequested; bool StandbyModeRequested; diff --git a/src/include/access/ondemand_extreme_rto/redo_utils.h b/src/include/access/ondemand_extreme_rto/redo_utils.h index 29a3ca7027f3e28c1e3c19373aae22a75cda872a..80c162747b53f60874c7ad6acd7fb58048d7919e 100644 --- a/src/include/access/ondemand_extreme_rto/redo_utils.h +++ b/src/include/access/ondemand_extreme_rto/redo_utils.h @@ -52,6 +52,5 @@ void OnDemandBackupControlFile(ControlFileData* controlFile); XLogRecPtr GetRedoLocInCheckpointRecord(XLogReaderState *record); void OnDemandUpdateRealtimeBuildPrunePtr(); XLogRecParseType GetCurrentXLogRecParseType(XLogRecParseState *preState); -void WaitUntilRealtimeBuildStatusToFailoverAndUpdatePrunePtr(); #endif /* ONDEMAND_EXTREME_RTO_REDO_UTILS_H */ \ No newline at end of file diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index f85c605eff767dfb978aec2df83918371d6a3888..85e06682acdeec698f2ac23587254f6493daeab5 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -308,5 +308,6 @@ void SetOneOfCompressOption(DefElem* defElem, TableCreateSupport *tableCreateSup bool ReadBoolFromDefElem(DefElem* defElem); void CheckCompressOption(TableCreateSupport *tableCreateSupport); bool CheckSegmentStorageOption(List *options); +void CheckSegmentCompressOption(List *options, char relkind, StorageType storage_type, char* storeChar); #endif /* RELOPTIONS_H */ diff --git a/src/include/catalog/gs_dependencies_fn.h b/src/include/catalog/gs_dependencies_fn.h index 98dadddccc582a98c3254fe0d84256f01c95297f..cc82adda6daae2482d076e7932282648a2e88ae7 100644 --- a/src/include/catalog/gs_dependencies_fn.h +++ b/src/include/catalog/gs_dependencies_fn.h @@ -103,6 +103,7 @@ extern bool gsplsql_build_ref_type_dependency(Oid typ_oid); extern List* gsplsql_prepare_recompile_func(Oid func_oid, Oid schema_oid, Oid pkg_oid, bool is_recompile); extern void gsplsql_complete_recompile_func(List* list); extern Oid gsplsql_parse_pkg_var_obj4(GsDependObjDesc* obj, List* var_name); +extern void gsplsql_do_autonomous_compile(Oid objoid, bool is_pkg); /* * internal interface */ diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h index bc80a5721e8229d1659a72c5f1f77e25b3498e7c..dd27cdfbfd39a20be54eae94cebaa5c9e429ea2e 100644 --- a/src/include/catalog/pg_index.h +++ b/src/include/catalog/pg_index.h @@ -111,6 +111,7 @@ typedef FormData_pg_index *Form_pg_index; * the less ugly representation used after 9.2. */ #define IndexIsUsable(indexForm) ((indexForm)->indisusable) +#define IndexIsUnique(indexForm) ((indexForm)->indisunique) #define IndexIsReady(indexForm) ((indexForm)->indisready) #define IndexIsValid(indexForm) (((indexForm)->indisvalid && (indexForm)->indisready) && ((indexForm)->indisusable)) #define IndexIsLive(indexForm) (((indexForm)->indisready || !(indexForm)->indisvalid) && ((indexForm)->indisusable)) diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 11c80cf161b2fa35faa8491b34a46fb14878c4b7..0918328cfa6b330a0e77388a03bd33ea94a4e967 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -46,7 +46,7 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO float4 procost; /* estimated execution cost */ float4 prorows; /* estimated # of rows out (if proretset) */ Oid provariadic; /* element type of variadic array, or 0 */ - regproc protransform; /* transforms calls to it during planning */ + regproc protransform; /* planner support function for this function, or 0 if none */ bool proisagg; /* is it an aggregate? */ bool proiswindow; /* is it a window function? */ bool prosecdef; /* security definer */ diff --git a/src/include/catalog/pg_proc.h_for_llt b/src/include/catalog/pg_proc.h_for_llt index 747e9ff501c299ee8c3c0c89f668b2c09c56950c..9b4acc40f7ffacadebc60765a27f0e259638efd6 100755 --- a/src/include/catalog/pg_proc.h_for_llt +++ b/src/include/catalog/pg_proc.h_for_llt @@ -43,7 +43,7 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO float4 procost; /* estimated execution cost */ float4 prorows; /* estimated # of rows out (if proretset) */ Oid provariadic; /* element type of variadic array, or 0 */ - regproc protransform; /* transforms calls to it during planning */ + regproc protransform; /* planner support function for this function, or 0 if none */ bool proisagg; /* is it an aggregate? */ bool proiswindow; /* is it a window function? */ bool prosecdef; /* security definer */ @@ -845,11 +845,11 @@ DATA(insert OID = 659 ( namene PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 DATA(insert OID = 668 ( bpchar PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1042 "1042 23 16" _null_ _null_ _null_ _null_ bpchar _null_ _null_ _null_ "" f)); DESCR("adjust char() to typmod length"); -DATA(insert OID = 3097 ( varchar_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ varchar_transform _null_ _null_ _null_ "" f)); -DESCR("transform a varchar length coercion"); -DATA(insert OID = 669 ( varchar PGNSP PGUID 12 1 0 0 varchar_transform f f f f t f i 3 0 1043 "1043 23 16" _null_ _null_ _null_ _null_ varchar _null_ _null_ _null_ "" f)); +DATA(insert OID = 3097 ( varchar_support PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ varchar_support _null_ _null_ _null_ "" f)); +DESCR("planner support for varchar length coercion"); +DATA(insert OID = 669 ( varchar PGNSP PGUID 12 1 0 0 varchar_support f f f f t f i 3 0 1043 "1043 23 16" _null_ _null_ _null_ _null_ varchar _null_ _null_ _null_ "" f)); DESCR("adjust varchar() to typmod length"); -DATA(insert OID = 3961 ( nvarchar2 PGNSP PGUID 12 1 0 0 varchar_transform f f f f t f i 3 0 3969 "3969 23 16" _null_ _null_ _null_ _null_ nvarchar2 _null_ _null_ _null_ "" f)); +DATA(insert OID = 3961 ( nvarchar2 PGNSP PGUID 12 1 0 0 varchar_support f f f f t f i 3 0 3969 "3969 23 16" _null_ _null_ _null_ _null_ nvarchar2 _null_ _null_ _null_ "" f)); DESCR("adjust nvarchar2() to typmod length"); DATA(insert OID = 676 ( mktinterval PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 704 "702 702" _null_ _null_ _null_ _null_ mktinterval _null_ _null_ _null_ "" f)); @@ -1396,9 +1396,9 @@ DESCR("date difference preserving months and years"); /* OIDS 1200 - 1299 */ -DATA(insert OID = 3918 ( interval_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ interval_transform _null_ _null_ _null_ "" f)); -DESCR("transform an interval length coercion"); -DATA(insert OID = 1200 ( interval PGNSP PGUID 12 1 0 0 interval_transform f f f f t f i 2 0 1186 "1186 23" _null_ _null_ _null_ _null_ interval_scale _null_ _null_ _null_ "" f)); +DATA(insert OID = 3918 ( interval_support PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ interval_support _null_ _null_ _null_ "" f)); +DESCR("planner support for interval length coercion"); +DATA(insert OID = 1200 ( interval PGNSP PGUID 12 1 0 0 interval_support f f f f t f i 2 0 1186 "1186 23" _null_ _null_ _null_ _null_ interval_scale _null_ _null_ _null_ "" f)); DESCR("adjust interval precision"); DATA(insert OID = 1215 ( obj_description PGNSP PGUID 14 100 0 0 0 f f f f t f s 2 0 25 "26 19" _null_ _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP) and objsubid = 0" _null_ _null_ _null_ "" f)); @@ -2254,9 +2254,9 @@ DESCR("convert bitstring to int4"); DATA(insert OID = 1685 ( bit PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1560 "1560 23 16" _null_ _null_ _null_ _null_ bit _null_ _null_ _null_ "" f)); DESCR("adjust bit() to typmod length"); -DATA(insert OID = 3158 ( varbit_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ varbit_transform _null_ _null_ _null_ "" f)); -DESCR("transform a varbit length coercion"); -DATA(insert OID = 1687 ( varbit PGNSP PGUID 12 1 0 0 varbit_transform f f f f t f i 3 0 1562 "1562 23 16" _null_ _null_ _null_ _null_ varbit _null_ _null_ _null_ "" f)); +DATA(insert OID = 3158 ( varbit_support PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ varbit_support _null_ _null_ _null_ "" f)); +DESCR("planner support for varbit length coercion"); +DATA(insert OID = 1687 ( varbit PGNSP PGUID 12 1 0 0 varbit_support f f f f t f i 3 0 1562 "1562 23 16" _null_ _null_ _null_ _null_ varbit _null_ _null_ _null_ "" f)); DESCR("adjust varbit() to typmod length"); DATA(insert OID = 1698 ( position PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "1560 1560" _null_ _null_ _null_ _null_ bitposition _null_ _null_ _null_ "" f)); @@ -2391,9 +2391,9 @@ DATA(insert OID = 2917 ( numerictypmodin PGNSP PGUID 12 1 0 0 0 f f f f t f i DESCR("I/O typmod"); DATA(insert OID = 2918 ( numerictypmodout PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "23" _null_ _null_ _null_ _null_ numerictypmodout _null_ _null_ _null_ "" f)); DESCR("I/O typmod"); -DATA(insert OID = 3157 ( numeric_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ numeric_transform _null_ _null_ _null_ "" f)); +DATA(insert OID = 3157 ( numeric_support PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ numeric_support _null_ _null_ _null_ "" f)); DESCR("transform a numeric length coercion"); -DATA(insert OID = 1703 ( numeric PGNSP PGUID 12 1 0 0 numeric_transform f f f f t f i 2 0 1700 "1700 23" _null_ _null_ _null_ _null_ numeric _null_ _null_ _null_ "" f)); +DATA(insert OID = 1703 ( numeric PGNSP PGUID 12 1 0 0 numeric_support f f f f t f i 2 0 1700 "1700 23" _null_ _null_ _null_ _null_ numeric _null_ _null_ _null_ "" f)); DESCR("adjust numeric to typmod precision/scale"); DATA(insert OID = 1704 ( numeric_abs PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_abs _null_ _null_ _null_ "" f)); DATA(insert OID = 1705 ( abs PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_abs _null_ _null_ _null_ "" f)); @@ -3213,12 +3213,12 @@ DESCR("does not match like expression"); DATA(insert OID = 3478 ( rawcat PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 86 "86 86" _null_ _null_ _null_ _null_ rawcat _null_ _null_ _null_"" f)); DESCR("concatenate"); -DATA(insert OID = 3917 ( timestamp_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ timestamp_transform _null_ _null_ _null_ "" f)); -DESCR("transform a timestamp length coercion"); -DATA(insert OID = 3944 ( time_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ time_transform _null_ _null_ _null_ "" f)); +DATA(insert OID = 3917 ( timestamp_support PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ timestamp_support _null_ _null_ _null_ "" f)); +DESCR("planner support for timestamp length coercion"); +DATA(insert OID = 3944 ( time_support PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ time_support _null_ _null_ _null_ "" f)); DESCR("transform a time length coercion"); -DATA(insert OID = 1961 ( timestamp PGNSP PGUID 12 1 0 0 timestamp_transform f f f f t f i 2 0 1114 "1114 23" _null_ _null_ _null_ _null_ timestamp_scale _null_ _null_ _null_ "" f)); +DATA(insert OID = 1961 ( timestamp PGNSP PGUID 12 1 0 0 timestamp_support f f f f t f i 2 0 1114 "1114 23" _null_ _null_ _null_ _null_ timestamp_scale _null_ _null_ _null_ "" f)); DESCR("adjust timestamp precision"); DATA(insert OID = 1965 ( oidlarger PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 26 "26 26" _null_ _null_ _null_ _null_ oidlarger _null_ _null_ _null_ "" f)); @@ -3226,11 +3226,11 @@ DESCR("larger of two"); DATA(insert OID = 1966 ( oidsmaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 26 "26 26" _null_ _null_ _null_ _null_ oidsmaller _null_ _null_ _null_ "" f)); DESCR("smaller of two"); -DATA(insert OID = 1967 ( timestamptz PGNSP PGUID 12 1 0 0 timestamp_transform f f f f t f i 2 0 1184 "1184 23" _null_ _null_ _null_ _null_ timestamptz_scale _null_ _null_ _null_ "" f)); +DATA(insert OID = 1967 ( timestamptz PGNSP PGUID 12 1 0 0 timestamp_support f f f f t f i 2 0 1184 "1184 23" _null_ _null_ _null_ _null_ timestamptz_scale _null_ _null_ _null_ "" f)); DESCR("adjust timestamptz precision"); -DATA(insert OID = 1968 ( time PGNSP PGUID 12 1 0 0 time_transform f f f f t f i 2 0 1083 "1083 23" _null_ _null_ _null_ _null_ time_scale _null_ _null_ _null_ "" f)); +DATA(insert OID = 1968 ( time PGNSP PGUID 12 1 0 0 time_support f f f f t f i 2 0 1083 "1083 23" _null_ _null_ _null_ _null_ time_scale _null_ _null_ _null_ "" f)); DESCR("adjust time precision"); -DATA(insert OID = 1969 ( timetz PGNSP PGUID 12 1 0 0 time_transform f f f f t f i 2 0 1266 "1266 23" _null_ _null_ _null_ _null_ timetz_scale _null_ _null_ _null_ "" f)); +DATA(insert OID = 1969 ( timetz PGNSP PGUID 12 1 0 0 time_support f f f f t f i 2 0 1266 "1266 23" _null_ _null_ _null_ _null_ timetz_scale _null_ _null_ _null_ "" f)); DESCR("adjust time with time zone precision"); DATA(insert OID = 2003 ( textanycat PGNSP PGUID 14 1 0 0 0 f f f f t f s 2 0 25 "25 2776" _null_ _null_ _null_ _null_ "select $1 || $2::pg_catalog.text" _null_ _null_ _null_ "" f)); diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_420.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_420.sql index d357e1010fd1e005193bcbd2cca5ff4871a63e95..f8e11b4e8c3f02753698816bd848fd5c469a49f7 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_420.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_420.sql @@ -259,7 +259,7 @@ DROP TYPE IF EXISTS pg_catalog.jsonb; DROP FUNCTION IF EXISTS pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;DROP FUNCTION IF EXISTS pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;DROP FUNCTION IF EXISTS pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; -DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;UPDATE pg_catalog.pg_am set amcanunique = FALSE where amname = 'cbtree'; +DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;UPDATE pg_catalog.pg_am set amcanunique = FALSE, amhandler = 0 where amname = 'cbtree'; CREATE OR REPLACE VIEW pg_catalog.gs_session_cpu_statistics AS SELECT S.datid AS datid, diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_806.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_806.sql index 01e06299335cfdd2a2ba428b4a0cfa9badd23fd2..4c64a7d0bf4650c04770c39d549dd2d563005a16 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_806.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_806.sql @@ -1,3 +1,8 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then DROP FUNCTION IF EXISTS pg_catalog.sha(text) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.sha1(text) CASCADE; -DROP FUNCTION IF EXISTS pg_catalog.sha2(text, bigint) CASCADE; \ No newline at end of file +DROP FUNCTION IF EXISTS pg_catalog.sha2(text, bigint) CASCADE; +END IF; +END $upgrade$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_812.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_812.sql index 395c2ce32fec0c665310155801b6845cf9a6eb8b..9b20a17887d0323eff9926b164faa03b8762a235 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_812.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_812.sql @@ -1,3 +1,6 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then -------------------------------------------------------------- -- delete pg_amop -------------------------------------------------------------- @@ -23,7 +26,6 @@ delete from pg_catalog.pg_opfamily where oid = 8646; -------------------------------------------------------------- -- delete pg_cast -------------------------------------------------------------- -DO $$ DECLARE cnt int; BEGIN @@ -50,13 +52,12 @@ BEGIN DROP CAST IF EXISTS (anyset AS nvarchar2) CASCADE; DROP CAST IF EXISTS (nvarchar2 AS anyset) CASCADE; end if; -END$$; +END; -------------------------------------------------------------- -- delete pg_operator -------------------------------------------------------------- -DO $$ DECLARE cnt int; BEGIN @@ -117,13 +118,12 @@ BEGIN DROP OPERATOR IF EXISTS pg_catalog.<=(text, anyset) CASCADE; DROP OPERATOR IF EXISTS pg_catalog.>=(text, anyset) CASCADE; end if; -END$$; +END; -------------------------------------------------------------- -- delete builtin funcs -------------------------------------------------------------- -DO $$ DECLARE cnt int; BEGIN @@ -222,12 +222,11 @@ BEGIN DROP FUNCTION IF EXISTS pg_catalog.anyset_in(cstring) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.anyset_out(anyset) CASCADE; end if; -END$$; +END; -------------------------------------------------------------- -- delete all set types -------------------------------------------------------------- -DO $$ DECLARE stmt text; cursor r is select typname from pg_type where typcategory = 'H'; @@ -237,7 +236,7 @@ BEGIN stmt := 'DROP TYPE IF EXISTS pg_catalog.' || tname.typname || ' CASCADE'; execute immediate stmt; end loop; -END$$; +END; DROP TYPE IF EXISTS pg_catalog.anyset CASCADE; @@ -249,3 +248,6 @@ DROP INDEX IF EXISTS pg_catalog.pg_set_typid_label_index; DROP INDEX IF EXISTS pg_catalog.pg_set_oid_index; DROP TYPE IF EXISTS pg_catalog.pg_set; DROP TABLE IF EXISTS pg_catalog.pg_set; + +END IF; +END $upgrade$; diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_920.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_920.sql index 570b0b1d4aaef260dc8f25143bf0560434fb2a7a..1f4ec9e42b8bf829df5e0777ad726df896b0c3dc 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_920.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_920.sql @@ -1,12 +1,21 @@ -DROP VIEW IF EXISTS pg_catalog.pg_publication_tables; -CREATE VIEW pg_catalog.pg_publication_tables AS - SELECT - P.pubname AS pubname, - N.nspname AS schemaname, - C.relname AS tablename - FROM pg_publication P, pg_class C - JOIN pg_namespace N ON (N.oid = C.relnamespace) - WHERE C.oid IN (SELECT relid FROM pg_catalog.pg_get_publication_tables(P.pubname)); +do $$DECLARE ans boolean; +BEGIN + for ans in select case when count(*) = 1 then true else false end as ans from (select relname from pg_class where relname = 'pg_publication_tables' and relkind = 'v' and relnamespace = 11) + LOOP + if ans = true then -- base version is after 92-507, create older view + DROP VIEW IF EXISTS pg_catalog.pg_publication_tables; + CREATE VIEW pg_catalog.pg_publication_tables AS + SELECT + P.pubname AS pubname, + N.nspname AS schemaname, + C.relname AS tablename + FROM pg_publication P, pg_class C + JOIN pg_namespace N ON (N.oid = C.relnamespace) + WHERE C.oid IN (SELECT relid FROM pg_catalog.pg_get_publication_tables(P.pubname)); + end if; + exit; + END LOOP; +END$$; -- drop reform info functions DROP FUNCTION IF EXISTS pg_catalog.query_node_reform_info_from_dms() CASCADE; diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_927.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_927.sql new file mode 100644 index 0000000000000000000000000000000000000000..186140d728df47bb0687654eae89d480da2c8395 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_927.sql @@ -0,0 +1,12 @@ +do $$ +DECLARE +ans boolean; +BEGIN + for ans in select case when count(*)=1 then true else false end as ans from (select extname from pg_extension where extname='dolphin') + LOOP + if ans = true then + ALTER EXTENSION dolphin UPDATE TO '3.0'; + end if; + exit; + END LOOP; +END$$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_928.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_928.sql new file mode 100644 index 0000000000000000000000000000000000000000..a7e9eb5486b569514fd7465c8a3f441bc350a493 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_928.sql @@ -0,0 +1,7 @@ + +UPDATE pg_proc SET proname = 'varchar_transform', prosrc='varchar_transform' WHERE oid = 3097; +UPDATE pg_proc SET proname = 'numeric_transform', prosrc='numeric_transform' WHERE oid = 3157; +UPDATE pg_proc SET proname = 'varbit_transform', prosrc='varbit_transform' WHERE oid = 3158; +UPDATE pg_proc SET proname = 'timestamp_transform', prosrc='timestamp_transform' WHERE oid = 3917; +UPDATE pg_proc SET proname = 'interval_transform', prosrc='interval_transform' WHERE oid = 3918; +UPDATE pg_proc SET proname = 'time_transform', prosrc='time_transform' WHERE oid = 3944; diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_420.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_420.sql index d357e1010fd1e005193bcbd2cca5ff4871a63e95..f8e11b4e8c3f02753698816bd848fd5c469a49f7 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_420.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_420.sql @@ -259,7 +259,7 @@ DROP TYPE IF EXISTS pg_catalog.jsonb; DROP FUNCTION IF EXISTS pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;DROP FUNCTION IF EXISTS pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;DROP FUNCTION IF EXISTS pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; -DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;UPDATE pg_catalog.pg_am set amcanunique = FALSE where amname = 'cbtree'; +DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT encrypt_result_str text) CASCADE;UPDATE pg_catalog.pg_am set amcanunique = FALSE, amhandler = 0 where amname = 'cbtree'; CREATE OR REPLACE VIEW pg_catalog.gs_session_cpu_statistics AS SELECT S.datid AS datid, diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_806.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_806.sql index 01e06299335cfdd2a2ba428b4a0cfa9badd23fd2..4c64a7d0bf4650c04770c39d549dd2d563005a16 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_806.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_806.sql @@ -1,3 +1,8 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then DROP FUNCTION IF EXISTS pg_catalog.sha(text) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.sha1(text) CASCADE; -DROP FUNCTION IF EXISTS pg_catalog.sha2(text, bigint) CASCADE; \ No newline at end of file +DROP FUNCTION IF EXISTS pg_catalog.sha2(text, bigint) CASCADE; +END IF; +END $upgrade$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_812.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_812.sql index 395c2ce32fec0c665310155801b6845cf9a6eb8b..9b20a17887d0323eff9926b164faa03b8762a235 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_812.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_812.sql @@ -1,3 +1,6 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then -------------------------------------------------------------- -- delete pg_amop -------------------------------------------------------------- @@ -23,7 +26,6 @@ delete from pg_catalog.pg_opfamily where oid = 8646; -------------------------------------------------------------- -- delete pg_cast -------------------------------------------------------------- -DO $$ DECLARE cnt int; BEGIN @@ -50,13 +52,12 @@ BEGIN DROP CAST IF EXISTS (anyset AS nvarchar2) CASCADE; DROP CAST IF EXISTS (nvarchar2 AS anyset) CASCADE; end if; -END$$; +END; -------------------------------------------------------------- -- delete pg_operator -------------------------------------------------------------- -DO $$ DECLARE cnt int; BEGIN @@ -117,13 +118,12 @@ BEGIN DROP OPERATOR IF EXISTS pg_catalog.<=(text, anyset) CASCADE; DROP OPERATOR IF EXISTS pg_catalog.>=(text, anyset) CASCADE; end if; -END$$; +END; -------------------------------------------------------------- -- delete builtin funcs -------------------------------------------------------------- -DO $$ DECLARE cnt int; BEGIN @@ -222,12 +222,11 @@ BEGIN DROP FUNCTION IF EXISTS pg_catalog.anyset_in(cstring) CASCADE; DROP FUNCTION IF EXISTS pg_catalog.anyset_out(anyset) CASCADE; end if; -END$$; +END; -------------------------------------------------------------- -- delete all set types -------------------------------------------------------------- -DO $$ DECLARE stmt text; cursor r is select typname from pg_type where typcategory = 'H'; @@ -237,7 +236,7 @@ BEGIN stmt := 'DROP TYPE IF EXISTS pg_catalog.' || tname.typname || ' CASCADE'; execute immediate stmt; end loop; -END$$; +END; DROP TYPE IF EXISTS pg_catalog.anyset CASCADE; @@ -249,3 +248,6 @@ DROP INDEX IF EXISTS pg_catalog.pg_set_typid_label_index; DROP INDEX IF EXISTS pg_catalog.pg_set_oid_index; DROP TYPE IF EXISTS pg_catalog.pg_set; DROP TABLE IF EXISTS pg_catalog.pg_set; + +END IF; +END $upgrade$; diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_920.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_920.sql index 9702137ea47b19b288ac98ce7b4c4dc17785448d..07ecd2c02186aade47b573b83849184d0744c163 100644 --- a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_920.sql +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_920.sql @@ -1,12 +1,21 @@ -DROP VIEW IF EXISTS pg_catalog.pg_publication_tables; -CREATE VIEW pg_catalog.pg_publication_tables AS - SELECT - P.pubname AS pubname, - N.nspname AS schemaname, - C.relname AS tablename - FROM pg_publication P, pg_class C - JOIN pg_namespace N ON (N.oid = C.relnamespace) - WHERE C.oid IN (SELECT relid FROM pg_catalog.pg_get_publication_tables(P.pubname)); +do $$DECLARE ans boolean; +BEGIN + for ans in select case when count(*) = 1 then true else false end as ans from (select relname from pg_class where relname = 'pg_publication_tables' and relkind = 'v' and relnamespace = 11) + LOOP + if ans = true then -- base version is after 92-507, create older view + DROP VIEW IF EXISTS pg_catalog.pg_publication_tables; + CREATE VIEW pg_catalog.pg_publication_tables AS + SELECT + P.pubname AS pubname, + N.nspname AS schemaname, + C.relname AS tablename + FROM pg_publication P, pg_class C + JOIN pg_namespace N ON (N.oid = C.relnamespace) + WHERE C.oid IN (SELECT relid FROM pg_catalog.pg_get_publication_tables(P.pubname)); + end if; + exit; + END LOOP; +END$$; -- drop reform info functions DROP FUNCTION IF EXISTS pg_catalog.query_node_reform_info_from_dms() CASCADE; diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_927.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_927.sql new file mode 100644 index 0000000000000000000000000000000000000000..186140d728df47bb0687654eae89d480da2c8395 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_927.sql @@ -0,0 +1,12 @@ +do $$ +DECLARE +ans boolean; +BEGIN + for ans in select case when count(*)=1 then true else false end as ans from (select extname from pg_extension where extname='dolphin') + LOOP + if ans = true then + ALTER EXTENSION dolphin UPDATE TO '3.0'; + end if; + exit; + END LOOP; +END$$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_928.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_928.sql new file mode 100644 index 0000000000000000000000000000000000000000..a7e9eb5486b569514fd7465c8a3f441bc350a493 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_928.sql @@ -0,0 +1,7 @@ + +UPDATE pg_proc SET proname = 'varchar_transform', prosrc='varchar_transform' WHERE oid = 3097; +UPDATE pg_proc SET proname = 'numeric_transform', prosrc='numeric_transform' WHERE oid = 3157; +UPDATE pg_proc SET proname = 'varbit_transform', prosrc='varbit_transform' WHERE oid = 3158; +UPDATE pg_proc SET proname = 'timestamp_transform', prosrc='timestamp_transform' WHERE oid = 3917; +UPDATE pg_proc SET proname = 'interval_transform', prosrc='interval_transform' WHERE oid = 3918; +UPDATE pg_proc SET proname = 'time_transform', prosrc='time_transform' WHERE oid = 3944; diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_420.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_420.sql index 04eb184fcb52cd9a0be3f2142da576868618e3d9..f906df2382e6331f1accf7bb7abca054168ca198 100644 --- a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_420.sql +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_420.sql @@ -1402,7 +1402,7 @@ CREATE FUNCTION pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN typ DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 6323; -CREATE FUNCTION pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text, OUT encrypt_result_str text) RETURNS text LANGUAGE INTERNAL as 'gs_encrypt';UPDATE pg_catalog.pg_am set amcanunique = TRUE where amname = 'cbtree'; +CREATE FUNCTION pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text, OUT encrypt_result_str text) RETURNS text LANGUAGE INTERNAL as 'gs_encrypt';UPDATE pg_catalog.pg_am set amcanunique = TRUE, amhandler = 0 where amname = 'cbtree'; CREATE OR REPLACE VIEW pg_catalog.gs_session_cpu_statistics AS SELECT S.datid AS datid, diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_806.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_806.sql index 706cf5506191228f1a6d7eaee85333139368038b..9c62f5d9a3dbcedad639c299c85b62744bf0aab6 100644 --- a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_806.sql +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_806.sql @@ -1,3 +1,6 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then --sha SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 558; CREATE OR REPLACE FUNCTION pg_catalog.sha(text) @@ -28,3 +31,5 @@ AS $function$sha2$function$; comment on function PG_CATALOG.sha2(text,bigint) is 'use the sha2 algorithm to hash'; SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0; +END IF; +END $upgrade$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_812.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_812.sql index f9e0313ec0cdff7cd3d3f6f902ec4c3ee77b6fae..3a4a1a06f5c2a393364a8f6599ebfe05162d0bac 100644 --- a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_812.sql +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_812.sql @@ -1,3 +1,6 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then -------------------------------------------------------------- -- add pg_set table -------------------------------------------------------------- @@ -1088,7 +1091,7 @@ END; $$ LANGUAGE 'plpgsql'; SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 8646; -select Insert_pg_opfamily_temp(405, 'set_ops', 11, 10); +PERFORM Insert_pg_opfamily_temp(405, 'set_ops', 11, 10); DROP FUNCTION Insert_pg_opfamily_temp(); @@ -1113,11 +1116,11 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; -select Insert_pg_opclass_temp(403, 'setasint_ops', 11, 10, 1976, 3272, true, 0); -select Insert_pg_opclass_temp(405, 'setasint_ops', 11, 10, 1977, 3272, false, 0); -select Insert_pg_opclass_temp(405, 'settext_ops', 11, 10, 1995, 3272, false, 0); -select Insert_pg_opclass_temp(4439, 'setasint_ops', 11, 10, 6976, 3272, true, 0); -select Insert_pg_opclass_temp(405, 'set_ops', 11, 10, 8646, 3272, true, 0); +PERFORM Insert_pg_opclass_temp(403, 'setasint_ops', 11, 10, 1976, 3272, true, 0); +PERFORM Insert_pg_opclass_temp(405, 'setasint_ops', 11, 10, 1977, 3272, false, 0); +PERFORM Insert_pg_opclass_temp(405, 'settext_ops', 11, 10, 1995, 3272, false, 0); +PERFORM Insert_pg_opclass_temp(4439, 'setasint_ops', 11, 10, 6976, 3272, true, 0); +PERFORM Insert_pg_opclass_temp(405, 'set_ops', 11, 10, 8646, 3272, true, 0); DROP FUNCTION Insert_pg_opclass_temp(); @@ -1139,25 +1142,25 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; -SELECT Insert_pg_amproc_temp(1976, 3272, 3272, 1, 6544); -SELECT Insert_pg_amproc_temp(1976, 3272, 3272, 2, 6538); -SELECT Insert_pg_amproc_temp(1976, 3272, 23, 1, 6545); -SELECT Insert_pg_amproc_temp(1976, 23, 3272, 1, 6543); -SELECT Insert_pg_amproc_temp(1976, 3272, 20, 1, 6546); -SELECT Insert_pg_amproc_temp(1976, 20, 3272, 1, 6547); -SELECT Insert_pg_amproc_temp(1976, 3272, 21, 1, 6549); -SELECT Insert_pg_amproc_temp(1976, 21, 3272, 1, 6548); -SELECT Insert_pg_amproc_temp(1977, 3272, 3272, 1, 3294); -SELECT Insert_pg_amproc_temp(1995, 3272, 3272, 1, 3297); -SELECT Insert_pg_amproc_temp(8646, 3272, 3272, 1, 3297); -SELECT Insert_pg_amproc_temp(6976, 3272, 3272, 1, 6544); -SELECT Insert_pg_amproc_temp(6976, 3272, 3272, 2, 6538); -SELECT Insert_pg_amproc_temp(6976, 3272, 23, 1, 6545); -SELECT Insert_pg_amproc_temp(6976, 23, 3272, 1, 6543); -SELECT Insert_pg_amproc_temp(6976, 3272, 20, 1, 6546); -SELECT Insert_pg_amproc_temp(6976, 20, 3272, 1, 6547); -SELECT Insert_pg_amproc_temp(6976, 3272, 21, 1, 6549); -SELECT Insert_pg_amproc_temp(6976, 21, 3272, 1, 6548); +PERFORM Insert_pg_amproc_temp(1976, 3272, 3272, 1, 6544); +PERFORM Insert_pg_amproc_temp(1976, 3272, 3272, 2, 6538); +PERFORM Insert_pg_amproc_temp(1976, 3272, 23, 1, 6545); +PERFORM Insert_pg_amproc_temp(1976, 23, 3272, 1, 6543); +PERFORM Insert_pg_amproc_temp(1976, 3272, 20, 1, 6546); +PERFORM Insert_pg_amproc_temp(1976, 20, 3272, 1, 6547); +PERFORM Insert_pg_amproc_temp(1976, 3272, 21, 1, 6549); +PERFORM Insert_pg_amproc_temp(1976, 21, 3272, 1, 6548); +PERFORM Insert_pg_amproc_temp(1977, 3272, 3272, 1, 3294); +PERFORM Insert_pg_amproc_temp(1995, 3272, 3272, 1, 3297); +PERFORM Insert_pg_amproc_temp(8646, 3272, 3272, 1, 3297); +PERFORM Insert_pg_amproc_temp(6976, 3272, 3272, 1, 6544); +PERFORM Insert_pg_amproc_temp(6976, 3272, 3272, 2, 6538); +PERFORM Insert_pg_amproc_temp(6976, 3272, 23, 1, 6545); +PERFORM Insert_pg_amproc_temp(6976, 23, 3272, 1, 6543); +PERFORM Insert_pg_amproc_temp(6976, 3272, 20, 1, 6546); +PERFORM Insert_pg_amproc_temp(6976, 20, 3272, 1, 6547); +PERFORM Insert_pg_amproc_temp(6976, 3272, 21, 1, 6549); +PERFORM Insert_pg_amproc_temp(6976, 21, 3272, 1, 6548); DROP FUNCTION Insert_pg_amproc_temp(); @@ -1188,85 +1191,88 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; -SELECT Insert_pg_amop_temp(1995, 3272, 25, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1995, 25, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1995, 3272, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(1977, 3272, 23, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 23, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 3272, 20, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 20, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 3272, 21, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 21, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(8646, 3272, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1995, 3272, 25, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1995, 25, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1995, 3272, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(1977, 3272, 23, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 23, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 3272, 20, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 20, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 3272, 21, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 21, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(8646, 3272, 3272, 1, 's', 405, 0); DROP FUNCTION Insert_pg_amop_temp(); + +END IF; +END $upgrade$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_927.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_927.sql new file mode 100644 index 0000000000000000000000000000000000000000..cf2c7b29734262a8b4eabb04ad7a2bf3d3a8bcfe --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_927.sql @@ -0,0 +1,12 @@ +do $$ +DECLARE +ans boolean; +BEGIN + for ans in select case when count(*)=1 then true else false end as ans from (select extname from pg_extension where extname='dolphin') + LOOP + if ans = true then + ALTER EXTENSION dolphin UPDATE TO '4.0'; + end if; + exit; + END LOOP; +END$$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_928.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_928.sql new file mode 100644 index 0000000000000000000000000000000000000000..6c4e140cc65ef0a6b952ae2f1b453d5355831b09 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_928.sql @@ -0,0 +1,7 @@ + +UPDATE pg_proc SET proname = 'varchar_support', prosrc='varchar_support' WHERE oid = 3097; +UPDATE pg_proc SET proname = 'numeric_support', prosrc='numeric_support' WHERE oid = 3157; +UPDATE pg_proc SET proname = 'varbit_support', prosrc='varbit_support' WHERE oid = 3158; +UPDATE pg_proc SET proname = 'timestamp_support', prosrc='timestamp_support' WHERE oid = 3917; +UPDATE pg_proc SET proname = 'interval_support', prosrc='interval_support' WHERE oid = 3918; +UPDATE pg_proc SET proname = 'time_support', prosrc='time_support' WHERE oid = 3944; diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_420.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_420.sql index 6bec8e58df99d01031dbf571198d591ad92443b9..e2da8093442ab5a96098c7eddd0353d26a6a07ac 100644 --- a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_420.sql +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_420.sql @@ -1402,7 +1402,7 @@ CREATE FUNCTION pg_catalog.gs_decrypt(IN decryptstr text, IN keystr text, IN typ DROP FUNCTION IF EXISTS pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text,OUT decrypt_result_str text) CASCADE; SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 6323; -CREATE FUNCTION pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text, OUT encrypt_result_str text) RETURNS text LANGUAGE INTERNAL as 'gs_encrypt';UPDATE pg_catalog.pg_am set amcanunique = TRUE where amname = 'cbtree'; +CREATE FUNCTION pg_catalog.gs_encrypt(IN encryptstr text, IN keystr text, IN type text, OUT encrypt_result_str text) RETURNS text LANGUAGE INTERNAL as 'gs_encrypt';UPDATE pg_catalog.pg_am set amcanunique = TRUE, amhandler = 0 where amname = 'cbtree'; CREATE OR REPLACE VIEW pg_catalog.gs_session_cpu_statistics AS SELECT S.datid AS datid, diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_806.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_806.sql index 706cf5506191228f1a6d7eaee85333139368038b..d90cc383600092beffff83a1abaf1639f971c59b 100644 --- a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_806.sql +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_806.sql @@ -1,3 +1,6 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then --sha SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 558; CREATE OR REPLACE FUNCTION pg_catalog.sha(text) @@ -28,3 +31,5 @@ AS $function$sha2$function$; comment on function PG_CATALOG.sha2(text,bigint) is 'use the sha2 algorithm to hash'; SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0; +END IF; +END $upgrade$; diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_812.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_812.sql index f9e0313ec0cdff7cd3d3f6f902ec4c3ee77b6fae..3a4a1a06f5c2a393364a8f6599ebfe05162d0bac 100644 --- a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_812.sql +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_812.sql @@ -1,3 +1,6 @@ +DO $upgrade$ +BEGIN +IF working_version_num() < 92780 then -------------------------------------------------------------- -- add pg_set table -------------------------------------------------------------- @@ -1088,7 +1091,7 @@ END; $$ LANGUAGE 'plpgsql'; SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 8646; -select Insert_pg_opfamily_temp(405, 'set_ops', 11, 10); +PERFORM Insert_pg_opfamily_temp(405, 'set_ops', 11, 10); DROP FUNCTION Insert_pg_opfamily_temp(); @@ -1113,11 +1116,11 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; -select Insert_pg_opclass_temp(403, 'setasint_ops', 11, 10, 1976, 3272, true, 0); -select Insert_pg_opclass_temp(405, 'setasint_ops', 11, 10, 1977, 3272, false, 0); -select Insert_pg_opclass_temp(405, 'settext_ops', 11, 10, 1995, 3272, false, 0); -select Insert_pg_opclass_temp(4439, 'setasint_ops', 11, 10, 6976, 3272, true, 0); -select Insert_pg_opclass_temp(405, 'set_ops', 11, 10, 8646, 3272, true, 0); +PERFORM Insert_pg_opclass_temp(403, 'setasint_ops', 11, 10, 1976, 3272, true, 0); +PERFORM Insert_pg_opclass_temp(405, 'setasint_ops', 11, 10, 1977, 3272, false, 0); +PERFORM Insert_pg_opclass_temp(405, 'settext_ops', 11, 10, 1995, 3272, false, 0); +PERFORM Insert_pg_opclass_temp(4439, 'setasint_ops', 11, 10, 6976, 3272, true, 0); +PERFORM Insert_pg_opclass_temp(405, 'set_ops', 11, 10, 8646, 3272, true, 0); DROP FUNCTION Insert_pg_opclass_temp(); @@ -1139,25 +1142,25 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; -SELECT Insert_pg_amproc_temp(1976, 3272, 3272, 1, 6544); -SELECT Insert_pg_amproc_temp(1976, 3272, 3272, 2, 6538); -SELECT Insert_pg_amproc_temp(1976, 3272, 23, 1, 6545); -SELECT Insert_pg_amproc_temp(1976, 23, 3272, 1, 6543); -SELECT Insert_pg_amproc_temp(1976, 3272, 20, 1, 6546); -SELECT Insert_pg_amproc_temp(1976, 20, 3272, 1, 6547); -SELECT Insert_pg_amproc_temp(1976, 3272, 21, 1, 6549); -SELECT Insert_pg_amproc_temp(1976, 21, 3272, 1, 6548); -SELECT Insert_pg_amproc_temp(1977, 3272, 3272, 1, 3294); -SELECT Insert_pg_amproc_temp(1995, 3272, 3272, 1, 3297); -SELECT Insert_pg_amproc_temp(8646, 3272, 3272, 1, 3297); -SELECT Insert_pg_amproc_temp(6976, 3272, 3272, 1, 6544); -SELECT Insert_pg_amproc_temp(6976, 3272, 3272, 2, 6538); -SELECT Insert_pg_amproc_temp(6976, 3272, 23, 1, 6545); -SELECT Insert_pg_amproc_temp(6976, 23, 3272, 1, 6543); -SELECT Insert_pg_amproc_temp(6976, 3272, 20, 1, 6546); -SELECT Insert_pg_amproc_temp(6976, 20, 3272, 1, 6547); -SELECT Insert_pg_amproc_temp(6976, 3272, 21, 1, 6549); -SELECT Insert_pg_amproc_temp(6976, 21, 3272, 1, 6548); +PERFORM Insert_pg_amproc_temp(1976, 3272, 3272, 1, 6544); +PERFORM Insert_pg_amproc_temp(1976, 3272, 3272, 2, 6538); +PERFORM Insert_pg_amproc_temp(1976, 3272, 23, 1, 6545); +PERFORM Insert_pg_amproc_temp(1976, 23, 3272, 1, 6543); +PERFORM Insert_pg_amproc_temp(1976, 3272, 20, 1, 6546); +PERFORM Insert_pg_amproc_temp(1976, 20, 3272, 1, 6547); +PERFORM Insert_pg_amproc_temp(1976, 3272, 21, 1, 6549); +PERFORM Insert_pg_amproc_temp(1976, 21, 3272, 1, 6548); +PERFORM Insert_pg_amproc_temp(1977, 3272, 3272, 1, 3294); +PERFORM Insert_pg_amproc_temp(1995, 3272, 3272, 1, 3297); +PERFORM Insert_pg_amproc_temp(8646, 3272, 3272, 1, 3297); +PERFORM Insert_pg_amproc_temp(6976, 3272, 3272, 1, 6544); +PERFORM Insert_pg_amproc_temp(6976, 3272, 3272, 2, 6538); +PERFORM Insert_pg_amproc_temp(6976, 3272, 23, 1, 6545); +PERFORM Insert_pg_amproc_temp(6976, 23, 3272, 1, 6543); +PERFORM Insert_pg_amproc_temp(6976, 3272, 20, 1, 6546); +PERFORM Insert_pg_amproc_temp(6976, 20, 3272, 1, 6547); +PERFORM Insert_pg_amproc_temp(6976, 3272, 21, 1, 6549); +PERFORM Insert_pg_amproc_temp(6976, 21, 3272, 1, 6548); DROP FUNCTION Insert_pg_amproc_temp(); @@ -1188,85 +1191,88 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; -SELECT Insert_pg_amop_temp(1995, 3272, 25, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1995, 25, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1995, 3272, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 23, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 23, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 20, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 20, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 3272, 21, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 1, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 2, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 3, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 4, 's', 403, 0); -SELECT Insert_pg_amop_temp(1976, 21, 3272, 5, 's', 403, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 23, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 23, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 20, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 20, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 3272, 21, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 1, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 2, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 3, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 4, 's', 4439, 0); -SELECT Insert_pg_amop_temp(6976, 21, 3272, 5, 's', 4439, 0); -SELECT Insert_pg_amop_temp(1977, 3272, 23, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 23, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 3272, 20, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 20, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 3272, 21, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(1977, 21, 3272, 1, 's', 405, 0); -SELECT Insert_pg_amop_temp(8646, 3272, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1995, 3272, 25, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1995, 25, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1995, 3272, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 23, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 23, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 20, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 20, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 3272, 21, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 1, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 2, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 3, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 4, 's', 403, 0); +PERFORM Insert_pg_amop_temp(1976, 21, 3272, 5, 's', 403, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 23, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 23, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 20, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 20, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 3272, 21, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 1, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 2, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 3, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 4, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(6976, 21, 3272, 5, 's', 4439, 0); +PERFORM Insert_pg_amop_temp(1977, 3272, 23, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 23, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 3272, 20, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 20, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 3272, 21, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(1977, 21, 3272, 1, 's', 405, 0); +PERFORM Insert_pg_amop_temp(8646, 3272, 3272, 1, 's', 405, 0); DROP FUNCTION Insert_pg_amop_temp(); + +END IF; +END $upgrade$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_927.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_927.sql new file mode 100644 index 0000000000000000000000000000000000000000..cf2c7b29734262a8b4eabb04ad7a2bf3d3a8bcfe --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_927.sql @@ -0,0 +1,12 @@ +do $$ +DECLARE +ans boolean; +BEGIN + for ans in select case when count(*)=1 then true else false end as ans from (select extname from pg_extension where extname='dolphin') + LOOP + if ans = true then + ALTER EXTENSION dolphin UPDATE TO '4.0'; + end if; + exit; + END LOOP; +END$$; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_928.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_928.sql new file mode 100644 index 0000000000000000000000000000000000000000..6c4e140cc65ef0a6b952ae2f1b453d5355831b09 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_928.sql @@ -0,0 +1,7 @@ + +UPDATE pg_proc SET proname = 'varchar_support', prosrc='varchar_support' WHERE oid = 3097; +UPDATE pg_proc SET proname = 'numeric_support', prosrc='numeric_support' WHERE oid = 3157; +UPDATE pg_proc SET proname = 'varbit_support', prosrc='varbit_support' WHERE oid = 3158; +UPDATE pg_proc SET proname = 'timestamp_support', prosrc='timestamp_support' WHERE oid = 3917; +UPDATE pg_proc SET proname = 'interval_support', prosrc='interval_support' WHERE oid = 3918; +UPDATE pg_proc SET proname = 'time_support', prosrc='time_support' WHERE oid = 3944; diff --git a/src/include/ddes/dms/dms_api.h b/src/include/ddes/dms/dms_api.h index f08db3c2318ca7dd6fc1b984334365b787d29ffa..f2442edb71dbc4e4f83d7d6f431cc1ef240288e3 100644 --- a/src/include/ddes/dms/dms_api.h +++ b/src/include/ddes/dms/dms_api.h @@ -25,6 +25,7 @@ #define __DMS_API_H__ #include +#include #ifdef __cplusplus extern "C" { #endif @@ -33,7 +34,7 @@ extern "C" { #define DMS_LOCAL_MINOR_VER_WEIGHT 1000 #define DMS_LOCAL_MAJOR_VERSION 0 #define DMS_LOCAL_MINOR_VERSION 0 -#define DMS_LOCAL_VERSION 135 +#define DMS_LOCAL_VERSION 148 #define DMS_SUCCESS 0 #define DMS_ERROR (-1) @@ -50,6 +51,7 @@ extern "C" { #define DMS_MAX_IP_LEN 64 #define DMS_MAX_INSTANCES 64 #define DMS_MAX_NAME_LEN 64 +#define DMS_MAX_RESOURCE_NAME_LEN 136 #define DMS_VERSION_MAX_LEN 256 #define DMS_OCK_LOG_PATH_LEN 256 @@ -59,6 +61,13 @@ extern "C" { #define DMS_MAX_XA_BASE16_GTRID_LEN (128) #define DMS_MAX_XA_BASE16_BQUAL_LEN (128) +#define DB_FI_ENTRY_BEGIN 10000 +#define DB_FI_ENTRY_COUNT 1024 +#define FI_ENTRY_END (DB_FI_ENTRY_BEGIN + DB_FI_ENTRY_COUNT) +#define MAX_FI_ENTRY_COUNT 2000 + +#define MAX_DMS_THREAD_NUM 512 + typedef enum en_dms_online_status { DMS_ONLINE_STATUS_OUT = 0, DMS_ONLINE_STATUS_JOIN = 1, @@ -95,12 +104,15 @@ typedef enum en_dms_dr_type { DMS_DR_TYPE_SEQVAL = 25, DMS_DR_TYPE_SHARED_INNODE = 26, DMS_DR_TYPE_PROC_ENTRY = 27, - DMS_DR_TYPE_PART_TABLE, + DMS_DR_TYPE_PART_TABLE = 28, + DMS_DR_TYPE_SS_LINK = 29, + DMS_DR_TYPE_TX_ALCK = 30, + DMS_DR_TYPE_SE_ALCK = 31, DMS_DR_TYPE_MAX, } dms_dr_type_t; #define DMS_DR_IS_TABLE_TYPE(type) ((type) == DMS_DR_TYPE_TABLE || (type) == DMS_DR_TYPE_PART_TABLE) - +#define DMS_DR_IS_ALOCK_TYPE(type) ((type) == DMS_DR_TYPE_TX_ALCK || (type) == DMS_DR_TYPE_SE_ALCK) // persistent distributed resource id typedef enum en_dms_persistent_id { DMS_ID_DATABASE_CTRL = 0, @@ -117,10 +129,10 @@ typedef enum en_dms_persistent_id { // for smon deadlock check #define DMS_SMON_DLOCK_MSG_MAX_LEN 24 -#define DMS_SMON_TLOCK_MSG_MAX_LEN 24 -#define DMS_SMON_ILOCK_MSG_MAX_LEN 60 +#define DMS_SMON_TLOCK_MSG_MAX_LEN 56 #define DMS_SMON_MAX_SQL_LEN 10240 // The maximum size of a message to be transferred in the MES is 32 KB. -#define MAX_TABLE_LOCK_NUM 2048 +#define MAX_TABLE_LOCK_NUM 512 +#define DMS_MAX_W_MARKS_NUM (16320 * 64) typedef enum en_dms_smon_req_type { DMS_SMON_REQ_SID_BY_RMID = 0, @@ -128,23 +140,13 @@ typedef enum en_dms_smon_req_type { DMS_SMON_REQ_ROWID_BY_RMID = 2, }dms_smon_req_type_t; -typedef enum en_dms_smon_req_tlock_type { - DMS_SMON_REQ_TABLE_LOCK_SHARED_MSG = 0, - DMS_SMON_REQ_TABLE_LOCK_EXCLU_MSG = 1, - DMS_SMON_REQ_TABLE_LOCK_ALL_MSG = 2, -}dms_smon_req_tlock_type_t; - typedef enum en_dms_smon_req_rm_type { - DMS_SMON_REQ_TABLE_LOCK_RM = 0, - DMS_SMON_REQ_TABLE_LOCK_WAIT_RM = 1, + DMS_SMON_REQ_TLOCK_RM = 0, + DMS_SMON_REQ_TLOCK_WAIT_RM = 1, }dms_smon_req_rm_type_t; -typedef enum en_dms_smon_check_tlock_type { - DMS_SMON_CHECK_WAIT_EVENT_STATUS_BY_SID = 0, - DMS_SMON_CHECK_WAIT_TABLE_STATUS_BY_TID = 1, -}dms_smon_check_tlock_type_t; - /* distributed resource id definition */ +#define DMS_DRID_CTX_SIZE 128 #pragma pack(4) typedef struct st_dms_drid { union { @@ -155,7 +157,10 @@ typedef struct st_dms_drid { }; struct { unsigned short type; // lock type - unsigned short uid; // user id, for table lock resource + union { + unsigned short uid; // user id, for table lock resource + unsigned short len; + }; union { struct { unsigned int oid; // lock id @@ -167,6 +172,9 @@ typedef struct st_dms_drid { unsigned long long oid_64; unsigned long long unused; }; + struct { + unsigned char resid[DMS_DRID_CTX_SIZE]; + }; }; }; }; @@ -254,7 +262,7 @@ typedef struct st_dms_cr_assist_t { dms_cr_status_t status; /* OUT parameter */ } dms_cr_assist_t; -#define DMS_RESID_SIZE 32 +#define DMS_RESID_SIZE 132 #define DMS_DRID_SIZE sizeof(dms_drid_t) typedef struct st_dms_drlock { @@ -328,8 +336,12 @@ typedef struct st_dms_context { unsigned char edp_inst; drc_global_xid_t global_xid; }; + void *stat; + void *stat_instance; + unsigned long long wait_usecs; unsigned char intercept_type; unsigned char curr_mode; // used for table lock + unsigned long long max_wait_rsp_time; // unit ms. under some circumstances, dms need get rsp quickly for timeout. } dms_context_t; typedef struct st_dms_cr { @@ -389,6 +401,7 @@ typedef struct st_dms_txn_info { unsigned char is_owscn; unsigned char status; unsigned char unused[2]; + unsigned long long xid; } dms_txn_info_t; typedef struct st_dms_txn_snapshot { @@ -425,10 +438,14 @@ typedef struct st_dms_buf_ctrl { volatile unsigned char need_flush; // for recovery, owner is abort, copy instance should flush before release volatile unsigned char been_loaded; // first alloc ctrl:FALSE, after successfully loaded: TRUE volatile unsigned char in_rcy; // if drc lost, we can rebuild in_recovery flag according buf_ctrl - volatile unsigned char unused; + unsigned char release_conflict : 1; + unsigned char unused : 7; unsigned long long edp_scn; // set when become edp, lastest scn when page becomes edp unsigned long long edp_map; // records edp instance long long last_ckpt_time; // last time when local edp page is added to group. + volatile unsigned char is_reform_visit; + unsigned unused_array[3]; + volatile unsigned int lock_ss_read; // concurrency control for rebuild/confirm #ifdef OPENGAUSS int buf_id; unsigned int state; @@ -437,7 +454,7 @@ typedef struct st_dms_buf_ctrl { unsigned long long pblk_lsn; unsigned char seg_fileno; unsigned int seg_blockno; - void* ctrl_lock; + void *ctrl_lock; #endif } dms_buf_ctrl_t; @@ -568,10 +585,13 @@ typedef enum en_dms_wait_event { DMS_EVT_DLS_REQ_TABLE, DMS_EVT_DLS_REQ_PART_X, DMS_EVT_DLS_REQ_PART_S, + DMS_EVT_DLS_REQ_ALOCK_X, + DMS_EVT_DLS_REQ_ALOCK_S, DMS_EVT_DLS_WAIT_TXN, DMS_EVT_DEAD_LOCK_TXN, DMS_EVT_DEAD_LOCK_TABLE, DMS_EVT_DEAD_LOCK_ITL, + DMS_EVT_DEAD_LOCK_ALCK, DMS_EVT_BROADCAST_BTREE_SPLIT, DMS_EVT_BROADCAST_ROOT_PAGE, DMS_EVT_QUERY_OWNER_ID, @@ -638,6 +658,15 @@ typedef enum en_dms_reform_type { DMS_REFORM_TYPE_FOR_MAINTAIN, // for start database without CM, every instance is supported // New type need to be added start from here DMS_REFORM_TYPE_FOR_RST_RECOVER, + DMS_REFORM_TYPE_FOR_NEW_JOIN, + DMS_REFORM_TYPE_FOR_OLD_REMOVE, + DMS_REFORM_TYPE_FOR_SHUTDOWN_CONSISTENCY, + DMS_REFORM_TYPE_FOR_STANDBY_MAINTAIN, + DMS_REFORM_TYPE_FOR_NORMAL_STANDBY, + DMS_REFORM_TYPE_FOR_AZ_SWITCHOVER_DEMOTE, + DMS_REFORM_TYPE_FOR_AZ_SWITCHOVER_PROMOTE, + DMS_REFORM_TYPE_FOR_AZ_FAILOVER, + DMS_REFORM_TYPE_COUNT } dms_reform_type_t; @@ -686,6 +715,7 @@ typedef struct st_stat_buf_info { typedef enum en_broadcast_scope { DMS_BROADCAST_OLDIN_LIST = 0, // default value DMS_BROADCAST_ONLINE_LIST = 1, + DMS_BROADCAST_SPECIFY_LIST = 2, DMS_BROADCAST_TYPE_COUNT, } dms_broadcast_scope_e; @@ -695,7 +725,7 @@ typedef enum en_broadcast_scope { typedef struct st_dv_drc_buf_info { stat_buf_info_t buf_info[DMS_MAX_INSTANCES]; /* save buffer related information */ dms_context_t dms_ctx; - char data[DMS_MAX_NAME_LEN]; /* user defined resource(page) identifier */ + char data[DMS_MAX_RESOURCE_NAME_LEN]; /* user defined resource(page) identifier */ unsigned char master_id; unsigned long long copy_insts; /* bitmap for owners, for S mode, more than one owner may exist */ unsigned char claimed_owner; /* owner */ @@ -723,6 +753,26 @@ typedef struct st_dms_reform_start_context { unsigned long long bitmap_reconnect; } dms_reform_start_context_t; +typedef enum en_dms_db_role { + DMS_DB_ROLE_PRIMARY = 0, + DMS_DB_ROLE_PHYSICAL_STANDBY = 1, + DMS_DB_ROLE_CASCADED_PHYSICAL_STANDBY = 2, +} dms_db_role_t; + +typedef struct st_dms_broadcast_info { + char *data; + unsigned int len; + char *output; + unsigned int *output_len; + dms_broadcast_scope_e scope; + unsigned long long inst_map; /* when scope is DMS_BROADCAST_SPECIFY_LIST, inst_map is used */ + unsigned int timeout; + unsigned char handle_recv_msg; + unsigned char check_session_kill; +} dms_broadcast_info_t; + +typedef struct dms_fi_entry dms_fi_entry; +typedef int(*dms_fi_callback_func)(const dms_fi_entry *entry, va_list args); typedef int(*dms_get_list_stable)(void *db_handle, unsigned long long *list_stable, unsigned char *reformer_id); typedef int(*dms_save_list_stable)(void *db_handle, unsigned long long list_stable, unsigned char reformer_id, unsigned long long list_in, unsigned int save_ctrl); @@ -761,6 +811,7 @@ typedef int(*dms_set_buf_load_status)(dms_buf_ctrl_t *buf_ctrl, dms_buf_load_sta typedef int(*dms_remove_buf_load_status)(dms_buf_ctrl_t *buf_ctrl, dms_buf_load_status_t dms_buf_load_status); typedef void(*dms_update_global_lsn)(void *db_handle, unsigned long long lamport_lsn); typedef void(*dms_update_global_scn)(void *db_handle, unsigned long long lamport_scn); +typedef void(*dms_update_node_lfn)(void *db_handle, unsigned long long lfn, char node_id); typedef void(*dms_update_page_lfn)(dms_buf_ctrl_t *buf_ctrl, unsigned long long lastest_lfn); typedef unsigned long long (*dms_get_page_lfn)(dms_buf_ctrl_t *buf_ctrl); typedef unsigned long long(*dms_get_global_lfn)(void *db_handle); @@ -838,6 +889,8 @@ typedef void (*dms_reset_user)(void *db_handle, unsigned long long list_in); typedef int (*dms_drc_xa_res_rebuild)(void *db_handle, unsigned char thread_index, unsigned char parall_num); typedef void (*dms_reform_shrink_xa_rms)(void *db_handle, unsigned char undo_seg_id); typedef void (*dms_ckpt_unblock_rcy_local)(void *db_handle, unsigned long long list_in); +typedef int (*dms_drc_rebuild_parallel)(void *db_handle, unsigned char thread_index, unsigned char thread_num); +typedef int (*dms_drc_validate_parallel)(void *db_handle, unsigned char thread_index, unsigned char thread_num); // for openGauss typedef void (*dms_thread_init_t)(unsigned char need_startup, char **reg_data); @@ -855,12 +908,10 @@ typedef void (*dms_get_txn_dlock_by_rmid)(void *db_handle, unsigned short rmid, typedef void (*dms_get_rowid_by_rmid)(void *db_handle, unsigned short rmid, char rowid[DMS_ROWID_SIZE]); typedef void (*dms_get_sql_from_session)(void *db_handle, unsigned short sid, char *sql_str, unsigned int sql_str_len); typedef int (*dms_get_itl_lock_by_xid)(void *db_handle, char xid[DMS_XID_SIZE], char *ilock, unsigned int ilock_len); -typedef void (*dms_check_tlock_status)(void *db_handle, unsigned int type, unsigned short sid, - unsigned long long tableid, unsigned int *in_use); -typedef void (*dms_get_tlock_msg_by_tid)(void *db_handle, unsigned long long table_id, unsigned int type, char *rsp, - unsigned int rsp_len, unsigned int *tlock_cnt); -typedef void (*dms_get_tlock_msg_by_rm)(void *db_handle, unsigned short sid, unsigned short rmid, int type, char *tlock, +typedef void (*dms_get_tlock_by_rm)(void *db_handle, unsigned short sid, unsigned short rmid, int type, char *tlock, unsigned int tlock_len); +typedef int (*dms_get_tlock_by_tid)(void *db_handle, char *tlock, char *out_msg); +typedef void (*dms_get_tlock_by_tid_ack)(char *data, char *stack, char *w_marks, unsigned int *cnt); typedef int (*dms_switchover_demote)(void *db_handle); typedef int (*dms_switchover_promote)(void *db_handle); @@ -893,7 +944,29 @@ typedef void (*dms_free_prot_proc)(void *ptr); typedef int (*dms_get_kernel_error_code)(); typedef int (*dms_lsn_validate)(void *db_handle, char *pageid, unsigned long long lsn, unsigned char in_recovery); typedef int (*dms_invld_tlock_ownership)(void *db_handle, char *resid, unsigned char req_mode, unsigned char is_try); -typedef int (*dms_get_tlock_mode)(void *db_handle, char *resid); +typedef unsigned short (*dms_get_tlock_mode)(void *db_handle, char *resid); +typedef void (*dms_set_current_point)(void *db_handle); + +typedef void (*dms_get_db_role)(void *db_handle, unsigned int *role); +typedef void (*dms_check_lrpl_takeover)(void *db_handle, unsigned int *need_takeover); +typedef void (*dms_reset_link)(void *db_handle); +typedef void (*dms_set_online_list)(void *db_handle, unsigned long long online_list); +typedef int (*dms_start_lrpl)(void *db_handle, int is_reformer); +typedef int (*dms_stop_lrpl)(void *db_handle, int is_reformer); +typedef int (*dms_az_switchover_demote_phase1)(void *db_handle); +typedef int (*dms_az_switchover_demote_approve)(void *db_handle); +typedef int (*dms_az_switchover_demote_phase2)(void *db_handle); +typedef int (*dms_az_switchover_promote_core)(void *db_handle); +typedef void (*dms_dyn_log)(void *db_handle, long long dyn_log_time); + +typedef int (*dms_invld_alock_ownership)(void *db_handle, char *resid, unsigned char req_mode, unsigned char is_try); +typedef unsigned short (*dms_get_alock_mode)(void *db_handle, char *resid); +typedef int (*dms_get_alock_wait_info)(void *db_handle, char *resid, char *info_buf, unsigned int buf_len, + unsigned int *info_len); +typedef int (*dms_az_failover_promote_phase1)(void *db_handle); +typedef int (*dms_az_failover_promote_resetlog)(void *db_handle); +typedef int (*dms_az_failover_promote_phase2)(void *db_handle); +typedef int (*dms_check_shutdown_consistency)(void *db_handle, instance_list_t *old_remove); typedef struct st_dms_callback { // used in reform @@ -935,6 +1008,8 @@ typedef struct st_dms_callback { dms_reform_shrink_xa_rms dms_shrink_xa_rms; dms_ckpt_unblock_rcy_local ckpt_unblock_rcy_local; + dms_drc_rebuild_parallel rebuild_alock_parallel; + dms_drc_validate_parallel validate_alock_parallel; // used in reform for opengauss dms_thread_init_t dms_thread_init; dms_thread_deinit_t dms_thread_deinit; @@ -1015,9 +1090,9 @@ typedef struct st_dms_callback { dms_get_rowid_by_rmid get_rowid_by_rmid; dms_get_sql_from_session get_sql_from_session; dms_get_itl_lock_by_xid get_itl_lock_by_xid; - dms_check_tlock_status check_tlock_status; - dms_get_tlock_msg_by_tid get_tlock_by_tid; - dms_get_tlock_msg_by_rm get_tlock_by_rm; + dms_get_tlock_by_rm get_tlock_by_rm; + dms_get_tlock_by_tid get_tlock_by_tid; + dms_get_tlock_by_tid_ack get_tlock_by_tid_ack; // for switchover dms_switchover_demote switchover_demote; @@ -1057,7 +1132,31 @@ typedef struct st_dms_callback { dms_get_kernel_error_code db_get_kernel_error_code; dms_lsn_validate lsn_validate; dms_invld_tlock_ownership invld_tlock_ownership; + dms_invld_alock_ownership invld_alock_ownership; + dms_get_alock_mode get_alock_mode; dms_get_tlock_mode get_tlock_mode; + dms_set_current_point set_current_point; + dms_update_node_lfn update_node_lfn; + + dms_get_db_role get_db_role; + dms_check_lrpl_takeover check_lrpl_takeover; + dms_reset_link reset_link; + dms_set_online_list set_online_list; + dms_start_lrpl start_lrpl; + dms_stop_lrpl stop_lrpl; + + // for az switchover and az failover + dms_az_switchover_demote_phase1 az_switchover_demote_phase1; + dms_az_switchover_demote_approve az_switchover_demote_approve; + dms_az_switchover_demote_phase2 az_switchover_demote_phase2; + dms_az_switchover_promote_core az_switchover_promote; + dms_az_failover_promote_phase1 az_failover_promote_phase1; + dms_az_failover_promote_resetlog az_failover_promote_resetlog; + dms_az_failover_promote_phase2 az_failover_promote_phase2; + + dms_dyn_log dyn_log; + dms_get_alock_wait_info get_alock_wait_info; + dms_check_shutdown_consistency check_shutdown_consistency; } dms_callback_t; typedef struct st_dms_instance_net_addr { @@ -1069,6 +1168,12 @@ typedef struct st_dms_instance_net_addr { unsigned char reserved[1]; } dms_instance_net_addr_t; +typedef struct dms_fi_config { + unsigned int entries[MAX_FI_ENTRY_COUNT]; + unsigned int count; + unsigned int fault_value; +} dms_fi_config_t; + typedef struct st_dms_profile { unsigned int inst_id; unsigned long long inst_map; @@ -1097,7 +1202,6 @@ typedef struct st_dms_profile { unsigned char rdma_rpc_bind_core_start; unsigned char rdma_rpc_bind_core_end; char ock_log_path[DMS_OCK_LOG_PATH_LEN]; - unsigned char enable_reform; // ock scrlock configs unsigned char enable_scrlock; unsigned int primary_inst_id; @@ -1161,8 +1265,6 @@ typedef enum en_reform_callback_stat { REFORM_CALLBACK_STAT_CKPT_LATCH = 0, REFORM_CALLBACK_STAT_BUCKET_LOCK, REFORM_CALLBACK_STAT_SS_READ_LOCK, - REFORM_CALLBACK_STAT_ENTRY_TLOCK, - REFORM_CALLBACK_STAT_PART_ENTRY_TLOCK, REFORM_CALLBACK_STAT_REBUILD_TLOCK_REMOTE, REFORM_CALLBACK_STAT_GET_DISK_LSN, REFORM_CALLBACK_STAT_DRC_EXIST, @@ -1180,26 +1282,55 @@ typedef enum en_reform_callback_stat { REFORM_CALLBACK_STAT_VALIDATE_DRC_PAGE_BUCKET_LOCK, REFORM_CALLBACK_STAT_VALIDATE_DRC_PAGE_SS_READ_LOCK, REFORM_CALLBACK_STAT_VALIDATE_DRC_PAGE_REMOTE, - REFORM_CALLBACK_STAT_VALIDATE_DRC_ENTRY_TLOCK, - REFORM_CALLBACK_STAT_VALIDATE_DRC_PART_ENTRY_TLOCK, REFORM_CALLBACK_STAT_VALIDATE_DRC_TLOCK_REMOTE, REFORM_MES_TASK_STAT_VALIDATE_LSN_GET_CTRL, REFORM_MES_TASK_STAT_VALIDATE_LSN_GET_CTRL_TIMEOUT, REFORM_MES_TASK_STAT_VALIDATE_LSN_GET_DISK_LSN, REFORM_MES_TASK_STAT_VALIDATE_LSN_BUF_UNLATCH, - + REFORM_CALLBACK_STAT_REBUILD_ALOCK_LOCAL, + REFORM_CALLBACK_STAT_REBUILD_DRC_ALOCK_REMOTE, + REFORM_CALLBACK_STAT_VALIDATE_ALOCK_LOCAL, + REFORM_CALLBACK_STAT_VALIDATE_DRC_ALOCK_REMOTE, REFORM_CALLBACK_STAT_COUNT } reform_callback_stat_e; +typedef enum e_dms_fi_type { + DMS_FI_TYPE_BEGIN = 0, + DMS_FI_TYPE_PACKET_LOSS = DMS_FI_TYPE_BEGIN, + DMS_FI_TYPE_NET_LATENCY, + DMS_FI_TYPE_CPU_LATENCY, + DMS_FI_TYPE_PROCESS_FAULT, + DMS_FI_TYPE_CUSTOM_FAULT, + DMS_FI_TYPE_END, +} dms_fi_type_e; + +struct dms_fi_entry { + int pointId; + unsigned int faultFlags; + int calledCount; + dms_fi_callback_func func; +}; + typedef struct st_dms_tlock_info { dms_drid_t resid; unsigned char lock_mode; unsigned char unused[3]; } dms_tlock_info_t; +typedef dms_tlock_info_t dms_alock_info_t; + +typedef struct thread_info { + char thread_name[DMS_MAX_NAME_LEN]; + void *thread_info; +} thread_info_t; + +typedef struct thread_set { + thread_info_t threads[MAX_DMS_THREAD_NUM]; + int thread_count; +} thread_set_t; + #ifdef __cplusplus } #endif #endif /* __DMS_H__ */ - diff --git a/src/include/ddes/dms/ss_common_attr.h b/src/include/ddes/dms/ss_common_attr.h index 40c581d15e79eee25533afa22f5a053f38c9a5ac..91b854cd3e3e3694f2d9a55454ba275491f8cc6f 100644 --- a/src/include/ddes/dms/ss_common_attr.h +++ b/src/include/ddes/dms/ss_common_attr.h @@ -33,14 +33,12 @@ #ifdef ENABLE_LITE_MODE #define ENABLE_DMS false -#define ENABLE_REFORM false #define ENABLE_VERIFY_PAGE_VERSION false #define ENABLE_SS_TXNSTATUS_CACHE false #define ENABLE_SS_BCAST_SNAPSHOT false #define SS_SINGLE_CLUSTER false #else #define ENABLE_DMS (g_instance.attr.attr_storage.dms_attr.enable_dms && !IsInitdb) -#define ENABLE_REFORM (g_instance.attr.attr_storage.dms_attr.enable_reform) #define ENABLE_VERIFY_PAGE_VERSION (g_instance.attr.attr_storage.dms_attr.enable_verify_page) #define ENABLE_SS_TXNSTATUS_CACHE (ENABLE_DMS && g_instance.attr.attr_storage.dms_attr.txnstatus_cache_size > 0) #define ENABLE_SS_BCAST_SNAPSHOT (ENABLE_DMS && g_instance.attr.attr_storage.dms_attr.enable_bcast_snapshot) @@ -138,10 +136,10 @@ #define BUF_ONDEMAND_REDO_DONE 0x1000 #define SS_BROADCAST_FAILED_RETRYCOUNTS 4 -#define SS_BROADCAST_WAIT_INFINITE (0xFFFFFFFF) -#define SS_BROADCAST_WAIT_FIVE_SECONDS (5000) -#define SS_BROADCAST_WAIT_ONE_SECOND (1000) -#define SS_BROADCAST_WAIT_FIVE_MICROSECONDS (5) +#define SS_BROADCAST_WAIT_INFINITE (0xFFFFFFFFU) +#define SS_BROADCAST_WAIT_FIVE_SECONDS (5000U) +#define SS_BROADCAST_WAIT_ONE_SECOND (1000U) +#define SS_BROADCAST_WAIT_FIVE_MICROSECONDS (5U) #define SS_ACQUIRE_LOCK_DO_NOT_WAIT 0 #define SS_ACQUIRE_LOCK_RETRY_INTERVAL (50) // 50ms diff --git a/src/include/ddes/dms/ss_dms.h b/src/include/ddes/dms/ss_dms.h index 5f4302b3ee74ccef0ba73bda7b090c77b76e3d04..1f7be0dd4d197698acb936d60c0da0b6333a2ec4 100644 --- a/src/include/ddes/dms/ss_dms.h +++ b/src/include/ddes/dms/ss_dms.h @@ -43,8 +43,7 @@ typedef struct st_ss_dms_func { void (*dms_get_error)(int *errcode, const char **errmsg); void (*dms_uninit)(void); int (*dms_request_page)(dms_context_t *dms_ctx, dms_buf_ctrl_t *ctrl, dms_lock_mode_t mode); - int (*dms_broadcast_msg)(dms_context_t *dms_ctx, char *data, unsigned int len, unsigned char handle_recv_msg, - unsigned int timeout); + int (*dms_broadcast_msg)(dms_context_t *dms_ctx, dms_broadcast_info_t *dms_broad_info); int (*dms_request_opengauss_update_xid)(dms_context_t *dms_ctx, unsigned short t_infomask, unsigned short t_infomask2, unsigned long long *uxid); int (*dms_request_opengauss_xid_csn)(dms_context_t *dms_ctx, dms_opengauss_xid_csn_t *dms_txn_info, @@ -101,8 +100,7 @@ void dms_refresh_logger(char *log_field, unsigned long long *value); void dms_get_error(int *errcode, const char **errmsg); void dms_uninit(void); int dms_request_page(dms_context_t *dms_ctx, dms_buf_ctrl_t *ctrl, dms_lock_mode_t mode); -int dms_broadcast_msg(dms_context_t *dms_ctx, char *data, unsigned int len, unsigned char handle_recv_msg, - unsigned int timeout); +int dms_broadcast_msg(dms_context_t *dms_ctx, dms_broadcast_info_t *dms_broad_info); int dms_request_opengauss_update_xid(dms_context_t *dms_ctx, unsigned short t_infomask, unsigned short t_infomask2, unsigned long long *uxid); int dms_request_opengauss_xid_csn(dms_context_t *dms_ctx, dms_opengauss_xid_csn_t *dms_txn_info, diff --git a/src/include/ddes/dms/ss_dms_bufmgr.h b/src/include/ddes/dms/ss_dms_bufmgr.h index 8c1a33ea3316121929ddd2c5e02d13f60b3de53b..c4bce2d4e55ee43fdaa83bc3733843940ba75d35 100644 --- a/src/include/ddes/dms/ss_dms_bufmgr.h +++ b/src/include/ddes/dms/ss_dms_bufmgr.h @@ -32,16 +32,6 @@ #define SS_BUF_MAX_WAIT_TIME (1000L * 1000 * 20) // 20s #define SS_BUF_WAIT_TIME_IN_ONDEMAND_REALTIME_BUILD (100000L) // 100ms -#define DmsInitLatch(drid, _type, _oid, _idx, _parent_part, _part, _uid) \ - do { \ - (drid)->type = _type; \ - (drid)->uid = _uid; \ - (drid)->oid = _oid; \ - (drid)->index = _idx; \ - (drid)->parent_part = _parent_part; \ - (drid)->part = _part; \ - } while (0) - typedef struct SSBroadcastDDLLock { SSBroadcastOp type; // must be first LOCKTAG locktag; @@ -93,7 +83,23 @@ bool SSWaitIOTimeout(BufferDesc *buf); void buftag_get_buf_info(BufferTag tag, stat_buf_info_t *buf_info); Buffer SSReadBuffer(BufferTag *tag, ReadBufferMode mode); void DmsReleaseBuffer(int buffer, bool is_seg); -bool SSRequestPageInOndemandRealtimeBuild(BufferTag *bufferTag, XLogRecPtr recordLsn, XLogRecPtr *pageLsn); bool SSOndemandRealtimeBuildAllowFlush(BufferDesc *buf); bool SSNeedTerminateRequestPageInReform(dms_buf_ctrl_t *buf_ctrl); + +inline bool SSBufferIsDirty(BufferDesc *buf_desc) +{ + uint64 state = pg_atomic_read_u64(&buf_desc->state); + // no need to judge (BM_DIRTY | BM_JUST_DIRTIED), BM_DIRTY is enough + if (state & BM_DIRTY) { +#ifdef USE_ASSERT_CHECKING + Assert((state & BM_VALID) == BM_VALID); +#endif + return true; + } + if (ENABLE_DSS_AIO && buf_desc->extra->aio_in_progress) { + return true; + } + return false; +} + #endif diff --git a/src/include/ddes/dms/ss_dms_recovery.h b/src/include/ddes/dms/ss_dms_recovery.h index d0d08a95b37cb39031c2fdf21889db07166dc81c..aa95ac8c44b1f9b056d9621a4d1f43b37a1719c0 100644 --- a/src/include/ddes/dms/ss_dms_recovery.h +++ b/src/include/ddes/dms/ss_dms_recovery.h @@ -86,6 +86,8 @@ typedef struct st_reform_info { uint64 redo_total_bytes; bool reform_success; bool is_hashmap_constructed; + TimestampTz reform_ver; + TimestampTz reform_ver_startup_wait; } ss_reform_info_t; typedef enum st_failover_ckpt_status { @@ -155,7 +157,6 @@ typedef struct ondemand_htab_ctrl { } ondemand_htab_ctrl_t; extern bool SSRecoveryNodes(); -extern void SSWaitStartupExit(); extern int SSGetPrimaryInstId(); extern void SSSavePrimaryInstId(int id); extern void SSInitReformerControlPages(void); diff --git a/src/include/ddes/dms/ss_reform_common.h b/src/include/ddes/dms/ss_reform_common.h index 891bb144380c94abf2eae26332442a9d62ffeb0c..593d75f98f4de06ef380fe8da0715a635cda2483 100644 --- a/src/include/ddes/dms/ss_reform_common.h +++ b/src/include/ddes/dms/ss_reform_common.h @@ -35,6 +35,8 @@ #define REFORM_CTRL_VERSION 1 +#define SS_RTO_LIMIT (10 * 1000 * 1000) /* 10 sec */ + typedef struct SSBroadcastCancelTrx { SSBroadcastOp type; // must be first } SSBroadcastCancelTrx; @@ -57,4 +59,6 @@ void SSDisasterUpdateHAmode(); bool SSPerformingStandbyScenario(); void SSGrantDSSWritePermission(void); bool SSPrimaryRestartScenario(); -bool SSBackendNeedExitScenario(); \ No newline at end of file +bool SSBackendNeedExitScenario(); +void SSWaitStartupExit(bool send_signal = true); +void SSHandleStartupWhenReformStart(); \ No newline at end of file diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 92dfc1e882b98067af87d21117b237e490ace3b2..ebb1489eceff02f8ec78f7b0441318df1d4c69b8 100755 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -222,7 +222,8 @@ extern void InitResultRelInfo( ResultRelInfo* resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, int instrument_options); extern ResultRelInfo* ExecGetTriggerResultRel(EState* estate, Oid relid); extern bool ExecContextForcesOids(PlanState* planstate, bool* hasoids); -extern bool ExecConstraints(ResultRelInfo* resultRelInfo, TupleTableSlot* slot, EState* estate, bool skipAutoInc = false); +extern bool ExecConstraints(ResultRelInfo* resultRelInfo, TupleTableSlot* slot, EState* estate, + bool skipAutoInc = false, bool replaceNull = false); extern void ExecWithCheckOptions(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate); extern ExecRowMark* ExecFindRowMark(EState* estate, Index rti); extern ExecAuxRowMark* ExecBuildAuxRowMark(ExecRowMark* erm, List* targetlist); @@ -642,6 +643,8 @@ static inline Datum autoinc2datum(ConstrAutoInc *cons_autoinc, int128 autoinc) extern Partition ExecOpenScanParitition( EState* estate, Relation parent, PartitionIdentifier* partID, LOCKMODE lockmode); +extern void ExecOpenUnusedIndices(ResultRelInfo* resultRelInfo, bool speculative); +extern void ExecCloseUnsedIndices(ResultRelInfo* resultRelInfo); extern void ExecOpenIndices(ResultRelInfo* resultRelInfo, bool speculative); extern void ExecCloseIndices(ResultRelInfo* resultRelInfo); extern List* ExecInsertIndexTuples( @@ -721,6 +724,14 @@ extern Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot* slot); extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone); extern int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace); +typedef bool (*replaceNullOrNotFunc)(); + +extern inline bool CheckPluginReplaceNull() +{ + return u_sess->hook_cxt.replaceNullOrNotHook != NULL ? + ((replaceNullOrNotFunc)(u_sess->hook_cxt.replaceNullOrNotHook))() : false; +} + // AutoMutexLock // Auto object for non-recursive pthread_mutex_t lock // diff --git a/src/include/executor/node/nodeModifyTable.h b/src/include/executor/node/nodeModifyTable.h index 3fe98835abbf97f35811d6a8ec71204502695d50..27b99ec4f95e721913777155907ac2b98181b007 100644 --- a/src/include/executor/node/nodeModifyTable.h +++ b/src/include/executor/node/nodeModifyTable.h @@ -50,7 +50,8 @@ extern TupleTableSlot* ExecUpdate(ItemPointer tupleid, Oid oldPartitionOid, int2 template extern TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, TupleTableSlot* planSlot, - EState* estate, bool canSetTag, int options, List** partitionList, char* partExprKeyStr = NULL); + EState* estate, bool canSetTag, int options, List** partitionList, char* partExprKeyStr = NULL, + bool replaceNull = false); template extern TupleTableSlot * ExecHBucketInsertT(ModifyTableState* state, TupleTableSlot *slot, diff --git a/src/include/executor/node/nodeSamplescan.h b/src/include/executor/node/nodeSamplescan.h index 58e02e36c75cd41da52317546b560e177029ffeb..e2d818dec3cc2061d41926f4c5cee16013956e19 100644 --- a/src/include/executor/node/nodeSamplescan.h +++ b/src/include/executor/node/nodeSamplescan.h @@ -33,9 +33,13 @@ #define NEWBLOCK 0 /* Identify we have got a new block. */ #define NONEWBLOCK 1 /* Identify we are under scanning tuple in old block. */ -#define MIN_PERCENT_ARG 0 /* Minimum value of percent. */ +#define MIN_PERCENT_ARG 0.000001 /* Minimum value of percent. */ #define MAX_PERCENT_ARG 100 /* Maxmum value of percent. */ +#define MIN_SEED_ARG 0 /* Minimum value of seed. */ +#define MAX_SEED_ARG 4294967295 /* Maxmum value of seed. */ + + /* The flag identify the tuple or block is valid or not for sample scan. */ typedef enum { VALIDDATA, NEXTDATA, INVALIDBLOCKNO, INVALIDOFFSET } ScanValid; diff --git a/src/include/knl/knl_guc/knl_instance_attr_sql.h b/src/include/knl/knl_guc/knl_instance_attr_sql.h index ff5a7626bd910cf2ecd0660a92ff5b6150dd6874..ba7c05108c7fc5c4dd7170d9c541ad4fb6b13e16 100644 --- a/src/include/knl/knl_guc/knl_instance_attr_sql.h +++ b/src/include/knl/knl_guc/knl_instance_attr_sql.h @@ -47,6 +47,7 @@ typedef struct knl_instance_attr_sql { bool enable_orc_cache; bool enable_default_cfunc_libpath; bool enableRemoteExcute; + bool plan_cache_type_validation; int udf_memory_limit; int UDFWorkerMemHardLimit; int job_queue_processes; diff --git a/src/include/knl/knl_guc/knl_instance_attr_storage.h b/src/include/knl/knl_guc/knl_instance_attr_storage.h index 96773713120009b889c0dbf4163a5ad3674d0783..b7e0d80d145e6a3b64b79b800b4505c17c2df538 100755 --- a/src/include/knl/knl_guc/knl_instance_attr_storage.h +++ b/src/include/knl/knl_guc/knl_instance_attr_storage.h @@ -111,7 +111,6 @@ typedef struct knl_instance_attr_dms { char* ock_log_path; int channel_count; int work_thread_count; - bool enable_reform; bool enable_ssl; int inst_count; bool enable_log_level; diff --git a/src/include/knl/knl_guc/knl_session_attr_storage.h b/src/include/knl/knl_guc/knl_session_attr_storage.h index ef25329b4e6b0fcdb690d2ae71483d17c2382c41..c617cd9919bdcc874a750beb51707b2f25a37aef 100755 --- a/src/include/knl/knl_guc/knl_session_attr_storage.h +++ b/src/include/knl/knl_guc/knl_session_attr_storage.h @@ -274,6 +274,7 @@ typedef struct knl_session_attr_storage { bool enable_uwal; char* uwal_path; + bool handle_toast_in_autovac; /* pre-read parms */ int heap_bulk_read_size; diff --git a/src/include/knl/knl_instance.h b/src/include/knl/knl_instance.h index aac9c7d7f19be756a55fc158ec7e860efe288cf8..a89f9d1dca73d34241352467cd205e109e1021c5 100755 --- a/src/include/knl/knl_instance.h +++ b/src/include/knl/knl_instance.h @@ -757,7 +757,7 @@ typedef struct knl_g_parallel_redo_context { char* ali_buf; XLogRedoNumStatics xlogStatics[RM_NEXT_ID][MAX_XLOG_INFO_NUM]; RedoCpuBindControl redoCpuBindcontrl; - ondemand_htab_ctrl_t **redoItemHashCtrl; /* used in ondemand extreme RTO */ + ondemand_htab_ctrl_t **redoItemHashCtrl; /* RedoItem hashmap linked list of each pipeline, used in ondemand extreme RTO */ /* extreme-rto standby read */ TransactionId exrto_recyle_xmin; XLogRecPtr global_recycle_lsn; diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index a1dc6e8cfabe5438ceb7339904c6afaa25fb2607..36b4f5d2af1fd81255bad5a4d9154e415895e9b0 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -1726,6 +1726,7 @@ typedef struct knl_u_plpgsql_context { MemoryContext depend_mem_cxt; /* temp context for build_gs_depend*/ int compile_check_node_level; int real_func_num; + HTAB* plpgsql_lock_objects; } knl_u_plpgsql_context; //this is used to define functions in package @@ -2925,6 +2926,8 @@ typedef struct knl_u_hook_context { void *typeTransfer; void *forTsdbHook; void *pluginPlannerHook; + void *groupingplannerHook; + void *replaceNullOrNotHook; } knl_u_hook_context; typedef struct knl_u_libsw_context { @@ -3159,6 +3162,7 @@ extern void set_function_style_none(); extern void set_function_style_a(); extern void set_function_style_pg(); extern bool set_is_create_plsql_type(); +extern void set_is_create_pkg_function(bool is_create_pkg_function); extern THR_LOCAL knl_session_context* u_sess; diff --git a/src/include/knl/knl_thread.h b/src/include/knl/knl_thread.h index 489ac5f690ded1ba2308e592272fc2309be02fb4..80d7ad942f8db9f3c6ec073b99f807bc5c5bfd32 100755 --- a/src/include/knl/knl_thread.h +++ b/src/include/knl/knl_thread.h @@ -800,6 +800,7 @@ typedef struct knl_t_xlog_context { int ssXlogReadFailedTimes; UwalInfo uwalInfo; List* uwalInfoHis; + XLogRecPtr uwalFileRenamePtr; } knl_t_xlog_context; typedef struct knl_t_dfs_context { diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index 35695f2825e7ea5a6ddd907b16f6997d2dea6ee0..d1023717be4baf5929f270faef675d1aea02514f 100644 --- a/src/include/libpq/pqcomm.h +++ b/src/include/libpq/pqcomm.h @@ -247,5 +247,9 @@ typedef struct StopRequestPacket { } StopRequestPacket; extern int internal_putbytes(const char* s, size_t len); +extern bool pq_disk_is_temp_file_enabled(void); +extern size_t pq_disk_write_tempfile(const void* data, size_t size); +extern void pq_set_nonblocking(bool nonblocking); +extern int internal_flush(void); #endif /* PQCOMM_H */ diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h index 22c553a2ca3ce36bdc6c2be9cf62b7214d979095..e0dfce6d22a77e67e0063ce76fcda9b7bb0e21c8 100644 --- a/src/include/mb/pg_wchar.h +++ b/src/include/mb/pg_wchar.h @@ -525,7 +525,7 @@ extern void mic2latin_with_table( extern bool pg_utf8_islegal(const unsigned char* source, int length); extern bool pg_gbk_islegal(const unsigned char* source, int length); -extern char* gs_setlocale_r(int category, const char* locale); +extern char* gs_perm_setlocale_r(int category, const char* locale); #ifndef WIN32 extern char* gs_nl_langinfo_r(nl_item item); #else diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 543f10859a30b61c5b059671eb6f51b029614e92..87029db45e671b52d58a6c1ebaac2b3478fecef0 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -141,6 +141,7 @@ extern const uint32 SPQ_VERSION_NUM; extern const uint32 UPSERT_ALIAS_VERSION_NUM; extern const uint32 SELECT_STMT_HAS_USERVAR; extern const uint32 PUBLICATION_DDL_VERSION_NUM; +extern const uint32 PRIOR_EXPR_VERSION_NUM; extern void register_backend_version(uint32 backend_version); extern bool contain_backend_version(uint32 version_number); @@ -205,7 +206,8 @@ extern bool contain_backend_version(uint32 version_number); #define OPT_ACCEPT_EMPTY_STR 134217728 #define OPT_PLPGSQL_DEPENDENCY 268435456 #define OPT_PROC_UNCHECK_DEFAULT_PARAM 536870912 -#define OPT_MAX 30 +#define OPT_UPDATE_UNUSABLE_UNIQUE_INDEX_ON_IUD 1073741824 +#define OPT_MAX 31 #define PLPSQL_OPT_FOR_LOOP 1 #define PLPSQL_OPT_OUTPARAM 2 @@ -249,6 +251,7 @@ extern bool contain_backend_version(uint32 version_number); #define SELECT_INTO_RETURN_NULL (u_sess->utils_cxt.behavior_compat_flags & OPT_SELECT_INTO_RETURN_NULL) #define PLPGSQL_DEPENDENCY (u_sess->utils_cxt.behavior_compat_flags & OPT_PLPGSQL_DEPENDENCY) #define PROC_UNCHECK_DEFAULT_PARAM (u_sess->utils_cxt.behavior_compat_flags & OPT_PROC_UNCHECK_DEFAULT_PARAM) +#define UPDATE_UNUSABLE_UNIQUE_INDEX_ON_IUD (u_sess->utils_cxt.behavior_compat_flags & OPT_UPDATE_UNUSABLE_UNIQUE_INDEX_ON_IUD) /* define database compatibility Attribute */ typedef struct { diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index ed39064727a6d9ab158aac75c4de8857395bf387..a70c4efad145d82d52f3c3abee08010d0ca92235 100755 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -593,6 +593,11 @@ typedef struct ResultRelInfo { #ifdef USE_SPQ AttrNumber ri_actionAttno; /* is this an INSERT or DELETE ? */ #endif + + /* number of the unusable index*/ + int ri_NumUnusableIndices; + RelationPtr ri_UnusableIndexRelationDescs; + IndexInfo** ri_UnusableIndexRelationInfo; } ResultRelInfo; /* bloom filter controller */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index edeed07f212b76e7e11907af159874308d63ed94..405970efec8cb06d6b600d2ec703ceb553fa7473 100755 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -282,6 +282,7 @@ typedef enum NodeTag { T_HashFilter, T_EstSPNode, T_Rownum, + T_PriorExpr, T_PseudoTargetEntry, T_PrefixKey, T_SetVariableExpr, @@ -684,6 +685,7 @@ typedef enum NodeTag { T_TIDBitmap, /* in nodes/tidbitmap.h */ T_InlineCodeBlock, /* in nodes/parsenodes.h */ T_FdwRoutine, /* in foreign/fdwapi.h */ + T_SupportRequestSimplify, /* in nodes/supportnodes.h */ T_DistFdwDataNodeTask, /* in bulkload/dist_fdw.h */ T_DistFdwFileSegment, /* in bulkload/dist_fdw.h */ diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index e7e4133c2fdb41085572683eef3a2ac8bff519fe..3690ab5ded258914cc40000b6dbef3c7053d4824 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -915,6 +915,8 @@ typedef enum AlterTableType { AT_COMMENTS, AT_InvisibleIndex, AT_VisibleIndex, + AT_InvisibleIndexDirect, + AT_VisibleIndexDirect, AT_ModifyColumn, AT_SetCharsetCollate, AT_ConvertCharset, diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index e46b92f6f3487cf20538816b58493705db1f21c9..458b47c05e299d188bdd7ac823ae98213bc7f070 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -370,6 +370,12 @@ typedef struct Rownum { Oid rownumcollid; /* OID of collation of result */ int location; /* token location, or -1 if unknown */ } Rownum; + +typedef struct PriorExpr { + Expr xpr; + Node *node; +} PriorExpr; + /* ---------------- * ArrayRef: describes an array subscripting operation * diff --git a/src/include/nodes/supportnodes.h b/src/include/nodes/supportnodes.h new file mode 100644 index 0000000000000000000000000000000000000000..1f7d02b5ee2637419882580ae76d207477875761 --- /dev/null +++ b/src/include/nodes/supportnodes.h @@ -0,0 +1,70 @@ +/*------------------------------------------------------------------------- + * + * supportnodes.h + * Definitions for planner support functions. + * + * This file defines the API for "planner support functions", which + * are SQL functions (normally written in C) that can be attached to + * another "target" function to give the system additional knowledge + * about the target function. All the current capabilities have to do + * with planning queries that use the target function, though it is + * possible that future extensions will add functionality to be invoked + * by the parser or executor. + * + * A support function must have the SQL signature + * supportfn(internal) returns internal + * The argument is a pointer to one of the Node types defined in this file. + * The result is usually also a Node pointer, though its type depends on + * which capability is being invoked. In all cases, a NULL pointer result + * (that's PG_RETURN_POINTER(NULL), not PG_RETURN_NULL()) indicates that + * the support function cannot do anything useful for the given request. + * Support functions must return a NULL pointer, not fail, if they do not + * recognize the request node type or cannot handle the given case; this + * allows for future extensions of the set of request cases. + * + * + * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/nodes/supportnodes.h + * + *------------------------------------------------------------------------- + */ +#ifndef SUPPORTNODES_H +#define SUPPORTNODES_H + +#include "nodes/primnodes.h" + +struct PlannerInfo; /* avoid including relation.h here */ + + +/* + * The Simplify request allows the support function to perform plan-time + * simplification of a call to its target function. For example, a varchar + * length coercion that does not decrease the allowed length of its argument + * could be replaced by a RelabelType node, or "x + 0" could be replaced by + * "x". This is invoked during the planner's constant-folding pass, so the + * function's arguments can be presumed already simplified. + * + * The planner's PlannerInfo "root" is typically not needed, but can be + * consulted if it's necessary to obtain info about Vars present in + * the given node tree. Beware that root could be NULL in some usages. + * + * "fcall" will be a FuncExpr invoking the support function's target + * function. (This is true even if the original parsetree node was an + * operator call; a FuncExpr is synthesized for this purpose.) + * + * The result should be a semantically-equivalent transformed node tree, + * or NULL if no simplification could be performed. Do *not* return or + * modify *fcall, as it isn't really a separately allocated Node. But + * it's okay to use fcall->args, or parts of it, in the result tree. + */ +typedef struct SupportRequestSimplify +{ + NodeTag type; + + struct PlannerInfo *root; /* Planner's infrastructure */ + FuncExpr *fcall; /* Function call to be simplified */ +} SupportRequestSimplify; + +#endif /* SUPPORTNODES_H */ diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 3dbf6a5c346abd2042eff428de8e92fd2f17b5ef..e1fe18cdf7d29c3270b769a1a7a843563d71565f 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -33,7 +33,7 @@ typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root, List *restrictlist); extern THR_LOCAL PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook; -extern RelOptInfo* make_one_rel(PlannerInfo* root, List* joinlist); +extern RelOptInfo* make_one_rel(PlannerInfo* root, List* joinlist, Relids non_keypreserved = NULL); extern RelOptInfo* standard_join_search(PlannerInfo* root, int levels_needed, List* initial_rels); extern void set_base_rel_sizes(PlannerInfo* root, bool onlyRelatinalTable = false); diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 733a6b3c6b9777e19334e93f1517b0d518e9341c..a79d8df0d434c2ceb9b5ffd918917106b904019f 100755 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -158,7 +158,7 @@ extern void add_vars_to_targetlist(PlannerInfo* root, List* vars, Relids where_n extern void find_lateral_references(PlannerInfo *root); extern void create_lateral_join_info(PlannerInfo *root); extern void add_lateral_info(PlannerInfo *root, Index rhs, Relids lhs); -extern List* deconstruct_jointree(PlannerInfo* root); +extern List* deconstruct_jointree(PlannerInfo* root, Relids* non_keypreserved = NULL); extern void distribute_restrictinfo_to_rels(PlannerInfo* root, RestrictInfo* restrictinfo); extern void process_security_clause_appendrel(PlannerInfo *root); extern void process_implied_equality(PlannerInfo* root, Oid opno, Oid collation, Expr* item1, Expr* item2, diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h index 6d9ef53e1a364ff4f4dfa2fc81e7f605dac64461..b613082a46188f6ebea0eedd68dd07d5ff299d51 100644 --- a/src/include/optimizer/planner.h +++ b/src/include/optimizer/planner.h @@ -52,6 +52,7 @@ typedef struct { extern ExecNodes* getExecNodesByGroupName(const char* gname); extern PlannedStmt* planner(Query* parse, int cursorOptions, ParamListInfo boundParams); extern PlannedStmt* standard_planner(Query* parse, int cursorOptions, ParamListInfo boundParams); +extern Plan* grouping_planner(PlannerInfo* root, double tuple_fraction); typedef PlannedStmt* (*planner_hook_type) (Query* parse, int cursorOptions, ParamListInfo boundParams); typedef List* (*for_tsdb_hook_type) (PlannerInfo *root,RelOptInfo *rel, @@ -68,6 +69,8 @@ typedef PlannedStmt *(*spq_planner_hook_type) (Query* parse, int cursorOptions, extern THR_LOCAL PGDLLIMPORT spq_planner_hook_type spq_planner_hook; #endif +typedef Plan* (*grouping_plannerFunc)(PlannerInfo* root, double tuple_fraction); + extern Plan* subquery_planner(PlannerGlobal* glob, Query* parse, PlannerInfo* parent_root, bool hasRecursion, double tuple_fraction, PlannerInfo** subroot, int options = SUBQUERY_NORMAL, ItstDisKey* diskeys = NULL, List* subqueryRestrictInfo = NIL); diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index 238dae3993f4c0bb65918330f133c0b6807a9176..8cc76d838d74cce7c643e2c025abb845a3892f01 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -53,7 +53,8 @@ extern ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte, bool lateral_on * StartWith support transformStartWith() is the only entry point for START WITH...CONNECT BY * processing in parser/transformar layer */ -extern void transformStartWith(ParseState *pstate, SelectStmt *stmt, Query *qry); +extern void transformStartWith(ParseState *pstate, ParseState *origin_pstate, SelectStmt *stmt, + SelectStmt *origin_stmt, Query *qry, bool is_first_node, bool is_creat_view); extern void AddStartWithCTEPseudoReturnColumns(CommonTableExpr *cte, RangeTblEntry *rte, Index rte_index); extern void pretransformAggWithUserSet(ParseState* pstate, List** targetList, Node* groupClause, ParseExprKind exprKind); diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 45cca960cc5d903329c709155c4d3ee758f3c0a7..ca831d37a657b68b0d2e8fbb9cf83ddca317470b 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -196,6 +196,7 @@ struct ParseState { List *sw_fromClause; WithClause *origin_with; bool p_hasStartWith; + bool p_split_where_for_swcb; bool p_has_ignore; /* whether SQL has ignore hint */ /* diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h index 140c957ae26711277a0d1d9890131caf3883befa..9e18e08d52a1e4b6d00a536fa4b451cdcb58c15a 100755 --- a/src/include/replication/walreceiver.h +++ b/src/include/replication/walreceiver.h @@ -238,8 +238,9 @@ typedef struct WalRcvData { Latch* walrcvWriterLatch; WalRcvCtlBlock* walRcvCtlBlock; - UwalrcvWriterState* uwalRcvState; slock_t mutex; /* locks shared variables shown above */ + UwalrcvWriterState* uwalRcvState; + slock_t uwalMutex; /* lock uwal state */ slock_t exitLock; char recoveryTargetBarrierId[MAX_BARRIER_ID_LENGTH]; char recoveryStopBarrierId[MAX_BARRIER_ID_LENGTH]; @@ -353,6 +354,7 @@ extern void XLogWalRecordsPreProcess(char **buf, Size *len, WalDataMessageHeader extern int XLogDecompression(const char *buf, Size len, XLogRecPtr dataStart); void GetPasswordForHadrStreamingReplication(char user[], char password[]); extern char* remove_ipv6_zone(char* addr_src, char* addr_dest, int len); +extern void MoveUwalFile(void); static inline void WalRcvCtlAcquireExitLock(void) { diff --git a/src/include/storage/gs_uwal/gs_uwal.h b/src/include/storage/gs_uwal/gs_uwal.h index bd48adce541a636e4b23b820dab97b1aa3dbe156..13ab36c764131dd1a5b806bedcf13a10cff48bc9 100644 --- a/src/include/storage/gs_uwal/gs_uwal.h +++ b/src/include/storage/gs_uwal/gs_uwal.h @@ -63,17 +63,19 @@ typedef struct { int opCount; int curCount; int ret; - UwalNodeInfo *infos; bool interrupted; int interruptCount; -} UwalAsyncAppendCbCtx; +} UwalAsynCommonCbCtx; typedef struct { - UwalAsyncAppendCbCtx *commonCbCtx; UwalNodeInfo *infos; int ret; - UwalAppendParam *appendParam; -} UwalSingleAsyncCbCtx; + uint64_t writeOffset; + uint64_t writeLen; + int index; + bool processed; + char *buf; +} UwalAsyncCbCtx; typedef struct { int id; @@ -120,16 +122,22 @@ int GsUwalStandbyInitNotify(); /** * called after uwal append * @param lsn write log success lsn - * @param infos uwalAppend() return UwalNodeInfo */ -void GsUwalUpdateSenderSyncLsn(XLogRecPtr lsn, UwalNodeInfo *infos); +void GsUwalUpdateSenderSyncLsn(XLogRecPtr lsn); +UwalVector *GsUwalGetInitInfo(); int GsUwalQueryByUser(TimeLineID ThisTimeLineID, bool needHistoryList = true); int GsUwalQuery(UwalId *id, UwalBaseInfo *info); int GsUwalCreate(uint64_t startOffset); int GsUwalRead(UwalId *id, XLogRecPtr targetPagePtr, char *readBuf, uint64_t readlen); -int GsUwalWrite(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos); +int GsUwalWriteResHandle(int ret, int nBytes, char *buf, UwalNodeInfo *infos, uint64_t targetOffset); +int GsUwalWrite(int nBytes, char *buf, uint64_t writeOffset); +int GsUwalWriteSync(int nBytes, char *buf, UwalNodeInfo *infos, bool specified = false, uint64_t targetOffset = 0); void GsUwalWriteAsyncCallBack(void *cbCtx, int retCode); -int GsUwalWriteAsync(UwalId *id, int nBytes, char *buf, UwalNodeInfo *infos); +int GsUwalWriteAsync(int nBytes, char *buf, uint64_t targetOffset); int GsUwalTruncate(UwalId *id, uint64_t offset); +void GsUwalRenewFileRenamePtr(); +bool GsUwalCheckFileRename(XLogRecPtr targetPtr); +int GsUwalRewind(UwalId *id, uint64_t offset); +bool GsUwalCheckLocalRes(UwalNodeInfo *infos); #endif \ No newline at end of file diff --git a/src/include/storage/gs_uwal/gs_uwal_adaptor.h b/src/include/storage/gs_uwal/gs_uwal_adaptor.h index 377f653341258e4a279acf91f377efa70fd223df..fcb3c93fc2a14ee7329f22ed7fe85a8dec5696ad 100644 --- a/src/include/storage/gs_uwal/gs_uwal_adaptor.h +++ b/src/include/storage/gs_uwal/gs_uwal_adaptor.h @@ -40,6 +40,8 @@ int ock_uwal_delete(IN UwalDeleteParam *param); int ock_uwal_append(IN UwalAppendParam *param, OUT uint64_t *offset, OUT void* result); +int ock_uwal_append_with_offset(IN UwalAppendParam *param, IN uint64_t targetOffset, OUT uint64_t *offset, OUT void* result); + int ock_uwal_read(IN UwalReadParam *param, OUT UwalBufferList *bufferList); int ock_uwal_truncate(IN const UwalId *uwalId, IN uint64_t offset); diff --git a/src/include/storage/gs_uwal/uwal.h b/src/include/storage/gs_uwal/uwal.h index 8fcc5a1a39f734559007bd2eafb68fb4884816b0..ca2e3bb3202fdcb7fc3fa767e703c337567f0b0e 100644 --- a/src/include/storage/gs_uwal/uwal.h +++ b/src/include/storage/gs_uwal/uwal.h @@ -341,6 +341,9 @@ typedef int (*UwalDelete)(IN UwalDeleteParam *param); typedef int (*UwalAppend)(IN UwalAppendParam *param, OUT uint64_t *offset, OUT void* result); +typedef int (*UwalAppendWithOffset)(IN UwalAppendParam *param, IN uint64_t targetOffset, + OUT uint64_t *offset, OUT void* result); + typedef int (*UwalRead)(IN UwalReadParam *param, OUT UwalBufferList *bufferList); typedef int (*UwalTruncate)(IN const UwalId *uwalId, IN uint64_t offset); diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index e3343e18fe98b576eaca2b80fa2f1203b891c0f1..f883657a1eddbd09f6779ce509ad79151cbbfc27 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -79,8 +79,6 @@ extern void cancel_shmem_exit(pg_on_exit_callback function, Datum arg); extern void on_exit_reset(void); /* ipci.c */ -extern pthread_mutex_t gLocaleMutex; - extern void CreateSharedMemoryAndSemaphores(bool makePrivate, int port); extern void cancelShmemExit(pg_on_exit_callback function, Datum arg); diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h index 929ed2bd558df85b1636a4142af33f1dba7bcd86..31d9d3f8934b9219ab52d47f9f7d092dfa4198ed 100644 --- a/src/include/storage/lmgr.h +++ b/src/include/storage/lmgr.h @@ -116,4 +116,14 @@ extern bool ConditionalLockCStoreFreeSpace(Relation relation); extern void UnlockCStoreFreeSpace(Relation relation); extern const char* GetLockNameFromTagType(uint16 locktag_type); +extern void LockProcedureIdForSession(Oid procId, Oid dbId, LOCKMODE lockmode); +extern void UnlockProcedureIdForSession(Oid procId, Oid dbId, LOCKMODE lockmode); +extern void LockPackageIdForSession(Oid packageId, Oid dbId, LOCKMODE lockmode); +extern void UnlockPackageIdForSession(Oid packageId, Oid dbId, LOCKMODE lockmode); + +extern void LockProcedureIdForXact(Oid procId, Oid dbId, LOCKMODE lockmode); +extern void UnlockProcedureIdForXact(Oid procId, Oid dbId, LOCKMODE lockmode); +extern void LockPackageIdForXact(Oid packageId, Oid dbId, LOCKMODE lockmode); +extern void UnlockPackageIdForXact(Oid packageId, Oid dbId, LOCKMODE lockmode); + #endif /* LMGR_H */ diff --git a/src/include/storage/lock/lock.h b/src/include/storage/lock/lock.h index 8bebfefaa59febb0ccbdfa9226bdb365093014f9..26df9f19eae9815c3dc0753df1667da13c112ceb 100644 --- a/src/include/storage/lock/lock.h +++ b/src/include/storage/lock/lock.h @@ -335,6 +335,26 @@ typedef struct LOCKTAG { (locktag).locktag_type = LOCKTAG_CSTORE_FREESPACE, \ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) +#define PackageRelationId 7815 +#define SET_LOCKTAG_PKG_OBJECT(locktag, dboid, objoid) \ + ((locktag).locktag_field1 = (dboid), \ + (locktag).locktag_field2 = (PackageRelationId), \ + (locktag).locktag_field3 = (objoid), \ + (locktag).locktag_field4 = 0, \ + (locktag).locktag_field5 = 0, \ + (locktag).locktag_type = LOCKTAG_OBJECT, \ + (locktag).locktag_lockmethodid = USER_LOCKMETHOD) + +#define ProcedureRelationId 1255 +#define SET_LOCKTAG_PROC_OBJECT(locktag, dboid, objoid) \ + ((locktag).locktag_field1 = (dboid), \ + (locktag).locktag_field2 = (ProcedureRelationId), \ + (locktag).locktag_field3 = objoid, \ + (locktag).locktag_field4 = 0, \ + (locktag).locktag_field5 = 0, \ + (locktag).locktag_type = LOCKTAG_OBJECT, \ + (locktag).locktag_lockmethodid = USER_LOCKMETHOD) + /* * Per-locked-object lock information: * diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index c89b117c23e903bd592432f26d5750b378668e91..6ea6633ac57e76c91bb9d1af9a3bee4ec103ef52 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -463,8 +463,10 @@ extern int16 pg_strtoint16(const char* s, bool can_ignore = false); extern int32 pg_strtoint32(const char* s, bool can_ignore); extern void pg_itoa(int16 i, char* a); extern void pg_ltoa(int32 l, char* a); +extern char* pg_ltoa_printtup(int32 l, int* len); extern void pg_ctoa(uint8 i, char* a); extern void pg_lltoa(int64 ll, char* a); +extern char* pg_lltoa_printtup(int64 ll, int* len); extern void pg_i128toa(int128 value, char* a, int length); /* @@ -992,7 +994,7 @@ extern Datum varcharrecv(PG_FUNCTION_ARGS); extern Datum varcharsend(PG_FUNCTION_ARGS); extern Datum varchartypmodin(PG_FUNCTION_ARGS); extern Datum varchartypmodout(PG_FUNCTION_ARGS); -extern Datum varchar_transform(PG_FUNCTION_ARGS); +extern Datum varchar_support(PG_FUNCTION_ARGS); extern Datum varchar(PG_FUNCTION_ARGS); extern Datum opfusion_varchar(Datum arg1, Datum arg2, Datum arg3); @@ -1011,9 +1013,6 @@ extern bytea *cstring_to_bytea_with_len(const char *s, int len); extern BpChar* cstring_to_bpchar_with_len(const char* s, int len); extern char* text_to_cstring(const text* t); extern char* output_text_to_cstring(const text* t); -extern char* output_int32_to_cstring(int32 value); -extern char* output_int64_to_cstring(int64 value); -extern char* output_int128_to_cstring(int128 value); extern char* output_date_out(int32 date); extern void text_to_cstring_buffer(const text* src, char* dst, size_t dst_len); extern int text_instr_3args(text* textStr, text* textStrToSearch, int32 beginIndex); @@ -1317,7 +1316,7 @@ extern Datum numeric_recv(PG_FUNCTION_ARGS); extern Datum numeric_send(PG_FUNCTION_ARGS); extern Datum numerictypmodin(PG_FUNCTION_ARGS); extern Datum numerictypmodout(PG_FUNCTION_ARGS); -extern Datum numeric_transform(PG_FUNCTION_ARGS); +extern Datum numeric_support(PG_FUNCTION_ARGS); extern Datum numeric(PG_FUNCTION_ARGS); extern Datum numeric_abs(PG_FUNCTION_ARGS); extern Datum numeric_uminus(PG_FUNCTION_ARGS); diff --git a/src/include/utils/date.h b/src/include/utils/date.h index e7db0304e2275e4dc5356978b95ab23ca6378a04..c9fa0e6e11d76ac596cb9542919bb530fc805264 100644 --- a/src/include/utils/date.h +++ b/src/include/utils/date.h @@ -162,7 +162,7 @@ extern Datum time_recv(PG_FUNCTION_ARGS); extern Datum time_send(PG_FUNCTION_ARGS); extern Datum timetypmodin(PG_FUNCTION_ARGS); extern Datum timetypmodout(PG_FUNCTION_ARGS); -extern Datum time_transform(PG_FUNCTION_ARGS); +extern Datum time_support(PG_FUNCTION_ARGS); extern Datum time_scale(PG_FUNCTION_ARGS); extern Datum time_eq(PG_FUNCTION_ARGS); extern Datum time_ne(PG_FUNCTION_ARGS); diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index 1af97ebb82397a16b3757fdac6b18ef7097765f8..82cf22817f7cdc5b020fa3bbb024f05713f90ba6 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -294,7 +294,7 @@ extern int DecodeUnits(int field, const char* lowtoken, int* val); extern int j2day(int jd); -extern Node* TemporalTransform(int32 max_precis, Node* node); +extern Node *TemporalSimplify(int32 max_precis, Node *node); extern bool CheckDateTokenTables(void); diff --git a/src/include/utils/fmgrtab.h b/src/include/utils/fmgrtab.h index 39a7dd0d185e6e4b820c2598aa9f043bdad1d53f..3662b7280145f6d928ec2ae328170a9bfae15c70 100644 --- a/src/include/utils/fmgrtab.h +++ b/src/include/utils/fmgrtab.h @@ -53,7 +53,7 @@ typedef struct { float4 procost; /* [10] estimated execution cost */ float4 prorows; /* [11] estimated # of rows out (if proretset) */ Oid provariadic; /* [12] element type of variadic array, or 0 */ - regproc protransform; /* [13] transforms calls to it during planning */ + regproc protransform; /* [13] planner support function for this function */ bool proisagg; /* [14] is it an aggregate? */ bool proiswindow; /* [15] is it a window function? */ bool prosecdef; /* [16] security definer */ diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index ac85dbfcc66f018160b958829021c7b065bc659c..dacf02821c2ab7db6800678b54b4d94e112aeef6 100755 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -474,6 +474,10 @@ typedef enum { g_instance.shmem_cxt.numaNodeNum <= PARTITION_OPFUSION_MAX_NUMA_NODE && \ !g_instance.attr.attr_common.enable_global_syscache) +/* Wrapper macro for forced plan cache result type check */ +#define FORCE_VALIDATE_PLANCACHE_RESULT \ + ((bool)g_instance.attr.attr_sql.plan_cache_type_validation) + typedef enum { SUMMARY = 0, /* not collect multi column statistics info */ DETAIL = 1, /* collect multi column statistics info */ diff --git a/src/include/utils/plpgsql.h b/src/include/utils/plpgsql.h index adc2e379e34e2c686b938e9fdd748bcc00fc849b..06442c7ecd069c07b20091d477fde9a8d94fabb5 100644 --- a/src/include/utils/plpgsql.h +++ b/src/include/utils/plpgsql.h @@ -34,6 +34,7 @@ #define TABLEOFINDEXBUCKETNUM 128 #define MAX_INT32_LEN 11 +#define GSPLSQL_LOCKED_HTAB_SIZE 128 /* * Compile status mark @@ -1145,6 +1146,7 @@ typedef struct FuncInvalItem { NodeTag type; int cacheId; /* a syscache ID, see utils/syscache.h */ Oid objId; + Oid dbId; } FuncInvalItem; typedef struct PLpgSQL_function { /* Complete compiled function */ @@ -2114,4 +2116,26 @@ extern void compute_return_type( extern CodeLine* debug_show_code_worker(Oid funcid, uint32* num, int* headerlines); void plpgsql_free_override_stack(int depth); +/* gsplsql lock/unlock api */ +typedef struct GSPLSQLLockedObjKey { + uint32 isPkg; /* 1 is pkg, 0 is func */ + Oid objId; + Oid dbId; +} GSPLSQLLockedObj; + +typedef struct GSPLSQLLockedObjEntry { + GSPLSQLLockedObj key; + bool has_locked; +} GSPLSQLLockedObjEntry; + +typedef enum { + PLSQL_UNKNOW_OBJ, + PLSQL_FUNCTION_OBJ, + PLSQL_PACKAGE_OBJ, +} GSPLSQLObjectType; + +extern void init_lock_hash_table(); +extern void gsplsql_lock_func_pkg_dependency_all(Oid obj_oid, GSPLSQLObjectType type); +extern void gsplsql_unlock_func_pkg_dependency_all(); +extern void gsplsql_lock_depend_pkg_on_session(PLpgSQL_function* func); #endif /* PLPGSQL_H */ diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index 43ae39fa0ff8de6ee7ac17de6a2dedb5176f3df2..ee51492b9f509716924872ad83ca4b4862fd6660 100644 --- a/src/include/utils/timestamp.h +++ b/src/include/utils/timestamp.h @@ -135,7 +135,7 @@ extern Datum timestamp_recv(PG_FUNCTION_ARGS); extern Datum timestamp_send(PG_FUNCTION_ARGS); extern Datum timestamptypmodin(PG_FUNCTION_ARGS); extern Datum timestamptypmodout(PG_FUNCTION_ARGS); -extern Datum timestamp_transform(PG_FUNCTION_ARGS); +extern Datum timestamp_support(PG_FUNCTION_ARGS); extern Datum timestamp_scale(PG_FUNCTION_ARGS); extern Datum timestamp_eq(PG_FUNCTION_ARGS); extern Datum timestamp_ne(PG_FUNCTION_ARGS); @@ -177,7 +177,7 @@ extern Datum interval_recv(PG_FUNCTION_ARGS); extern Datum interval_send(PG_FUNCTION_ARGS); extern Datum intervaltypmodin(PG_FUNCTION_ARGS); extern Datum intervaltypmodout(PG_FUNCTION_ARGS); -extern Datum interval_transform(PG_FUNCTION_ARGS); +extern Datum interval_support(PG_FUNCTION_ARGS); extern Datum interval_scale(PG_FUNCTION_ARGS); extern Datum interval_eq_withhead(PG_FUNCTION_ARGS); extern Datum interval_eq(PG_FUNCTION_ARGS); diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h index 047750b13cf5028d812d028c2378bcadfc839113..d05b291cbb53f3696f1acb923bf48b28a91ae38a 100644 --- a/src/include/utils/varbit.h +++ b/src/include/utils/varbit.h @@ -75,7 +75,7 @@ extern Datum varbit_send(PG_FUNCTION_ARGS); extern Datum varbittypmodin(PG_FUNCTION_ARGS); extern Datum varbittypmodout(PG_FUNCTION_ARGS); extern Datum bit(PG_FUNCTION_ARGS); -extern Datum varbit_transform(PG_FUNCTION_ARGS); +extern Datum varbit_support(PG_FUNCTION_ARGS); extern Datum varbit(PG_FUNCTION_ARGS); extern Datum biteq(PG_FUNCTION_ARGS); extern Datum bitne(PG_FUNCTION_ARGS); diff --git a/src/lib/page_compression/PageCompression.cpp b/src/lib/page_compression/PageCompression.cpp index 620704bd0c6195ce9276beb73026ad5cb049c07b..ef5be9520778a54d8955713a9395081986a20ced 100644 --- a/src/lib/page_compression/PageCompression.cpp +++ b/src/lib/page_compression/PageCompression.cpp @@ -310,16 +310,16 @@ size_t CalRealWriteSize(char *buffer) uint8 pagetype = PageGetPageLayoutVersion(buffer); if (pagetype == PG_UHEAP_PAGE_LAYOUT_VERSION) { UHeapPageCompressData *heapPageData = (UHeapPageCompressData *)(void *)buffer; - compressedBufferSize = heapPageData->size + offsetof(UHeapPageCompressData, data); + compressedBufferSize = heapPageData->size; } else if (pagetype == PG_HEAP_PAGE_LAYOUT_VERSION) { HeapPageCompressData *heapPageData = (HeapPageCompressData *)(void *)buffer; - compressedBufferSize = heapPageData->size + offsetof(HeapPageCompressData, data); + compressedBufferSize = heapPageData->size; } else { PageCompressData *heapPageData = (PageCompressData *)(void *)buffer; - compressedBufferSize = heapPageData->size + offsetof(PageCompressData, data); + compressedBufferSize = heapPageData->size; } - - return compressedBufferSize; + auto allDataSize = GetSizeOfCprsHeadData(pagetype) + compressedBufferSize; + return allDataSize; } inline void PunchHoleForCnmpExt(CfsExtentHeader *pcaHead, BlockNumber extNo, FILE *destFd) diff --git a/src/test/regress/data/gin_data_1000.txt b/src/test/regress/data/gin_data_1000.txt index f9c244b28a1f14885a9ad2a0f7b8d4fec6b25b8f..5de6c8d8dd2b31e581a41b5de3b0c9c52d09f837 100644 --- a/src/test/regress/data/gin_data_1000.txt +++ b/src/test/regress/data/gin_data_1000.txt @@ -1,1000 +1,1000 @@ -1 云TJ7JAR 417998195308177305 在苏文五岁的时 -2 皖U0C0VK 136193196409169234 苏文住的门前种着紫藤 -3 赣CO3DUR 120857193709249016 而不幸的 -4 冀LZZJ33 359992199611170811 当初如果不是你想要儿子,我怎么会生下他?你养他是理所当然的!那是母亲的叫声。 -5 鄂J891XL 335202195909299877 我忙生意都来不及了,怎么可能会想要这样的麻烦!是你妈要你生的吧,不要把责任推到我头上来!那个 -6 京JIROB5 520625200411274293 母亲摔了一个花瓶,婚是离定了!儿子你养!我不可能带着一个拖油瓶的 -7 藏MH1423 121734198902281048 随后紧跟着的是父亲砸烂椅子的 -8 藏FHHPWN 349462195707280120 ……,… -9 吉AVCM6I 655259198701094191 接下来的争吵话语苏文没有听到,他只看到他面前的门似乎朝着他扑过来,张牙舞爪般的,他盯着那门好长时间,然后,他 -10 粤OHUJF1 469762197308069007 苏文跟着父亲的时候,因为男人总是不会注意理家,国小的苏文的衬衫没有干净过,他的饭盒总是空的,在苏文十岁的时候,父亲遭遇车祸死掉了,苏文跟着母亲生活,然而苏文的衣服破了,破洞一 -11 闽XKM3DY 430775193709060034 苏文的少年时期非常贫瘠苍白,青年时期也非常的贫瘠苍白,那时候的生活在苏文的记忆里都是灰蒙蒙的一片,没有一 -12 川LYX0J6 812863198208211357 苏文的人生,就如同一条水平的线,本来一直毫无生机地在延续着,然而就在 -13 赣EW3022 537116199905116863 为那个小孩子洗澡 -14 晋FDOOTW 346830193806051938 这与常情背道而驰的现象,似乎预示着苏文的一生都将 -15 鄂LTQRQY 653469194004185293 而第二天的苏文却鬼迷心窍般地继续回到那个幼稚园,那个年轻的老师同样的把苏文当成了这个学校的教师,同样的热情招呼他,同样的毫不客气地让苏文帮忙。也许是认识了苏文,昨天还在他手下吵闹个不停的小男生不再闹了 -16 浙TV2471 339805195010315221 在一个破旧的无人经过的小巷里,那属于孩童的酸甜的气息、稚气而尖锐的哭闹声、不断踢打的四肢以及那小男孩身下流出 -17 琼FIAK8R 123854201109130103 那一天后,苏文就再也没有去过那个幼稚园。他也不知道那个被他强暴小男 -18 浙G9STVC 216692200406195070 而后,高考的成绩下来,苏文考入M -19 鄂KD71K0 426204197912250543 第 -20 京WIC0HS 133899195202112063 < -21 鄂LM8HMY 211787199202013640 九 -22 湘RI4O21 817549196601074600 M大校园里,来来往往的都 -23 赣F9NMH3 650843196707134974 走过校园的紫藤架的时候,苏文被人喊住了。那是跟他同个组的何教授,与他同一届进入M大,也 -24 苏EUJWE8 146470193503053826 苏文望着那有些枯了的紫藤架,想着每年的春天,这恼人的紫 -25 云QHQYMI 632710194312307885 何教授显然的没有对这些花花草草投以多大的注意,他的注意力集中在要与苏文讲的话上,“苏教授,你知 -26 闽PKKRQ7 450873196401200187 “是啊。”苏文应着,漫不经心的,他一向不喜欢与人多谈,尤其是这个多舌的何教授。在M大物理组这么多教授中, -27 云IGXYGP 119751194102222290 “哎,我跟你谈什么,你根本就不用担心,在学校的评审制度中,你的分数是很高的,你在学生当中有人缘嘛,可是我就 -28 沪E7MM1P 238413197009079622 “说说看,你到底是用了什么法子让学生给你评那么高的分的?”袖子被人拉扯,苏文才从自己的沉思中回过神来, -29 晋JY7QMF 810449200101021380 “……”苏 -30 川VT2OXP 448552200705160408 何教授热切的目光一下子黯淡下去,“哎,看你就是一副笨笨的样子,为什么会这么的得学生的喜欢呢?难道是像数学系的那个陈教授一样,请学生去凯悦大吃一顿?又没有 -31 沪HCHFWC 505245201003190683 何教授持续着他的自言自语,在他的感觉中,身边的苏文不知何时离开的,他并不知道也并不会在意,因为苏文在校园里,除了最后考评中学生给他的评分稍微高 -32 吉PVIU9Z 213016201108118688 大学同学四年加上同事十二年,苏文 -33 琼H3QIAQ 349283194108179958 ******** -34 辽V1NS6F 310757199902128085 离开何教授,苏文走入物理系的大楼,今天是开学的第一天,大一新生 -35 琼VO2TMQ 310551194406296360 走进可容纳三百人的教室,教室里一如以往的闹哄哄,上课时间还没到,学生们进进出出,打电话的闲聊的,三三两两,苏文走到讲台上把书放下,站了一会儿,抬腕看看时间,离上课还有五分钟,自己也觉得有些无聊,于是走 -36 吉Z9104V 323409196704245055 阳台上的风有些微凉,苏文靠在阳台上,凝望着楼下的草坪,思绪空空荡荡的 -37 京JT9MGY 121643194907019150 离苏文两米远左右的地方有个学生看起来像是对女朋友讲电话,风把他的声音传过来,“……我在302教室啦……人很多啊,听说这个老师对学生一点 -38 冀AV4FMA 523326195410211814 苏文不由得 -39 新A4A6QN 360885198608185876 再看看时 -40 沪CFFOS8 613899198604290354 洗手间在走廊的一侧,要去那儿,就必定要转个小弯 -41 皖G6SQMO 350612198211128134 猛然间,一个迎面冲过来的学生的肩膀撞到了苏文的身体 -42 沪H2A2HV 451682197302015123 “对不 -43 贵Q29MJF 631477199503267207 “老师?”为什么这位老师的模样像是被雷霹到一般 -44 新PVGQE7 159327198712132083 “不!不是我!不是我!”回应他的,是苏文慌乱的回答和粗鲁的推开他的动作,藤帆被他鲁莽的动作推到墙上,肩膀撞到墙壁,生疼,他吃痛地摸 -45 琼OI3SS1 344991194804085987 “奇怪的老师。”藤帆摸摸肩膀,还有些疼,虽然一开始是他不小心撞到他的,可是也不必这样粗暴地推他吧,“可是为什么看起 -46 闽T4GLIU 543277193511249273 藤 -47 豫DS64OP 115117200808179656 < -48 湘NKG81G 333447196311277534 每一颗紫藤 -49 渝UULMGW 516042196510022249 虽然水有时候太过少,有时候没有阳光,有时候落在没有土壤的地方,然而种子不会永久地沉默下去的,只要一接触到合适的生长环境,它就会 -50 青CCSND9 325682195604186793 “哗——”澄澈透明的水扑到脸上,冰凉,苏文抬起头来,镜子里的他脸孔湿润润的,脸色苍白,嘴唇没有一丝血色,眼睛里全是惊恐 -51 晋L3CH6X 500319199311119051 是他,是 -52 云IBUEIN 157220195809100484 他果然没 -53 湘HXA61R 154730194606222046 果然,他跟到这 -54 豫EEVNQI 416368195907118875 就如同冥冥之中有一只手在划拨着每个人的命运一般,苏文的命运之轮在他高考之后的那个寒假开始转动,轰隆隆的转动辗碎了他生命中所有的东西,那些东西或者是上天安排的,或者是苏文自己故意设置的,然而这些反抗的力 -55 桂RI9VDV 153723195305121081 即使 -56 津DVPPQB 440209196207108386 怎 -57 贵XXGQ0I 113369196203199459 怎么办 -58 湘ALQT4M 323578193703063895 刹那间看到他的时候,是无以伦比的恐惧狠狠地扼住了他的脖子,苏文一生中最大的禁忌,最丑陋的一块,在他用尽一切方法远离它,不去想起它,遮盖它的时候,它就这样被赤裸裸地暴露开 -59 川E1P78L 811516194003084604 一切虚伪的阴险的覆盖都被撕 -60 津RHQRT6 321623196611282885 虽然,跟那个小男孩相见只有两次,然而那个面孔却像是生了根一样,深深地扎在苏文的脑海深处。他用尽一切方法却遗忘它,去淡化它,然而当那个年轻人 -61 宁NAE3MF 535856198610080412 这是多么令人恐 -62 吉XC1KDO 210676200202093650 镜子里的人的面孔刹白 -63 藏XQXVHR 817199193505287921 哗啦——连忙低下头,水泼上脸,努力使 -64 甘DXCMCA 508029200004240332 那铃声就如同催命符一 -65 湘MR2QFQ 446200193903203789 不要怕,不 -66 渝T2T5C3 535874199312160967 苏文越是这样对自己说,然而却越是惊恐地发现自己居然有自己在三岁时候的记忆。三岁的时候,父亲母亲在吵架,他被托给外婆养,外婆死掉了,父母亲接回他,又不断地吵,他一个人坐在自己的小房间里,一动不动地坐着, -67 桂GEM6TF 533583198907029503 鲜明的记忆 -68 黑L2EWU1 641416193911190956 而越是恐慌,越是想起更可怕的事情。想起那一天进入那小男孩的身体时他撕心裂肺的哭喊声, -69 闽UUQXVD 625073195702276472 一旦认出他,他会怎么做?对强暴他自己的男人,一定 -70 晋FHYSDS 376860197712014641 苏文打了一个 -71 琼FHMIKR 120405197505040587 手表上的指针毫不留情地 -72 渝KOT44P 653501197303012242 镇定下来啊!镇定下来啊……苏文颤抖地对自己说,然而不断发抖的身体却让他骇怕得想哭。怎么办?怎么办?他要完 -73 渝K85KGT 446419200101111726 不 -74 陕DZ45SF 376866195106179561 想想那个男生刚才的反应吧,他显然没有认出他,虽然以后他可能会想起来,不不不,没有这个可能!今天没有认出他,以后也一定不会的!显然的当年的小男孩已经忘掉了那件事情了!而且——突然像抓住了救命稻草一般,苏 -75 冀XBZ4PN 537092195802283205 不是他的学生……不是他的学生……苏文默念着,使劲地镇定下来,看着分钟指到五分钟的方向,新生开学第一堂课,教授迟到十分钟,恐怕会出大问题吧,不要怕,不要怕……一切都不是最糟糕的…… -76 藏H0IZKQ 521790194404189571 苏文擦干了脸上的水,使劲地拍自己的脸,让那苍白得有些发青的脸上显 -77 云RX78JR 532542199006095529 <三 -78 浙DPVKD4 228470200501199973 上课铃声响了十分钟,开课的教授还没有进门,所有的学生都在吵,议论纷纷,其中不乏“这样的老师也太滥了吧,怎么会得到那么高的 -79 湘FAOX64 361977193501176169 苏文一进门,学生的吵闹声没有停下来,然而近250多位学生,每个人两只眼睛都直视着他,在以往作为教师上过这么多的课,这样的目光根本不算是什么,可是今天,苏文却感到无比的紧张及害怕。 -80 贵GCVAE0 218870195512191091 在那视线之下,他就如同满身污秽的罪犯一样,无法站在这视线之下。这种想法令苏文在走上讲台的 -81 渝W87TOX 826499199109279179 学生一阵哄笑。不过也让刚才气愤的议论声平静了下来 -82 冀B7IJ06 227307197706255483 “老师穿白色的袜子噢,不知道是不是有洁癖啊?”不知道是哪位大胆的学生突然嚷了一声,所有的学生都笑了起来。刚才苏文一脚踏空的时候,所有的学生都 -83 青ELWSN7 658450196106190730 “洁癖吗?如果这位同学去参观我的寝室,会发现我的床下跟你 -84 贵REUGHH 126482194212241691 果然这句话让学生们笑起来。 -85 藏L3U05C 507479193101222849 苏文战战兢兢看了一眼那个男生的位置,他 -86 桂TCPVLX 239837193712245511 他是怎么了?是怎么了?不 -87 辽TSTV1C 636921195102171679 “好了,同 -88 云MKXBS4 358014194607065690 “噢噢噢!”学生哄闹起来。那“噢噢噢”三个字是第二声的,一个 -89 闽X9Y8RV 360584198501081708 “大家现在动笔把这些联系方式都记下来,如果你认为你的物理以后可能会被当的话。”苏文道,“大家会选我的课,我知道原因,因为我在 -90 陕TZBIPH 213710198204033349 学生中 -91 吉TN9RIB 127206193109301065 苏文发现他的目光不自觉地追随着那个男生。该死!他到底是怎么了!不是 -92 粤HASPWP 507856193104114469 “我知道大家很讨厌修的课程被当,因为不但要交重修费,还浪费青春。”苏文继续道,“我也曾经被当过课,所以我知道大家的感受。”其实苏文在大学里并没有被当过一门,然而没有当过课的老师不会受学生喜欢的,至少不 -93 粤LB9Y9K 127374200905063193 “呀呀,老师您说出我的心里话了。”学生们在下面乱七 -94 鄂P4ZLR7 630528199705299969 苏文笑道,天知道他心里多么的害怕多么的恐惧,因为那个男生正托 -95 皖R69CCG 371292198503256452 “ -96 贵ZGXEVX 415800198502273322 当那个男生低头记时间的时候,苏文才敢看他。很黑的头发,看上去就是很柔软的样子,那个男生像是注意到苏文的视线,突然就抬起头来,苏文躲避不及,视线与那男生的视线相撞,那澄澈的眼眸一下子撞进了苏文的心,狼狈 -97 吉Y1VCYW 824609194105158641 “噢——不——多——说——”然而学生们心照不宣地笑了。物理系中苏教授透题最多是在学生中公认的,然而这些话当然不能说出去,因为这是学校不被允许的。不论是从学生的角度还是从苏文的角度,没有人会把这些事情说 -98 苏SYCXD8 455454200607058351 苏文注意到那个男生对着身边的同学似乎 -99 渝QQK1GB 432063200009012993 “考完试后三天,我会将考卷批改出来,学校例来要求在一周内教师都必须把成绩填报上去,而我会留到最后一天送上去。刚才留给大家的联系方式就是为了方便大家在那个时候找我的,除了晚上十点到第二天早上五点,大家都 -100 津PIQ9SH 455832193407260268 “哇噻,这个老师真不错啊!”座下 -101 浙ZQA7II 369489198109049992 “这是令人不耻的!”男生左边的戴了眼镜的同学道,“虽然我也很喜欢这个老师,因为我不想这 -102 琼APONJX 238538196302167274 “是不错。”藤帆若有所思地盯着讲台上的男人,“所谓的在学生中口碑极好的好老师原来 -103 吉AWECSI 501640196912092715 “啧,现在的竞争激烈,教师下岗多的是,比起那些明目张胆的讨好学生,这个老师已经是很不错的啦。那些以为请学生吃一顿就可以博得学生欢心的教授,看了就恶心,简直就是把学生当白痴看,以为我们都那 -104 桂U37RY3 814255197006270612 藤帆没有再说什么,只是望着那个老师,视线直直地盯着他,那台上的老师写了个公式转过身来,视线一下子就跟他的撞上了,没有为什么,藤帆就是可以肯定那个老师在看他!而且在视线对上的 -105 琼O7DYWR 626752193009106895 在五分钟以前,藤帆对身边 -106 豫I029FV 432280193410029454 “他还看我咧,你 -107 藏VBVXS3 319138196609020022 虽然身边的男生这样说,可是藤帆就是可以肯定,这个在这学期是他的物理教 -108 青E297RX 826654197202014997 而且,他自己对这位老师的一种若有若无的熟悉感是 -109 浙HOLYJJ 828221195110241445 第二 -110 沪AC37WK 542912200711129064 < -111 浙ZSE32N 328975198603081763 下课铃声一响,苏文就急步离开教室,往学校行政 -112 蒙ZBU8TN 635664197412317457 “这学期我的学生的资料全部整理好了吗?”苏文问。每一学期开学的时候,人事处都会将每位学生的资料影印给这位学生选的教师,而一般情况下,教授们不会对这些感兴趣,往往是拿到了所有的资料也放在一边,等到学期结 -113 甘LP0WNK 619555193107270091 “咦,苏教授,您的资料还没有弄好。”负责这件事情的职员道,“因为 -114 沪R5MC1I 350343198803161401 “那没关系,我要找其中一位学生的资料,你先把现在我的 -115 贵O4CRPA 220765196008092522 “那位同学的 -116 渝VE89ZJ 365774194109305108 苏文一下子 -117 苏UCBMS5 460744200211286480 “不知道名字吗?”那职员已经手 -118 赣RZPR52 371117199208037542 苏文坐下。一份份学生的资料在他面前出现,翻 -119 青WQQ8UE 376476201506068347 在一张黑白的一寸照下面,清清楚楚地写着那个男生的名字。藤帆。黑白的一 -120 赣IL2OAO 628914199402069363 苏文的心突突跳。他手指颤抖地按下“打印”,打印机发出声音吞进白纸,苏文觉得自己的心也好像白纸一样被打 -121 鲁MHSUY4 534894196001151816 刚打印出来的文字还有油墨的香气,苏文抓紧了那份资料,还有些微热的纸张熨着他的手指,他感到一阵暖意,一种令人全身都想战粟的暖意,他抓紧了资料, -122 津WS0679 358133194611021257 刚走出行政楼,苏文不由得倒吸一口气。在行政楼前面,凤凰树下,那年轻的男生双手环着胸,正慵懒地靠在树下,两条健腿 -123 津RJE0RY 369767197105298021 是藤帆 -124 津LU4RJ8 652628200402152209 细碎的阳光从凤凰树叶的间隙落下来,藤帆懒洋洋地把视线投向行政楼,落到那个刚从行政楼里出来的男人身上。男人叫苏文,他这学期的物理教授。他懒洋洋地打量着他。长度适中的短发,没有多大特色、平凡到会让人忽视的 -125 川KGM6R5 824349200601202683 “老师。”藤帆迈开长腿走过去,看到对面的男人的眼睛越张越大,那眸中明 -126 桂VKII49 625550200005106877 “您的东西掉了噢,老师。”藤帆走到男人面前,俯下身要去拾捡落在地上的纸。男人 -127 津WV3ECJ 815635194911066473 然而已经 -128 浙C4OONZ 143639197505242924 藤帆拿起地上的纸张,望见上面自己的照片以及自己的学生资料,“哎呀呀,藤、帆,这不就是 -129 沪TFH5UF 536094201204067336 “不,不是——”苏文慌 -130 浙ADUKU0 521448197404098168 “别的同学的资料呢?”藤帆双手 -131 辽X4Z0QT 623572195710020636 “不,不是只有你一个人的。”苏文一口否认,“你,你在这儿干什么?我,我要走了!”说完,他拔腿就 -132 渝FMLRAM 221665200102034213 “跑得那么快干嘛?”藤帆大步跟上,“老师您一下课就像逃跑一样跑到行政楼,知不知道我跟你跟得好辛苦,现在又走得那么快,赶着去投胎 -133 苏XYDFXW 530570196007027076 “对不起,我还有事。”苏文恨不得拔腿就逃,然而在这人来人往的路上拔腿就逃显然是极不明智的,他只有拼命加快脚步 -134 桂BVBO23 455375200403269119 藤帆一把拉住他的衣袖,把他的身体转过来,盯着他,那视线在苏文眼中就如同 -135 藏FF3RI8 444848196211094229 如同天籁一般的澄澈的声音,透明的声 -136 津PJ1UT5 446940196408167576 “放 -137 鄂L3U2Z4 377798201410276341 “ -138 苏X9DT2T 533064200511033391 撕心裂肺的叫声回荡在耳边,苏文果然是被逼 -139 鲁Y6Q383 136828197011271171 他拔腿就逃 -140 蒙MKW1RA 626412199207152188 中午的校园路上来往的学生很多,所有师生都看到一向严谨的不会有一丝一毫出轨的举动的苏教授在拔腿狂奔。然而那些师生 -141 蒙WCE1SB 310291195201026307 留下藤 -142 冀OFKPOT 112715194103025394 <二> -143 桂W6E5I7 234529198710212312 一路上不知道闯 -144 新MHZGTY 350050196803064495 回到家的时候,苏文只觉全身湿冷,一摸额头,全是汗。手中还紧紧地抓着什么东西,仔细一看,原来 -145 鄂PTLJLZ 449032199802093861 他深深地呼出一口气,慢慢地坐到书桌 -146 琼XR9M7P 549840201405243703 偌 -147 桂DE3TL9 435506199304224247 这是一间很没有人味的房 -148 吉P7ZYNP 623659197307137757 房间被人居住了十二年,然而这房间还是空荡荡的,除了 -149 青QKIDWI 157945195505074965 这一切都 -150 琼RPJYRM 133006193609078434 “嗯……啊……嗯哈——哈……”正午的时候,窗帘却没有打开,外面的阳光仅有一两缕透过窗帘的微动照进来,照在地上一条长长的阳光的痕迹,苏文的手紧紧地抓着那份藤帆的资料,资料上黑白照片里的男生漂亮的大眼睛凝 -151 冀ID64RL 439150199807315768 好热… -152 苏HMLBNU 126012201307082801 好热啊…… -153 豫LOM2PA 646457195507196049 近乎粗暴的,揉捏自己的敏感之处,全身禁不住地不停颤抖,呼出的空气都像是着了火一样, -154 蒙IUVG4U 441175196307014726 拉链早就拉开了,内裤下的手指包 -155 吉H7WY66 446808199304140663 “好痛——坏蛋 -156 吉HRV2IW 325442195204026129 “好痛啊— -157 宁B5XW0W 223995198611012839 忽然间耳边就响起了那个小男孩的声音。三岁的小男孩的生涩的身体被他急切地打开,狂乱 -158 皖JTJHOI 650181193011143170 “好痛 -159 陕M90DC0 151865196811131285 在愈来愈狂乱的回忆当中苏文也 -160 晋V1E6AD 421541196406263115 “呼——”长长地喘气渐渐地淡下来,在空气中像是钢琴的余韵一样,一丝一丝地隐 -161 赣GXHN8V 629451199101026833 手上粘滞的感觉是自己的体液。苏文躺在床上,抬起手,手上的液体流下来,手的背景是天花板,雪白的没有一丝生气的,怔怔地望着自己的手指好长时间,苏文忽然像回过神来一样,低咒一声,狠狠 -162 渝P4LYET 417746199905063983 “砰——”的一 -163 渝T8OD0X 460480194307129400 哗 -164 吉CQC7M2 655590195604190608 淋 -165 云S05AN0 511038201508137880 出 -166 沪MAUV8P 111718195511025690 我这是怎么了?我这是怎么了!冰凉得有些刺骨的水打在背上,苏文把头重重地靠在浴室的磁墙上,望着沿 -167 甘K7V9UT 819920195608168641 定定地看得太久了,视线就会有些模糊,在水珠模糊成白色的一片时,苏文感受到一股极大的力量向着他扑过来,在这股强大的力量 -168 皖SLZ2T4 322318195912055700 第 -169 皖ZU6AOJ 117275200203163305 <一> -170 琼SQEXU5 142646199201114333 隔天 -171 云G4ZKGQ 232787200207167896 那个男 -172 鲁RY3E5Q 434483198606222081 发现自己下意识地在搜寻着藤帆的身影,苏文不由得唾弃自己。他是怎么了?那学生不来上课,对他来说,只有庆幸、万幸。见的面越少,他就越不会想起当年 -173 鲁NB5F21 372069201007303392 当苏文登上讲台,无意地 -174 川TWF1LN 152763201401175345 腿在颤抖,手指也在颤抖,在那澄澈目光的注视之下,苏文连把视线移开的 -175 黑R7UMTQ 634277200708261975 然而完全不同于苏文的惊恐,藤帆却是极开心的,甚至非常好心情地微微笑着看着他的老师。昨天拜托女生帮他占位置果然是有好处的,在这个位置,可以清清楚楚地看到老师的每一 -176 陕UUGHS7 502518195704288821 “开……开始上课……”苏文深吸一口气, -177 渝ZK0E7A 827236197508050067 这一堂课分成两节,每节四十五 -178 粤JQLYE9 237545196609142550 压抑着,只敢把目光专注在自己要讲的内容上,然而就是这样一直低着头,却能感受到坐在第一排正中的藤帆直直注视他的视线,那种存在感是如此的强烈以至于他完全不能忽 -179 甘LXAEVC 536493196109077034 终于,下课铃声响了,那是休息的时间,苏文吐出一口气,四十五分钟过去了,“同学们休息一下吧。”他近 -180 京YMRYAJ 655985195809282146 教室里还剩下一百五十位学生左右,趁着下课的时间,走动的闲聊的到处都是,每个人说一句话,都是极 -181 藏TK7D6Y 132326200410317134 “真是谢谢你为我 -182 鲁AVC9IR 649455199007262021 那是藤帆与他身边的女生 -183 苏I9JNWT 311670193710072872 大学课堂上的位置从来就不是固定的,来的早的自然会坐到前排,而一向懒惰的男生是不会提早来占坐的,所以坐在第一排与第二排的全是女生。一身白色休闲装的藤帆坐在这么多女生当中,没有一点不自在的样子,相反的,应 -184 沪UV6PN6 237453198102084150 “啊,不用谢不用谢,”那女生显然是受宠若惊,而事实上,在前天藤帆叫住她,让她在今天为他留个位置的时候,她就已经受宠若惊了,跟她同一届的藤帆,帅气的面孔与大方的举止以及据说他家非常富有的传闻,都给这些女 -185 青UZHY9O 501143201105196119 “真是麻烦你了,这么好的位置,你来得很早吧。”藤帆道。旁边几个女生也围了过 -186 浙UZL4JC 316520197602232386 “不早不早。”那女生激动得脸都有些发红。事实上,在藤帆今天早上出现在教室门口,走到她身边,坐在与她不超过一尺 -187 吉XSL34T 829340200605023150 “咦,”有女生鄙夷 -188 赣MZCAOH 654495195407287938 藤帆微笑地看着那个为他占座的女生,那个女生窘迫地低下头。为了占个好位置,又为了给藤帆留 -189 京PEBNK7 427638199505109881 不同于这个羞涩的女生,从旁边围过来的几个女生显然是比较大胆的,“藤帅哥,有没 -190 晋URWWN2 466789196711072660 在讲台上的苏文突然有些喘不过气来,他不敢去看向那群笑得生机勃勃也谈得入巷的 -191 桂EICO6R 437934193409087903 “还没。”藤帆笑笑道,他把视线移到讲台上,刚好逮到苏 -192 云X333LY 523987194405036213 藤帆游移的目光显然的让 -193 沪R5D4N4 360707199301107623 “ -194 云CH0OQ0 131915196602120899 “骗你们干嘛,真的还没有……”藤 -195 琼S29V21 453911195805135843 苏文忽然觉得他坐姿会不会有些不端正?他脸上会不会有东西?他今天穿的衣服 -196 湘I9EH53 346088200302131957 为什么 -197 川RBGRMQ 508224194612026789 而那些女生们不等藤帆说完立刻欢呼起来,“真好!有 -198 青N0QOQ7 463728195611309577 她身边的一位发出不悦的娇呼,“雅子你好坏啦!干嘛推人家!”蹭蹭蹭,也挤上前,“也考虑一下我吧!我目前还是单身噢。” -199 晋M7V01L 137296193109168031 旁边几位鄙夷地出声,“咦,你 -200 云I1CELN 458653199804303234 “怎么能这样说呢,跟藤帆比起来, -201 桂GNGCNS 822411195504144704 苏文感受到的是一种说不出的沉闷感。这教室的灯 -202 陕O0VYLS 469168194804249689 这些女生的一会儿尖叫一 -203 吉PTUV90 423287195109282081 他有什么资格?他有什么资格?与这些生机勃 -204 黑SXELPH 654781193007284108 他根本就是连遐想的资格都没有!竟然,竟然还会在心底有贪念。苏文啊苏文 -205 川Y348PM 129261193211297021 “很荣幸这么多美丽的小姐都能看上我,但是抱歉我只喜欢男人啊。”藤帆的声音传过来,带 -206 宁FFOOIU 469615197207214518 “咦——乱 -207 浙GJBXBI 139197194107239047 “开 -208 渝HYQB5H 348043197711047590 “ -209 渝P5RD8B 237154198910225876 “这么好的一个帅哥,怎么可以是同性恋 -210 冀JZZZ2C 534682195702151803 “藤帆你不可以用这样蹩脚的理 -211 粤R7OY6K 511633200906057041 “这是实话啊。”藤帆落落大方地耸耸肩,“所以,各位 -212 黑UEGJW5 527571200505112514 “咦咦咦,是 -213 宁GRXPA7 641914195101161820 身 -214 川GK4H0F 506630193908022079 “是啊是啊,以为自己是D罩杯就了不起啊,人家也是D,只不过比你的小一点点罢了。”其中一女生不甘示 -215 鄂ZTB716 816391194708125182 这话引起旁边A罩杯的女生的不满,娇斥声四起, -216 冀TJLK11 351368197108298401 “ -217 川L24G1Y 631758201105046203 “啊,真遗憾,可是我只喜欢 -218 浙QA3FXE 522881197512308560 “骗人嘛 -219 桂I6BDX8 545784196802063816 “男人有什么好 -220 鄂EMJUMR 443487194612282732 “是啊是啊,为什么帅哥都要去 -221 甘NG00BF 650368200508113562 “你 -222 皖JAXT4A 500451197009081320 “你—— -223 宁F0ZGQS 513450194907190739 藤帆微笑地听着众家女生的莺 -224 冀RI734A 224759194012213961 苏文一下子如同置身冰窖。他果然记得!他果然记得他三岁时候的事情!他果然记得自己强暴他的事情!他要被认出来了!要被认出来了!恐慌如同这沉闷的空气一般笼罩了苏文的全身,他无处可逃 -225 藏UX3MBF 418576198610300346 而藤帆这话不异于在众女生中 -226 湘GI7MSK 637465195408242767 “啊?真的?”这是还承受不是心仪的帅哥变成 -227 辽RIXZ8Q 619066201406032148 “天哪,藤帆你好可怜噢——”这是很容易对帅哥产生同情心的女生的 -228 浙UZ4DEA 822357199410272419 “怎么会这样?难道这样就变成了同 -229 辽T72FXQ 153617195105147113 “就 -230 青ZIIM4X 514866194309168874 “啊——真可惜 -231 闽J4VPL8 129996200711187807 “天哪,才三岁,藤帆你当时一定很痛吧——”就是帅哥变成了同性恋,还是令她们同情心泛滥 -232 浙YZ1UVA 373589194205239598 “那个同性恋的男人真恶心!居然会对三岁的小孩子下手!”那些女生们的谴责声传 -233 陕OT96LW 465130196104105609 “是啊,天哪,藤帆你那时候 -234 新X1HGLU 125562197401016923 “真是恶心的 -235 吉TE89UQ 358497196710086054 “就是就是,就是那种人败坏同性恋的名声 -236 新X42N6Z 544944201302265141 “藤帆你不要再喜欢男人了。万一不小心又碰到同性恋里 -237 皖OBNP0A 615578199109039031 “是啊是啊, -238 鄂STIR9Z 652879199403202003 而就 -239 沪GF9F0L 311527198104067488 而万幸的是,就 -240 浙KTSYJ1 359099195302282069 “都安静下来 -241 宁BAL85K 145240200907214369 <二> -242 沪SDVQ8V 124796194812176085 下课铃 -243 新FI66Y4 420860193807258838 “老师!老师——”身后有人追 -244 鄂MVQQ4M 145445194112152849 正是下课的时候,在这来来往往的过道上,走的全是下课的学 -245 藏NIPLWB 316809199210048649 “老师,干嘛跑得那 -246 苏XHUKJ9 815696194801014310 苏文恐 -247 渝WISYMS 212862196203162753 “老 -248 苏P0XD7E 130927195203122747 下课时候拥挤的高潮一下子就过去了,更何况这儿本来人 -249 渝VOU3YS 126336200703031292 他要干什么?他要报复了吗?他认出他来了吗?认出他就是当年强暴他的 -250 苏I338O1 546771200012181295 他要打他吗?要杀死他吗?所 -251 豫AXAFSI 315681193801083891 藤帆在说什么话,苏文根本就听不到,恐惧充斥着苏文全身的每一个毛孔,每一个细胞都叫嚣着骇怕,苏文看到藤帆年轻的身体,健壮的手臂,还有抓住他肩膀的手,那手掌很宽很大,手指很长,骨骼有 -252 湘V3977A 627801193412256857 那样的手如果握成拳头打过来,一下子就能把他打趴下吧。如果他要打他的话,自己会是一点反 -253 豫B1WQ4J 814939201201219456 怎么办?怎么办?要被打死了吗? -254 云MDQ6OK 645448195406054650 “老师!老师!老师——”藤帆摇晃着他的肩膀,他的声音终 -255 桂ZJ1PY7 129518194312020578 一副 -256 陕M1Y2ZU 539417198509221432 “你,你……”苏文听到自己的嗓子里冒出的 -257 津LBQVDF 226186199404183376 藤帆以为苏文是想问你刚才讲了什么,于是又重复了一遍,“我刚才问老师,我有这个荣幸请老师吃一顿饭吗?老师 -258 琼HQDU62 623153198705210426 “为,为什么?”苏文发现 -259 晋VWL85R 521934199304062499 “为什么 -260 鲁KH42Q0 363970201101018797 “不——”苏文终于抓回自己的声音,他僵硬地丢下一句,“我 -261 豫B9OP3J 537757198705031488 “咦?一开学就答应学生会让他及格 -262 吉N7ZFDG 430666195804013845 “玩,玩笑——”苏文的声音干巴巴的,因为恐惧,“那 -263 粤J1AVSF 811745193812164067 “老师您真 -264 苏BB2MI2 214745196712139341 “我,我还有事!”苏文僵硬 -265 辽NLJNLU 124325195010204438 “噢?很 -266 黑B3TTAZ 135324196411026741 “不——不是的。”同性恋!同性恋!那词就如同飞镖一样扎得苏文千疮百孔。他认出他来了!一定是的,一定是认出他来了!所以现在在玩弄他!一定是的! -267 沪Z1GS4Z 228354193411300281 “咦,不是的话那老师为什么要拒绝我呢?”藤帆拖着他往电梯走去,“ -268 藏H0AGGZ 505933201105064944 苏文被他 -269 浙CGWM9G 463387199507078045 “老师您就不要再抵抗了啦——” -270 贵WE18KW 506771196910071531 “咦,那是老师您的 -271 青KFWWHP 374734198506307550 “不,不去食堂吃饭吗?”苏文僵硬地问。校内有学生食堂,有的教师课多的话,也会在那里随便解决一下 -272 冀FYOEO6 635996193409099166 “咦,才不要,食堂多糟糕啊,那么多人,我跟老师的第一次约会怎么可以在那种闹哄 -273 黑ZPMBLK 424329197109259780 苏文瞪着坐在驾驶座的藤帆,他抓紧了他的公文包,他的公文包里面放着一台手提电脑,如果藤帆想在车 -274 京XVIU3T 366947194405206972 等关上车门的时候,苏文忽然想起一 -275 甘LSF55A 365063193801030825 “放心啦老师,我开车都开了好几年了。 -276 沪AAAUUK 652882199006241941 “……” -277 陕TC32ON 625579193012193549 “老师您好聪明呢。”回答苏文的,是车子离弦一般的速度在不到一秒内极速飙升,“因为我一碰到车子就会不受控制地开好快,所以没有一次能通过,很 -278 京I6QRC5 619880193202113964 “……”晕车的感觉一下子冲上来,铁青着脸的苏文在努力控制住不断反胃恶心的感觉的同时,心底里不受控制地冒出一个可笑的想法 -279 闽P3WDRG 337277201410019504 藤帆……不会想用这种方 -280 鄂A031OX 351550194104264108 <三 -281 青CJ5U33 613504196112165473 自从那一次的共进午餐之后,苏文的心莫名的就放下来。因为他发现藤帆只是记得三岁时候发生的事情,可是对那个强暴他的男人一点印象都没有,这种逃过一劫的想法让苏文紧绷了三天的神经 -282 青AUR32G 429206198407263246 可是还是有一点不自在存在。因为自那以后,藤帆每次上课都还是坐在第一排正中的位置,不知道他用 -283 吉RTPHA4 450004199403050342 苏文 -284 云BA8SOI 828796198308053906 藤帆的目光如果说是专注地听他讲课,倒更不如说是有意无意地打量着他,有时候是托着腮直直地盯着他,有时候是若有若无地把视线落到他的身上,每次苏文一低头或者是转身在黑板上写东西的时候总能感觉到来自于第 -285 豫C02YL5 123069196903136515 而当苏文的视线一不小心与藤帆的视线对上的时候,藤帆就不断抛媚眼飞吻一个个,有点嘻皮笑 -286 陕MKLSR2 447429198405163879 藤帆这样明显的动作很快的让所有人都发现了,当那群女生询问他的时 -287 陕F8UNVW 829012200407091245 喜欢,是个很抽象的名词。子女对父母的是一种喜欢,哥哥对弟弟的是一种喜欢,甚至于售楼小姐对客户也是一种喜欢,苏文竭力想让藤帆所说 -288 鲁DYR0ZI 533300193511290430 也因为藤帆每次都来上他的课,苏文备课更加的用心,可以说把以往的教案全部重写了一遍,他甚至翻了很多幽默类的书,在图书馆借了很多口才讲演之类的书,以让自己的课堂更加的生动有趣、有吸引力。这样努力不是没有结 -289 赣QHE94W 119876196806290086 苏文第一次感受到了身为人师的骄傲与自豪,这是一种被人尊重的感觉, -290 川K5C7FY 369815196906213859 如果那些学生知道他是个见不得人的同性恋,是个 -291 苏LKS6Q1 615959195501175160 这样的想法让苏文度日如年,每次回家的时候都对自己憎恶至极,然而在藤帆每堂课微笑地看他 -292 黑RIOH0B 340241200811275592 有一天,苏文像往 -293 鲁GZ2M12 819389193408245462 苏文的心一下子 -294 桂E98ENY 370677196204224184 他慌乱地环顾整个教室,所有的学生一个个扫视过去,都 -295 渝US64P0 459276200504141594 藤帆没有 -296 青MPUYYY 431796196001276674 他放弃他了吗?他终于对他的课感到无聊了吗?一种被抛弃的感觉一下子扑面而来,就在这种感觉的控制之下,苏文的那一堂课讲得乱七八糟,前言不搭后语,虽然他已经竭力地没有 -297 粤GBWYWM 216770196802201894 在课间休息的时候,苏文看到一直坐在藤帆旁边的女生接了一个电话。明知这个电话很可能是女生的男朋友的,明知这个电话是藤帆打过来的可能性极少的,然而苏文就是不能不往这儿想。藤帆出事 -298 晋N9PFEA 310533198809226658 苏文盯着那个 -299 鄂ANVY3D 517123200202039218 苏文逃避不及,狼狈不堪 -300 沪E8JBGB 617263197912021808 “老师,”那个女生果 -301 闽ICLA2D 227244201307312460 “生——生病?” -302 晋VIE8S3 220450201007295172 “是啊。生病了,老师很担心吧, -303 津EUGFG0 115522199010105854 “怎,怎么可能!”苏文下 -304 川D74JNW 542809193303318705 “咦?不担心吗?老师真无情呢,藤帆可是每次都来上老师的课,难道因为藤帆 -305 沪JN2MGC 358871201312052784 “接,接受?” -306 黑I86B3N 510324193506215247 “是啊,老师您不知道吗?不会吧,连我们都看出来藤帆喜欢老师啊。 -307 宁KVVZTF 213273195704305864 “那,那不是随便乱说的吗?”苏文从来没有想 -308 津W6VTBA 826003199803220711 “咦,老师你才在乱讲呢,感情的事情怎么可以随随便便乱说,而且藤帆表现得那么明显,”那女生道,“因为呀,藤帆每次来上课看老师的模样,都是一副含情脉脉的样子啊,哎,如果我有这样的一个男朋友该有多好啊……” -309 粤ID6GI6 504905194109237131 生……病 -310 辽B65QZ3 229787198701166444 原来是病了啊!这种想法一下子充满了苏文的脑子。不是因为对他厌倦了,也不是因为觉得他无聊、没有吸引力,只是因为生病来不了了啊!这种感觉让苏文松了一口气,原来近乎要越沉越下,要沉入黑暗的绝望之中的心情又开 -311 粤Q4LGWC 344477193607316574 会病得很重吗? -312 辽X5VVGN 237859193201033495 在这样的担忧之下,苏文魂不守舍,接下来的一堂课更是乱七八糟,他自己也知道这次的课讲得实在不像话,索性提早半个小时左右就下课了,学生们欢呼着离开,苏文找出 -313 京LPDJKX 369892194501286516 藤帆没有住在校内,他在校外有一幢房子,离学校也不是很远,苏文在路上买了些苹果,及至到了藤帆的门 -314 闽P45LBC 468195197005115132 怎么会这样呢?面对着紧闭的大门 -315 青G6SCN9 648302199907090892 最后还是敲了门。敲了好长时间都没有人回应,苏文确认了好几次地址,没有错误,在最后一次敲门的时候苏文终于听到房里传出一个男生像是被什么东西捂住的沉闷的声音,“ -316 辽KWMZ9E 636942197011192037 那是藤 -317 闽TARZKZ 233794201010085374 苏文松了一口气,试着转动 -318 湘H9XJ5R 455537200602208203 脚下一下子踩到什么东西,仔细一看,是倒在地上的衣架,上面的衣服乱七八糟地堆着,有的已经被 -319 湘SEUL2F 613252194909121860 一本杂志的封面是一个一 -320 川INNU6S 624346200502050342 “谁……”从卧室里像是从被子底下发出的声音。 -321 苏S3GU5Z 140414195012283834 “是 -322 黑PFZEWB 348208199407268124 他挣扎着也许 -323 冀LUR9IN 431763195302212396 卧室的地上全是面巾纸,空气中是一股不正常的药的味道,苏文走过去的时候发现藤帆的脸有些红,是那种高热的 -324 青ZAJ1Q8 425493201205023247 “听说你生病了。 -325 吉A4W1N7 529950194802115676 “唔……感冒罢了……”藤帆舔舔干涩的唇,他 -326 陕G4MQOH 159773193011141777 “听……听说你生病了……”苏文在那视线下坐立难安,两只手不知道做些什么,看到藤帆的额头上渗出汗来, -327 琼R9UESK 220125194905250196 “……唔……”藤帆一动不动地躺在床上, -328 鲁YXR63V 621118196209197599 这想法一出,苏文的心脏就急速跳动起来,鼓躁着,苏文似乎能听到在这房间里他的心跳得好大声,只要捂住……趁着他生病虚弱没力气反抗的时候,只要捂下去……就没有人会知道他以前做过的事情了……苏文的手不断颤抖, -329 豫LAI9D9 113997194611032354 “老师!”藤帆突然叫了一声,苏文一震,手一惊,毛巾一下子掉落到地上 -330 云XFN2RS 216325199411057785 他发现了吗?他发现他要杀 -331 晋W40F79 415103201510162178 “毛,毛巾掉了,我,我去 -332 青U5G1M2 536226201507235680 “不用了,我不用再擦汗……”藤帆伸出手来拉住他,然而苏文的手已经把毛巾捡 -333 贵TIEUWX 339496200304192269 “出 -334 湘FK1J43 375262194505302225 在苏文拧洗毛巾的时候,藤帆的目光直直地盯着苏文,苏文的目光躲闪 -335 渝B1G93C 374105196907315124 “唔——”藤帆盯了他一会儿,忽然邪恶地笑开了,“老师,我身上流了好多汗,你帮我 -336 辽B212C0 536919194401045875 “好,好的 -337 豫EFIPRM 526512195405189561 被下的身 -338 川HPK6H9 312131196210011210 “吓!”苏文 -339 黑Y2RW3T 347253196203169280 “呵,呵呵呵 -340 赣AC6S33 825430198107209118 “我,我没想到……”苏 -341 闽N9VU1E 519742199404301957 “没想到什么?”藤 -342 皖ZIBP7J 515002197411224107 “我……我……”苏文不知道该把视线往 -343 云KAWR6T 317316193711108788 藤帆一下子抓住他的手,把他的手按到被子一处,声音沙哑而有些急促,“老师,你摸 -344 湘V1LVNS 310440200712155560 手一下子被人拉过去, -345 津NJ492L 466362200408058976 藤帆吃吃地 -346 川GCALH9 223929200311033238 “说,说什么话!”苏文斥道,眼神慌乱,那只手火辣辣的,刚才的那种 -347 辽JPS7IZ 323887199109223293 藤帆的目光 -348 辽UOBYCK 527947196501114737 “你,你——别胡说八道。”那个地方被人盯着看,就 -349 黑FPYYQM 226176200203305865 也许是盯得太累了,藤帆眨了一下眼,他的眼睛很大,双眼皮的线条很深,黑色眼眸像是带着电一般,那瞳眸像是黑洞一般,有着无尽的能把所有东西吞噬的力量,那有着好听的磁性的沙哑的声音进入苏文的耳中,“老师您都是 -350 青GAGRMZ 142937195504129247 “你,你在说些什么!”苏文又气又怒,因为藤帆的话让他的全身都像是着了火一样的热 -351 黑MM106C 414038195807022594 藤帆无辜地眨眼,“ -352 吉ZQIUDA 335107193809046506 “胡说八道些什么! -353 沪RZAON3 328546199208270612 “胡说八道的吗?”藤帆 -354 晋IK6LVM 238121198401255004 “乱,乱讲!”苏文像是被 -355 辽SM86IR 334140195604104575 “老,老师……”藤帆兴奋地坐上他的大腿,啊啊,被子滑到地上了,那个地方暴露在空气中,很激动地挺立着,苏文的心突突跳,心跳早已经不正常了,强硬地把视线移开,却落到地上摊开的漫画上,那漫画的封面就是两个赤 -356 川GYMW87 448782197801049927 而藤帆却脸色不变地拿起那本令苏文脸红心跳的漫画,抓住苏文的手,强硬地把那本漫画塞进苏文的手中,藤帆在吃吃笑,在苏文腿上不断地扭动,“呵呵,老师在害怕吗?没有看过这种书吧,比那些枯躁的公式好看多了噢。这 -357 川MHP3AM 820080197206132872 “咚——”的一声,苏文慌乱挣扎中一脚踢到藤帆的小腹,把他踢下床,藤帆捂住小 -358 沪FYP4T4 356031196702258507 那“好痛 -359 藏HDDI1F 145587199707100060 “好痛啊——坏蛋——坏蛋放开我 -360 沪PBRRHG 127661196110027750 “ -361 鲁SZVVPI 448317193612177266 “坏人——啊啊—— -362 吉IH1HXT 128645197405030615 苏文“唰——”一下子站起来,全身僵直着站在那 -363 粤YKB9ZD 410933200608273487 “老师,老师你怎么了?脸色发青呢——”藤帆站起 -364 鄂ZP8APF 443631195607075068 “别碰我!”苏文“啪——”的一声打掉他的手,藤帆的吃痛声让他又是一惊,这才发现面前的有着曾经的小鹿一般的双眼的小男孩已经不再是小男孩了,已经长成比他还高的男生了,他赤裸裸的,骄傲地一丝不挂地站在他面前 -365 蒙PUPTGS 334630197510074093 “怎么样老师,发现我的身体很完美吧,考虑跟我做吧,我可是想了好久——”沉闷的一声响,藤帆被苏文推倒在床上,“啊啊,老师不要那么急,我们可以慢慢来,有的是时间,虽然 -366 贵Q59LE8 615998195611283846 “叭——”的一 -367 黑ABQ317 466057195402018067 苏文近乎疯狂地把被子的每一个角都掖起来,牢牢的,密密实实的把这具年轻 -368 桂W17XN5 626958199212167200 苏文倒热水,看时间,也狠狠地瞪着床上的 -369 陕GZCWP8 458087199708214140 “……唔……”年轻男生的眉头皱成一团,连鼻子 -370 宁VFDECE 548595193703202332 “烫啊——好烫好烫——”药和水一咕噜地下去,藤帆吐舌头,“好烫好烫——老师您原来是想烫死我!就算我刚才兽性大发想侵犯 -371 晋DO2LI0 645365195304271674 苏文一拍床,喝道,“睡觉!”再这样下 -372 吉UBDFXK 432950200301140686 藤帆望着他,慢慢悠悠地在床上摊手摊脚躺着,转了转头,又转过去望望苏文,又 -373 京BSI9FP 379577197901124195 苏文铁青着脸瞪着他,“病了就要好好 -374 浙NAJJD6 504396199407232869 “呜呜老师你好残酷好无情——”藤帆的头缩到被子里,人在被子底下滚来滚去,又滚回来, -375 晋V9HLOZ 415508200507193135 苏文瞪着他,死死地瞪着这个一举一动都让他 -376 豫XX5L5Y 153597196505010832 电视一打开,苏文 -377 皖ATFWC0 132919197503091332 “啊啊……好棒 -378 京R1R0I2 427046195910279699 “快……快 -379 苏SO4IWA 356606199206020710 超大的屏幕上是两个男人纠缠在一起做爱的 -380 豫JR95CY 220364193410021889 整个房间里充斥着极响的呻吟声与喘息声 -381 陕XGKYBX 112377197501193600 苏文只觉得自己浑身的骨骼都僵硬了,因为他转过头的时候发现居然十分的艰难,每转一下,颈部的骨头 -382 藏A8A492 421444197406039529 藤帆似笑非笑地躺在床上看他的反 -383 津KBQCRF 536332193101086475 深深地吸一口气,告诫自己要冷静,不要失手掐死他,苏文面无表情地转过头来关掉 -384 贵L50ULW 333026193103120881 望见苏文眼中的火光,藤帆干笑着,“咳咳,老师——” -385 豫TVQXUK 130683200912043852 “睡觉 -386 冀M05N2V 221378194912149435 “噢。”藤帆乖乖地把被子蒙到头上,在被下眨了几下眼, -387 琼H8EKA9 320175196403075926 老师来看他呢 -388 鄂U6K3J7 822566194106200086 没有一次生病是有人会真心来看他的……父母亲吗?哈,根本就不可能,如果不是每年打进帐面的几千万,他根本就不知道他还会有父 -389 川DK2NG3 465910196610217116 一想到这里就更加的感觉到有些寂寞,怎么可能睡得着,藤帆悄悄地把 -390 陕VL49LF 508889200901011418 “嗯 -391 鲁JRD81L 110978201004113783 “我睡 -392 琼I7ZOSH 110734194707207601 “故事?”苏文伤脑筋 -393 豫XF2GR9 621400200909174421 “咦,老师你小时候也没人给你讲过床头故事吗?像是小 -394 豫DJTGIO 142889197006190952 苏文疑惑地接过书来 -395 鲁FGHE0H 525150200906254037 “嗯。”藤帆很响地应了一声,两眼满是期 -396 赣T3EDU0 326425196312312210 苏文的注意力 -397 京M53ZSA 370274201008215062 苏文的注意力全部集中的书上,他没有看到 -398 浙B4ZQ8I 129242194904222108 “……在阴暗的房间里,没有一丝光,暗红色的窗帘都拉得严严实实的,他面对着他,慢慢吞吞地脱掉黑色的 -399 陕NTSRQR 426688200905081352 老师,老师……苏文… -400 琼X2TM84 532620194610205789 床上的藤帆却没有很专心地听苏文在念着什么内容, -401 浙TT6V3A 216202199907100234 念过三页,苏文发现接下来的全是“嗯……嗯……啊啊……”之类的东西了,他有些羞怒地抬头想骂藤帆,却发现他把被子拉到胸前,已经沉沉地睡着了。那长长的睫毛覆在眼睑上,原来的大大的晶亮的如同小鹿一般但是却比小 -402 桂OJRO0Z 420605199911296930 苏文注意到那额头上有些汗 -403 皖QROPRJ 113110200610071208 在擦了几次汗之后, -404 赣Q4ADAA 523531198401101701 客厅很乱,卧室里更乱,别的房间更是无比的乱。苏文在这房间里不知道过去了多少时间,只记得那个高烧的人的呼吸声在耳边一直回响着,收拾完毕的时候看看时间,已经是下午一点钟了,走进厨房,冰箱里空空荡荡的,只有 -405 京S3AG64 423089194205149770 藤帆醒来,迷迷糊糊的样子,“老师?” -406 浙VTEUE2 519176201211184167 “是我,”苏文把床头柜清理干净,“吃点东西吧。 -407 琼BCGCME 425355201101045283 藤帆仍是有些没睡醒的样子,“老 -408 藏ST216Z 319640198803210312 “是,吃饭吧,已经快下午两点了。”苏文舀了饭到藤帆嘴边,藤帆傻乎乎的一口咽下去,嚼了两下,又问, -409 琼EQF3J8 818111199508141073 那样子不由得令苏文觉得有些好玩。“嗯”地应一声,再喂他一口汤,再一口饭,藤帆傻乎乎的全吃光,然后苏文说 -410 新OPVL5K 654373199306074590 苏文不由得有 -411 陕TC4QDB 369628200912158489 下午到 -412 晋DWIXZY 227458199705210794 夜晚的时候房间里 -413 蒙LVPGV2 627881198002212717 在那一页上,在抬头处记着他的电话号码,所有的联系方式,然后接下来就是不断重复着的密密麻麻的写着的苏文苏文,全是 -414 新HYCYZC 135743196310136298 ……苏文苏文苏文苏文苏 -415 吉PQ3DTK 126489198806157680 苏文一下子觉得心跳如雷。像是 -416 桂QDGL8X 436484193012068367 “啪——”的一声苏文阖上了电话本,手忙脚乱地把它丢掉。 -417 宁UOJCNA 545951200608291798 ……因为我喜欢 -418 川K0C1D5 134559193501239888 那一天藤帆回答女生们的话一下子冒了上来。 -419 桂S9EBXM 423995197210017615 我喜欢老师喜欢 -420 豫V0H9QI 225269201206167086 苏文紧紧地抓住自己的手,喜欢,喜欢……耳中一 -421 湘C072IP 534375197810017631 “跟哥哥一起出去玩好不好?那儿有好多好玩的东西噢, -422 陕J57ZQE 338920198612051663 “嗯。”那个小男孩的话很响很响,很快乐的音调回响在他的 -423 京NKWOAF 630439194501220093 然后是凄厉的,孩童的叫声总是让人觉得有些撕心裂肺,让人的心都跟着揪 -424 辽TORK4B 824948199901160566 “坏人 -425 新TO7BN2 327342201108091170 苏文的手心忽然一阵刺痛,低下头时,才看到自己的指甲不知何时狠狠地掐进手心,鲜红的血从手心流出来——罪 -426 吉W2LCKQ 638058193804071019 苏文觉得,命运之神让他成为一个罪犯,让他活在恐慌之中还远远不够,还要给他诱惑,那诱惑散发着罂粟的甜美的巨 -427 宁WMX59C 325486199009290626 第四章 -428 渝ACFR4J 825244200610273591 <一> -429 桂PAZQHA 816181194806021226 早上九点,透明的体温计插在沉睡的男生的微启 -430 渝GVMYN2 462882196911101368 苏文直直地瞪着体温计,想着那里面是水银,只要吞进去一点,就会汞中毒而死。而这样的死亡不会令人产生疑虑的,只要把那体温计弄破,让藤帆吞进水银,等他一死,他马上离开,这样就是警察查出来他来过这儿,他也可以 -431 苏NMGHI7 464195196912302737 只要藤 -432 沪LQPSR4 536708194606200347 十二年的心惊肉跳,这一个多月来的三魂 -433 蒙VUNNKE 129717195709212458 只 -434 藏I7CV58 136659195611175850 “…… -435 皖DUYX6V 336488199111198603 一边连连拍 -436 鲁M28B97 454091196810311127 取而代之的是对自己的无比的憎恨感。 -437 沪P1KC4M 541184199911045530 望了望时间,已经九点半了,肚子突然咕咕地叫起来,苏文这才发现,从昨天中午 -438 陕CSNLF1 635047194705247717 望着还熟睡的人儿,他长长地叹了一口气,走进厨房 -439 蒙OS0IGB 451001201102269717 <二 -440 晋FH5OYB 659076196904204790 迷迷糊糊中,好像有人为他擦汗,翻身,为他 -441 琼O7BGA0 541727201508166577 藤帆醒来的时候已经是第二天的 -442 闽IZDGYV 460014198006021168 睁开眼的时候发 -443 闽OAHX8L 546461197709022097 推开卧室的门,客厅里也是空荡荡的,可是明显的会看到客厅比之前整洁了好多,藤帆望着客厅的沙发,沙发上干干净净的,坐垫放在该放的地方,书叠 -444 辽WNTA1A 332039200004181365 老师 -445 黑WRKGY3 657444196302049982 厨房里传来一些声音,藤帆蹦跳地推开厨房的 -446 豫C52SO9 226997201305110063 午后的阳光透过厨房的玻璃照进来,原来显得没有生气的厨房在此刻看起来竟然是那般的温馨,站在锅前的男人背对着他,男人的衬衫有些皱, -447 蒙HJ6J8B 313557196206149721 藤帆的脸上露出好 -448 桂GAR775 445341199803019820 “老师!”藤帆的声音永远是快乐 -449 闽UASSDU 417810197305283884 “……”苏文望着自己腰间多出来的两只手,“不好好休息,出来干 -450 鲁SZBUID 650654197411108145 “我睡不着了。我的烧退了。”藤帆把脸凑到男人的背上,贪婪地呼吸着男人身上好闻的味道。那动 -451 蒙PJBB4D 426174196009026546 “放……放开,我 -452 桂T6PSQJ 453006196109251312 “我不要放。”藤帆把脸在苏文的背上蹭来蹭去,甩赖地抱着他,苏文往左边走,藤帆就跟着被拖到左边,苏文朝右走,藤帆跟着蹭到右边,“老师你真可爱。我舍不得放开了,老师 -453 浙K5RCZ9 230473198110056439 怎么办 -454 贵GOZNQQ 650169200307294364 那声“怎么办”带着糟糕了的语气,有点软侬侬的,又像是带了一点的鼻音,让苏文的 -455 湘KSZDA7 456256199512083995 我舍不得放 -456 新DG2LDA 816891195904095805 锅 -457 宁UINA26 375279194203086845 “蛋炒饭啊……昨天到今天吃的全是蛋……”藤帆蹙着眉头小小声地抱怨着,然而当他接过筷子的 -458 浙X0RKUY 332786196909248572 < -459 吉TNKVJZ 446462196908120688 隔天的物理课。 -460 赣BUD0OT 235280196909064389 离上 -461 鲁J5NR3I 514066196406115870 “老师——”跟着他跑过来的男生是藤帆,跑得气喘 -462 粤YJJOJM 115983196308302894 “老师,我们一起走吧。”藤帆伸出手就要去抓苏文的肩膀。苏文下意 -463 闽VR0JIA 465502197207027349 藤帆望了望自己落空的手,那神情似乎有些受伤,然而很快的,他的脸上又 -464 鲁PDDSBQ 365346200201026700 那双手紧紧地抓着他的身体,苏文的手臂像是一下子敏感起来了一样,那手臂上不属于他的手指轻微 -465 湘LMVI1A 361974200711192675 “拉拉扯扯,像什么样。”苏文 -466 鄂S16FS0 504791193910244884 “这又有什么。”藤帆明显的是不满了,更加挑衅地抓着苏文的手, -467 琼OK0VQ7 521705199809309228 一路上有同学与师生迎面走过来,对 -468 新WTSOR8 139818198005058981 苏文全身都有些 -469 沪JN7KVT 822774201202228969 藤帆就有些不高兴,在碎碎念,“老师 -470 桂W3JBJQ 813978194207317513 就这样在众 -471 浙NK3FUO 340962196812195726 苏文几乎是逃也似的挣扎掉藤帆的手,逃到讲台上,努力 -472 鲁HDQ0TT 445001197004090419 而藤帆一进教室就对着前几排的同学大声宣布道,“昨天老师在我家噢! -473 琼ICVAXG 638831201205082956 “咦 -474 京E03MYA 313143201102288978 “当然,老师一听到我生病 -475 冀ICB2YX 537700197109132814 “做,做做做——”前排的女生像是学舌的鹦鹉般重复 -476 沪GTVKNV 230053198312247591 正在努力调适自己的苏文一听到这话,一下子回 -477 晋IMAL0L 145235200410125774 “啊呀呀,老师您又看我了。”藤帆又是对着苏文抛媚眼加飞吻不断。他的动作是如此的夸张和坦率,以至于苏文只有转过头去闷声闷气地 -478 川V1VGSM 461416199606097346 < -479 沪XDSX54 431799193803075108 下课后藤帆奇迹一般地并没有跟上来,然而当苏文走到停车库的时候,却发现藤帆早 -480 宁LC1OVP 310231199610225858 一看到苏文走上来,藤帆就伸出手 -481 琼I1SVTV 331743198003281950 苏文吓了一跳,“干嘛 -482 新APQRNN 635497199409187903 “钥匙啊,老师我们不是说好了要 -483 晋ZRI1BR 618614198308064469 “给你钥匙是可以的,”苏文找钥匙,“可是你不 -484 皖C49DZ1 113598194707288927 “我知道啦。”藤帆应道,把车门打开,坐上去,苏文想起 -485 豫JBRKD7 427137199203209822 “知道啦知道啦。”藤帆把犹豫不决的苏文拖上车,“老师你有点罗罗嗦嗦的也,难道老男人 -486 贵J8GX69 529075193208238036 那一声老男人一下子刺入了苏文的心底,明知藤帆只是无心,而且可能更 -487 赣TUU88M 610630198011052745 藤帆三岁的时候,苏文 -488 贵CTIBBS 339695199207060307 藤帆现在十九岁,苏文三十五岁 -489 琼TNC0RF 826682200903237943 苏文第一次明明白白地看到了自己 -490 赣MJX102 321965193806088687 忽然苏文感觉到一阵反胃感,他连忙低头去 -491 青SGH2ML 316377198806273918 “哎呀呀,被老师逮到了。”藤帆的脸却是笑嘻嘻的,“老师不要害怕啦,我开车开了好几年了,老师的车子很好啊,我一开心就不小心 -492 鲁MDJJTI 226536195412257324 苏文铁青着脸瞪着 -493 湘YZ8DMB 450663196002144398 藤帆愉快地开着 -494 甘XJDMKS 427023198001073278 望着 -495 冀SR570U 461349197610305677 “吃饭,我们来共进午餐。”藤 -496 粤SNA8QX 132970195301018713 午餐确实很不错, -497 豫TWAD45 536464201101205829 牛排很嫩,蜗牛很鲜美,但是看上去就是价格不菲的样子,苏文并不是没钱的人,只不过不大会享受,然而西餐也是吃过几次的,那样的料理那样的味道一尝就知道会有多贵,更勿提进餐当中藤帆还让人开了一瓶红酒,一瓶八几 -498 琼FKN5WC 141099197001054391 吃完饭后藤帆又把他拉上车。对于藤帆很容易就把他的车子当成自己的这一件事情,苏文一 -499 新O3O1HC 822299201212270621 坐上车子,藤帆很快的就发动车 -500 贵C6P53H 540952198302204800 “约会!我们去约会!”藤帆无比快乐地高声道。可能是午餐的时候喝了一点酒的缘故,藤帆似乎很兴奋,又把车子开得很快,下车后又拖着苏 -501 粤F74HCR 128124197012082889 已经是下午三点多了,酒吧应该是刚开始营业,可是这里却早已经是很多人了。苏文进来的时候是被藤 -502 黑A5LEKD 816703197907204380 “小帆,又带人来了吗?”藤帆一进门,吧台上就有人招呼他。看起来藤帆也像是这里的老客,他轻车熟路地拉着苏文到吧台,吧台里的年轻男人一下子推出两大杯啤酒来,“不不不,给我们苏打水吧。”藤帆道,“他好像有点 -503 沪THOXTA 504693201108207478 “这次的好像不怎么帅噢,比以前的差了一点点。”那吧台上的几个人 -504 浙HLXR3L 151873201508096833 一进酒吧,苏文就有一种不适应的感觉,这里的灯光太暗,气氛太暧昧,男人与男人之间打量的眼光太不一样,尤其是这几位与藤帆对谈的男人打量他的目光,让 -505 桂OHFTPT 629299197004179460 “咦?不帅吗?”藤帆接过苏打水,递一杯给苏文,热切的目光凝视着他,“可是 -506 豫WQRZCM 536508195912273285 苏文 -507 京E38U27 824207193403124475 这里的藤帆太过陌生 -508 新WDJY1X 625597197807081027 “咦,老师你为什么要走?”藤帆追上他,把他拉 -509 辽HMFZX8 810122198105266910 苏文瞪着他,一字一句, -510 粤CXZCNI 637127195810121719 苏文在发现自己是同性恋的时候就是十九岁那年,在那之后,受罪恶感与愧疚感影响,他一直都像个清教徒一般过着禁欲的生活。又 -511 藏I5UOQG 448346195809263224 “咦,为什么,老师您可以再待一会儿嘛,这儿很好玩的 -512 川WZ6XAW 416351199508292978 苏文站住,不知道 -513 桂M4C02X 463612194701054348 “咦咦咦,老师你是吃醋了吗?”藤帆显得很开心,灯光下他的脸笑盈盈的,眼睛亮晶晶的,“安 -514 津XYXNRU 424780198609222285 苏文仍然在瞪他,“你就是在这儿随随便便地跟陌生人交朋友?万一——万一遇到危险怎么办?”话一说到这儿,苏文突然发现他自己 -515 鄂XPU4TK 343341194509307823 藤帆像是受宠若惊,“老师您是在担心我吗?我真感动。”他挨过来在苏文身上磨磨蹭蹭,“老师——”那拖得长长的音调更像是在撒娇,“那今天晚上我就跟老 -516 浙G9W7O2 157726197307201135 苏文仍 -517 沪K3A3J3 504704194911144472 藤帆所说的很好玩的节目原来只是几个男人上演肌肉秀,还有几个人妖的艳舞。随着节目的进行,场内似乎 -518 甘LD9XUX 232161198506243411 藤帆的眼睛在 -519 藏UBX5O9 440492195407224887 藤帆的话总是很开心很快乐的 -520 冀FKTGMF 377459195810109184 藤帆跳的简直就是贴面舞。磨磨 -521 云BDKDMS 427986193104136291 也因此,他跟着他跳了一曲又一曲,虽然苏文觉得 -522 赣KETU77 529883193909274257 苏文看到有人在跳着跳着,就不知道消 -523 皖N3KOHZ 456621193212237502 一想到那些人可能在阴暗 -524 冀SWD9K6 500907200401051878 看到这个酒吧的灯光这么的暗,似乎到处都有角落是看不到的,不知道那里会有些什么样的人,会有着什么 -525 藏PMYYPG 140737200711231774 苏文忽然间感觉到耳朵的轮廓被人舔 -526 藏KXLYHV 218716197004089020 藤 -527 宁I7SAYU 527656199709049002 这温情的气氛之下的藤帆像是有点醉了一样,跳着跳着不断地把身体贴在苏文身上,蠕动着大腿与大腿磨蹭着,就像是蓄意地要引起苏文的情欲一般, -528 京T8NDZP 450471196608181062 “藤!帆!”被偷袭的苏文恼怒地瞪他 -529 粤IPGGSB 511647193611025282 然而 -530 甘P0TSP4 135497197312060859 苏文低下头 -531 川Z6XUSH 335340195603222249 “这家酒吧有好多房间噢。”藤帆把鼻子 -532 苏MG3QE6 534369195402170122 “… -533 晋KFNA7T 233755197602040883 “所以老师我们也去吧。”藤帆 -534 贵EVIWC2 619413193704055164 苏文一把抓住他胡乱划在他胸膛的手指,狠狠地捏住,狠狠地甩开,“开什么玩笑!”愤怒地摔下一句 -535 津LRAQ3A 376742193601180864 这个酒吧从头 -536 青IDEKL8 411315199311169982 “老师?”藤帆望着抛 -537 晋UIJDXT 415519196809188353 其间撞到几个想上来拱讪的人,藤帆连道歉也来不及, -538 粤A7N5KJ 613223193603086840 苏文上车,仍然是怒气 -539 鄂OSNUAU 215380193402241521 他竟然可以,竟然可以 -540 琼E8LXEK 143198199308096984 “老师!”藤帆跑出来,坐 -541 沪BNZ3LS 360629193403075183 苏文转过头来怒气冲 -542 浙MMRE0X 457582201303071412 “老师您怎么可以这样说呢!”苏文大声的骂他令藤帆有些不高兴,“我不是说过了我是要看是不是自己喜欢的嘛,不喜欢的人,我是不会跟他们做的。” -543 粤VIEKDD 519135200902041037 苏文知道自己不该生气,然而他控制不住他的怒气,他恶狠狠地瞪着他,问:“你喜欢 -544 晋TB2OM6 351027200301251713 “老师您是吃醋了吗?”藤帆一下 -545 晋X09B0T 540503195103198030 “砰——”的一声,苏文 -546 宁P2GVV3 225209194912242276 藤帆望着车门缩了缩头 -547 晋REB4B3 131766199502152638 “老师!老师我没有啦——” -548 桂X1EFXK 115461196912149764 男人走得很快,带着一身的怒气,藤帆用跑的才能追上他。“老师我很洁身自好的噢,我才不会跟那些男人做呢,我长大 -549 桂ZCQ84O 213558196311180500 苏文停 -550 青COY2YD 516020200811228496 藤帆举手发誓,“我不是放 -551 青KAKGUY 423160198212126485 看到苏文 -552 渝RT81AR 349359201312105665 苏文抬腕看看时间,才四点半,然而发育中的男生总是消化极快的,他看看左右,这才发现自己在不知不觉中 -553 蒙XDI1OM 517157198201200148 “我们买些东西回去吃火锅吧。”藤帆指着路的尽头的一个菜市场。说完就率先大步往 -554 藏Y56B1S 423421197806063220 买了一般火锅中都要放的海带、昆布结、蟹肉棒之类的,想到藤帆的 -555 浙NIU1MS 142791197507054328 苏文在仔细了比较着两条鲜鱼的时候,在他身边的藤帆忽然又吃吃笑起来,苏文不解地转过头去看他的时候,藤帆悄悄地咬他的耳朵,“老师你这个样子好像 -556 桂Z7KA8D 445923201109191307 苏文有些气恼,然而更多的是甜 -557 桂LSGIQ0 461691195707083025 < -558 津C2A6RV 527485195102282810 回到藤帆住的地方,忙碌着把火锅弄好,再加上藤帆不停地在一旁捣乱,等 -559 冀YE7C76 460331201303037067 苏文在厨 -560 京H8Y8NB 366134193812185520 “老——师!老师老师!苏文!苏文苏文!”藤帆叫道。 -561 鄂XYMK69 329633200912138327 “没事叫什么叫!”苏文觉得脸上有些辣辣的,因为自己的名字从那 -562 豫AY69KZ 810376199203295924 “苏文!苏 -563 鄂JHCRYN 134993200512217057 苏文刷完锅洗好后要出厨房,可是藤帆却堵在厨房门口,他笑嘻嘻的看着苏文,“老师,现在十 -564 辽CNIIBZ 372340197409229220 “很晚了, -565 新SJ4K0V 529474197605281303 “不——”藤帆霸道地堵在厨房门口 -566 皖J8LYTI 458768193304240478 苏文有些愕然地抬起头望着这个 -567 沪L03BUA 445477194001063398 藤帆吃吃地笑,酒足 -568 晋DGO3HT 648103201008167465 苏文 -569 青WMZM2M 344909194607298162 “我不要。”藤帆近乎耍赖地张开手抱住那个想逃出厨房 -570 川QX6ENG 356958198205060008 他想禁锢他吗?苏文一下子警惕起来。然而藤帆 -571 浙Y9XFKI 463471193308142520 藤帆抱住苏文,头靠在这个男人的后背上,有些模糊的声音传过来,“老师我真的很羡慕你的子女呢…… -572 闽NH9WEC 221057194401067313 不知道为什么,这句话奇异地让苏文的警惕心 -573 桂GGHDJS 638617194406142961 苏文拉开缠着他的手臂,“我没有。”他说 -574 冀AGNCGJ 500674199707151485 “嗯?什么没有?”藤帆跟着 -575 琼TWD1T8 321701193507250536 “我没有子女 -576 桂A8CFM4 631600198102094430 “啊呀呀,真好!”藤帆满足地叹息道,扑 -577 闽OXGS4D 656136195503259694 “别乱来 -578 吉G9FHLE 334114193805158680 “呜呜……我好伤心……”然而藤帆完全看不出有任何伤心的样子,藤帆坐到沙发上,挪一挪,屁股挪到苏文旁边,苏文有些不自然地往一边移一移,藤帆马上 -579 津ZCY6PL 517408199401262857 “没有啊。”藤帆无辜道,随即坐得更近,“老师我们来谈心吧,谈 -580 晋D5FDB4 621281198209050106 今天的藤帆似乎话很多,是因为中 -581 藏S70Z6R 641824197803314555 苏文有些不自然,因为藤帆坐得是那样的近,以致于两人的身体有一部分是贴在一起的,虽然隔着衣料,但是藤帆的体温还是传过来,处于发育期的年轻人的体温似乎都要比他这个年 -582 云I90A5L 130215200810015334 “谈老师孤独一个 -583 吉A331MF 540234193810254613 “我不会。”藤帆碎碎念好多,看到苏文尴尬别过头去,本以为他听到这些话会气恼,然而在说了好 -584 贵TCMR0F 656267194103285963 “啊?”藤帆一时转不过弯来。 -585 辽IZU8PV 647171199111199270 苏文的脸有些红。“我不会在做的时候先把衣服折叠好。” -586 鄂UXG5D7 531220193511083706 “咦——”没想到苏文会回答他的话,藤帆兴奋地叫起来,“那老师您都是怎么做的呢?迫不及待的就把衣服全扒光?您会在地上啊厨房里啊浴室里做吗?老师你都是想着什么类型的男 -587 赣SJIBAP 450435200803261048 苏文更加的窘迫了,他 -588 冀TBNPQB 620910200612232515 然而藤帆更 -589 藏HD7IOU 421882201001149932 苏文大窘,骂 -590 赣ZLH0QO 467117193109083670 “那就说一半吧,一半一半。”藤帆兴奋地举起手指来,“来来来,先说第一点,老师您有没有在床之外的地方做过?第二点,老师您都是想着什么样的男人解放的?第三点, -591 贵T5ROVD 526487198101245313 三十五岁的物理系教授怒瞪着他,“藤!帆!你都在 -592 桂XYL0WY 434715195001098482 “这个不是什么乱 -593 蒙MCQFDE 210429193202215984 苏文转过头去,“你再说 -594 晋VK0NSM 508573198005065571 “那不说不说。”藤帆连忙道,唯恐苏文要离开 -595 京YORUTX 450814199012234755 苏文的唇张了张,有一句话,他一直想问,然 -596 津OGFEVF 616580200005248638 “来……来说说你的事情吧……”终于,苏文道 -597 甘ULM6FP 422906196111047781 藤帆显得很兴奋,“啊呀呀呀?老师您终于对我感兴趣了吗?”藤帆托着 -598 云IAFOJ3 456815199802058346 苏文张了张嘴,终于,他鼓足勇气说道,“说说 -599 沪E79O18 528637199809243044 “啊——老师说的是我三岁时被男人强暴的 -600 贵BS0KO9 520365198808094049 “……你……”苏文小心地观察着藤 -601 云YRGKFS 127176200412189114 “恨啊,怎么会不恨!那种坏蛋!”藤帆一口接道,他没有发现在他说出这句话的时候苏文的脸 -602 赣XYKYOM 427433196604094529 “……你……恨……到想杀了那个男人吗?”苏文全身冰冷,然而这是不得不问的 -603 桂GG4LCX 234938200507153924 “杀了他?我为什么要杀了他?杀人可是要 -604 浙PGJCN9 501894194009046247 苏 -605 粤XSX8D2 812945194403316220 “如果让我再碰到他,我会把他抓起来,关在小房间里,每天都叫男人来狠狠地X他,不给他饭吃,不给他喝水!每天心情好了进去鞭打他一次, -606 吉CUANJO 450493201407083498 苏文听到一个声 -607 津AWRIUU 433884198810245355 “记得!怎么会不记得!我狠狠地想把那 -608 津QE5XTY 314911196704309362 苏文全身冰冷。怎么办?怎么办 -609 苏URJQ6V 370054198503038580 一想到自己会被关在其中一间房间,每天遭受着藤帆口中说的那样的待遇,那样的话,自己一定会承受不了的吧,还不如死了 -610 贵D0I8BY 512043195711034031 除非— -611 晋HG6HQL 526409195706287566 除非 -612 皖I4OP2F 530519195307309032 苏文的心里突然冒出一个念头来。如果在这里 -613 皖B2NP3W 654301197411039375 一年,也可能是两年,也可能是十年二十年,只要没有人来这里,就不会有人发现藤帆的尸体被锁在一间紧闭的房间,而那房间里 -614 宁HOV0SL 428337200611295075 这也不是很难的事情! -615 津EFQVHQ 533713200704202618 苏文发现他的目光死死盯着沙发前面小茶几上的水果 -616 贵XHXPMF 436088196606103438 “哎……”藤帆叹气,“可是我越是想把那个男人的样子记住,我就越记不清。再说我当年才三岁啊,能记得多少,那个男人也不到二十岁吧,看起来文文静静的,也不像是很老,可是十六年,十六年会让人改变多少啊,现在就 -617 云WYSU7Y 232754200501180010 现在就算是那个男人站在我面前 -618 鲁C4INO9 111796198809019704 那最后一句话听得苏文心惊肉跳的。因为他这个强暴他的罪犯确实就出现 -619 沪GC5GS5 128844195708171614 “其实老师,说实在的我很可怜很孤独很寂寞的。”藤帆一下子转过头来面对苏文,吓了他一大跳,几乎要惊叫起来,然而当发现藤帆看向他的目光没有一点像是认出他来的样子,苏文的心才落回到胸腔,“从小,我就不是我妈 -620 陕XB2ZTO 411789193805083706 藤帆喃喃, -621 湘UZUL2B 137038193701070190 “……那个时候我很讨厌幼稚园里的老师,因为那里面都是孩子,一堆的孩子,所有的孩子的家里都是有钱的,可是他们的父母会来看他们,会来瞧瞧他们,他们来的时候,会给那些老师们一些钱,说是小 -622 鄂G46D2U 517237194706123974 藤帆自言自语了一会儿,看到苏文听得很专注,不由得偷偷摸摸伸出手来摸上他的大腿,嘻,成功,没被发现,“所以那一天,那个男人出现的时候,我真的很高兴,因为他一点都没有忽视我,我不断地吵啊闹啊,那个男人很温 -623 豫TBFKUP 545028196207011387 藤帆的手指爬爬爬,愉悦地沿着苏文的大腿往上爬,“第二天,那个男人再次出现的时候,你不知道我有多紧张,我一直看着他,就怕他认不出我了,或者把别的小朋友当成我了,可是他一下子就 -624 湘P49HFU 823720196602264600 藤帆嘻嘻笑开了,“他很笨哪,以为拿出一颗糖来就可以很容易 -625 赣REAAEI 330079193112076517 苏文有些狼狈不堪。低下头,视线刚好 -626 沪OS9QP9 239110197406089398 “咦咦咦,怎么我一不小心就把手放到那儿了呢。”藤帆叫得很无辜,然而那手却仍然大剌剌地摸到苏文 -627 吉Y7UL5W 512278201203144245 苏文想把藤帆的手移开,然而藤帆马上接着说起话来,那话语一下子就让苏文的注意力被转移开了,“除了那个男人,老师,我就再也没有跟别的人做过了呢,老师你相信吗?”藤 -628 皖EZHIHG 128200199511087930 “讨厌啦,老师你捏我的手捏得好紧呢 -629 渝U32PCU 615381200504221418 然而根本就不同于正在性欲旺盛期的男生,苏文的脑中根本就没有想到做不做的问题,他关心的是他十六年来一直想知道的事情,“……你……后来…… -630 贵TBCQ4J 112526194207138844 “老师你很关心我嘛。”藤帆笑眯眯,“我就说老师你暗恋我嘛,第一堂课那一天看到我的时 -631 蒙J6L94M 610984195011195504 “那时候……”藤帆说一大堆,却根本就没有回答苏文的问题 -632 辽SRU8MR 541159197709033112 “老师你的脸色有点糟糕啊。”藤帆瞄准时机就摸上苏文的脸,“啪——”的一声,另 -633 陕RZWRD2 426965195612270407 晴天霹雳一般,苏文怔在那里,“喜…… -634 皖S904J5 424724201006138970 为什么?为什么?不是刚说了恨那个男人吗?不是恨得连死都不给 -635 陕Q7NI30 444852197012022628 “咦,老师你不专心听我讲话噢,我很早之前 -636 蒙TYOPEB 157167200102159542 苏文怎么 -637 赣UEX9P8 312867197806157212 “为—— -638 豫JL13O4 120208196008045495 “嗯?什么为什么 -639 赣AEO1O1 527675201203256593 “为什么会喜欢那个男人?”苏文的怒气像是一下子爆发出来一样,“那个男人不是强暴你了吗?不是把你丢在那里根本就不理你了吗?为什么还会说喜欢那个男人?那种男人!死了也是活该!有什么可喜欢的——”苏文一下子 -640 川QWDI9E 621293195911188819 “为什么说死了也活该呢!”可能是手被握得有些痛,藤帆有些不悦地大声道,“老师你在胡说八道些什么!就是强暴女人也只是被判个三到五年吧。更何况是对男人,就算我是小孩子,猥亵罪最多的也判不了几年吧。就因为那 -641 沪CAKZ8F 468009198702247199 苏文一下子震惊 -642 津X6LHD0 623071197103131170 “老师是不是 -643 蒙RB898Z 532583199606249049 “想……想见……”苏文全身都在哆哆嗦嗦,刚才汹涌而上的杀意一下子消失掉 -644 琼BNGI53 310913195205205913 “嗯。就算他做出那种事情,我还是想见他啊,因为这个世界上只有他一个人会注意到我。我真想跟他一起,如果那个时候那个男人又出现在那里,当时的我就会跟他说,让他以后不要 -645 沪A7L24V 330859193911152566 “好……好多次……”苏文脑中一片空白,像是鹦鹉学舌一样呆呆 -646 京U0QJRL 223631200509141929 “嗯。有一个月左右吧,我天天都去,可是我都没有再碰到他。”藤帆的表情有些落寞,“我后来长大了,就发现自己不再喜欢女生了,我在国中的时候,第一次遗精就是在梦里想着那个男人的时候,后来有一阵子我经常去那种 -647 苏RADJHW 627595200808011610 “打……打手枪……”苏文的脑子像是停止思考了一样, -648 甘DC73TC 820558196004190175 “老师你有些傻乎乎的啦。嗯嗯,保持这个样子也不错,很可爱的噢。”藤帆望着他 -649 晋KO0ZTJ 519454201205275957 “只……只穿内裤……”苏文突然惊醒过来,条件反射地就破口大骂,“ -650 新W4YE85 512319193011170023 “啊……没有吗……” -651 川GFYNM1 360258194807080142 “为,为什么?”苏文突然问 -652 青X0U8IW 652461199705130653 “咦?什么为什么?”藤帆又有些转不过弯来,“老师你今晚经常问出怪怪的问题呢,没头没脑 -653 吉VWR0TZ 531972195507237633 “为什么……会……”苏文有些说不出口, -654 沪ZSWHB6 354938194406189600 难道藤帆发现他长 -655 贵DH9EO9 340487200902258459 “笨死了老师你!”藤帆有些不悦道,“我不是说了嘛,我当时会喜欢上那个男人,因为 -656 渝OOAVK0 317828199401033154 “ -657 川D3HE7Y 152427194307152134 “咦?什么 -658 粤HWCZV7 230967193412310108 “那些……说喜 -659 京EI7087 350614196702170915 “才不要呢!”藤帆撇撇嘴,“那些人跟老师不一样的啦!只要有比我更帅的男生出现,她们就尖叫着跑走了。老师才不会那样呢,就是有比我更帅的男生出现,老师也不会多看他们一眼的,嘻,因为老师对我一见钟情!”藤帆 -660 沪UQG2YL 622862200509029841 “……奖 -661 皖M07HFR 346338198110279840 “是啊是啊,我抛了那么多的媚眼那么多的飞吻,老师您都 -662 豫H7V4U1 420970193505042376 三十五岁的物理系教授有些羞怒,“那是在上课!上课!上课的时候谁会做那种事情 -663 新QXZQ32 459331195004225650 “咦?那下课的时候就可以做那种事情的噢。”藤帆立刻积极地 -664 闽Z759NB 630635197001198935 望着近在咫尺的唇,苏文脸上像着了火一样的,“ -665 辽DMHBQ8 642356193104153574 “就知道嘛……老师就是在下课也不可能做那种事情嘛……”藤帆道,又想起快乐的事情,“不过我知道老师您很喜欢我噢,我那个时候生病,打电话给同学,就是想 -666 桂BUKWKS 330887199611182041 “乱,乱讲!”苏文脸上有些挂不住 -667 桂TOZCDL 429421200310027078 “嘻,老师您就不用不好意思啦。”藤帆的手指在苏文的腿上快乐地打转,“其实那一天老师在敲门的时候我就知道是你来了噢,因为除了老师没 -668 贵HYBR19 658449195306253568 “你——”苏 -669 晋SFF35E 323710197205210894 藤帆 -670 闽Q87LHS 517927193609133555 “你——”三十五岁的物理系教授怒瞪着眼前的古灵精怪的学生,“ -671 鄂QHJON2 357782194112067387 “啊呀呀,是吗?怪不得那天我一 -672 鲁TBWMSZ 325429199604058208 “制——制服——”苏文结结巴巴,“你,你脑子里想 -673 琼QD6IGC 347389196302113333 “是啊 -674 浙UI8UXW 436049201005221124 “你——”苏文简直又好气又好笑。 -675 皖DVRE8D 429687193906040675 “所以老师,我们现在就来做吧。”藤帆望望时钟,“啊,凌晨两点了呢,时间虽然晚了一点,可是也不错啊,现在气氛也不错,野狼在嗷嗷叫噢,老师,你很危险噢——”藤帆 -676 蒙PPOKD1 333772200001218849 “咚——”的一声,两个人摔倒在地上。因为原来藤帆一直地坐过来,苏文一直与他保持距离,不知不觉间就坐到了沙发一端,现在藤帆一下子扑过来,苏文措手不及,被扑个正着,重 -677 桂ELV5E0 119251193711292074 疼痛的感觉以及地板特有的凉意从苏文的后脑上传过来,虽然铺了很厚的地毯,可是那么重的人一下子摔下来, -678 宁KIYOQX 416046197311200826 “啊——一不小心就把老师扑到地上了。”藤帆自然是没有感觉到痛,因为他身下有 -679 桂EZR9OY 642954194605069674 “……”苏文望着还赖在他身上根本就没有要 -680 藏Q1DP5L 149764195209159072 “很痛吗?老师?”藤帆又问 -681 宁IFF7G7 511533196307199875 “……还好……”苏文一说完,藤帆就立刻把苏文摊手摊脚压住,无恨愉快的声音在苏文耳中响起,“那老师我们就开始做吧!”藤帆明 -682 湘HGVDKC 442016197908215416 “……”本来是没有拒绝的意思的,然而当藤帆的手指一伸进他的衬衣的时候,苏文突然觉得他自己满身污秽,他剧烈地反抗起来,“不——”他叫道。 -683 闽UIAG4X 810341197307252389 “不要害怕 -684 闽M16R12 620811193103011169 “不!”苏文一下子坐起来,推开他,“不要这 -685 京UJ0JEI 620243199007081994 “咦,又 -686 冀VCNKGM 354938194207293510 “明,明天 -687 贵S7KFHP 530285198512171884 藤帆明 -688 桂Q8ZAFK 133321199712134787 “我……”忽然就有一股冲动让 -689 黑GYNP3T 122460201106143644 “……我……”然而苏文发现自己说不出口。虽然藤帆这样说,可是当他真正知道苏文就是那个人的时候!他会怎么做?苏文不敢想象那一丝的可能!当当年的罪犯真真正正地站在他面前的时候,藤帆会宽恕他吗?只要藤帆还有 -690 闽PIWLJX 501252195511309051 “哎,为什么老师您就不能冲动一下下呢。”藤帆遗憾道,他的这句话让苏文惊得要 -691 湘XLTD07 828415195510029963 “开,开什么玩笑!”苏文 -692 琼J0S12L 428712198805293769 他也根本就没有脸 -693 冀A8YP34 112746199705069851 被自厌自弃紧紧抓住心的苏文根本没有发现 -694 川MRW27P 337708198309236758 “哎,算了。老师不想做我就不勉强啦。”仔细地看了苏文的表情,藤帆突然说道,“睡觉吧!老师我们一起睡床吧 -695 沪UXBMUA 137560199212287625 “不……”苏文急迫道,“我要走……我要立刻就走……”他没脸面出现在这里!以后他都不要再出现在这里了!他要马上离开!他这么 -696 冀SI3HCA 623781199503079879 “咦,老师您会说 -697 吉YIAKPM 628561196411172887 “我……我睡沙发…… -698 黑QMRZSS 219792195307306115 藤帆又仔细地看了看苏文的眼睛,“老师您怎么了?怎么突然间好奇怪的样子?刚才还不是好好的吗?难道是因为我差点侵犯你?安啦安啦,沙发睡着不会舒服的,跟我一起到床上睡吧,我 -699 赣BUJUIK 500068196702150518 “我要睡沙发!”苏 -700 苏WL1D0T 122009196401234578 “……”藤帆看了一眼他,很有些苦恼,“老师您有时候真的有点固执呢,难道老男人都会很固执?虽然有那么一点点可爱,可是这真的是伤脑筋的事情。哎,那我就睡床吧。”藤帆突然调皮地笑了,“老师,我卧室的门不关噢 -701 甘YXVJNM 447277195012127961 闻言,苏文抬起头来 -702 苏DP9E03 506135199204238999 十九岁的男生 -703 黑R2QG0A 320151198404097259 “砰——”的一声,苏 -704 川WG9D86 329490199506191703 这个恶 -705 苏N91V2P 113347195602200704 第五章 -706 藏OYOFHX 112671196604167710 <一> -707 琼LAJDOC 816049200609268920 第二 -708 晋I6EH14 342793199908267564 刚开始的时 -709 皖PDOV3I 325802194905078557 脖子处的地方热呼呼 -710 沪KUQSCM 618737194002267534 然后是有手指像弹钢琴一样快乐地跳着到了他的脸上,眉毛鼻 -711 津F7IT9N 827042197507244665 于是苏 -712 云JOVNJE 459553198003259781 苏文睁开眼的时候一下子望见一双很大很漂亮的双眼,那双眸是如此的澄静透亮,以至于苏文有一瞬间觉得他看到了天堂。然而下一秒他就马上想起自己这种人,死后根本就不可能上天堂的,于 -713 鲁G8RIET 147160197207168427 在记忆里的小男孩的眼睛就很大,明亮的,带着稚气又带着一丝说不出来的感觉,苏文只记得第一次看到那个小男孩的时候,第一眼就被那双眸子深深地吸引住了。不知道是什么样的原因,只觉得那双眸子给他一种非常异样的感 -714 湘K718OY 366414196804085246 “……老师……”藤帆轻轻地在苏文的耳边唤道,他的声音有些沙哑,磁性十足, -715 辽ZWFOOK 640452201404156283 苏文根本就没有听到藤帆在讲些什么,他怔怔地望着那双眼。如果——当初他没有去那个幼稚园,如果当初他没有遇见藤帆,当初他没有对藤帆 -716 闽TIAPL0 121629201012079597 可能他还不会发现 -717 冀U5XDZZ 624755199006167632 藤帆在苏文的耳边轻轻 -718 渝YMGEYS 466489196204064477 如果他是个同性恋的话, -719 晋U8OFUP 813707193105092115 爱… -720 晋YUAR88 648139201101172482 “三!”藤帆突然发出极大的欢呼声,那声音吓了苏文一跳,藤帆“唰——”地扯开苏文的衬衣,嘴里咕哝着,“不管了 -721 津S0WTVF 508866194206273748 “藤——”苏文这才发现压住他的是藤帆,而且更可怕的是,藤帆正性致勃勃地坐在他身上,性致勃勃地把手抓在他的皮带上,正努力 -722 辽NLJLKE 354622197811268332 “别——”苏文连忙制 -723 豫NW16T4 505254193311217024 “我要做!我要做!我一定要做!”藤帆把脸凑近苏文叫道,“我忍受不了了!我再也忍受 -724 青Z6QJ85 155850193003319730 “藤帆……藤帆!”苏文无奈地制止他,“不行的,我今 -725 蒙E0FXAT 375855197812130486 “老师您这个也不是理由噢!”藤帆不悦,“我不赞同! -726 湘M340CV 366539195108045088 “别这样……”苏文推开他起身,望见藤帆垮着一张脸,又望见他眼下的黑眼圈,不由得有些心疼,“去睡觉吧,好好睡一觉,昨晚那 -727 京IYD66O 640086198109047971 “我不要!我才不要!”藤帆抱住他 -728 津MXURJ8 826316197801019676 “不行的……”苏文道,“真的,我不能不去上课的……去睡吧……”他看到藤帆的脸上也有些疲倦之色。苏文自己也感觉到有点累,凌晨三点钟才躺下,这儿的沙发太软,他根本就睡不着,晚上听到卧室里藤帆在翻来覆去,他 -729 青W1CA7G 535758196108124641 “老男人!”藤帆被赶回卧室,被盖上被子躺到床上,他不悦地叫,“老男人!真可怜!要去上课 -730 琼QJDKQ9 547249194606041916 “别满口 -731 琼W8S4T0 652404197502151350 藤帆却像是叫上了瘾一样,“老男人!老男人!真 -732 川XQKJ65 525138196804114116 明知这个学生在嘲笑他,然而苏文就是生气不起 -733 吉WJRG8Q 227971193503209010 苏文整理好自己要出去的时候藤帆还在睡觉,怕藤帆就这样一睡睡到中午连早餐 -734 晋XUMLAG 630556197612250811 藤帆张开眼的时候就看到床边苏文在微笑着看着他, -735 桂ESJOEZ 357687195409062460 不知道为什么,看到这种情形,想到自己这一生中,都没有也不会再有第二个人坐在他的床边, -736 赣GTT4O9 133765196509165715 不是一般的吻,也不是情色的想要勾起人的欲望那样的吻,只是很渴求的,像是极力 -737 甘PMIQ51 311551197103228853 “老师,”藤帆的声音哑得厉害,他咳了一声,“老师您真蠢!”他嗓音干涩 -738 湘RMFVK4 643492200201127699 苏文还在喘气,在眼前的男生这样紧紧地盯着 -739 川AADDWV 533082195811187246 <二> -740 川H78VAY 373010194609289373 那一天中午的时候,苏文上完课正在往办公室的路上走的时候,又被人叫住。 -741 皖AI2VCE 520781198705210245 “好久没有见到你了啊。”何教授跟上来,与苏文并排走,“怎么样?最近你负责的项目进展如何?我听说你带的几个研究生能力都很不错的啊,其中 -742 青KF3XJZ 332459193602034435 苏文嗯了一声,对于学生的成就,做为老师的只是为他们感到高兴,苏文一点都不觉得做为老师,可以把学生的成就当成自己的来说给别人听。然而何教授想跟他说的明显的不是这一点,因为他看向他的目光让苏文感觉到了有 -743 琼PICEOA 415205196110137240 何教授终于忍耐不住说 -744 冀TCSUTG 335019195502280960 苏文停下脚 -745 湘OBUWJ1 515930194301071963 “如果只是普通的请教倒也是没有什么,可是那个学生的样子——看起来好像对你有点古怪啊——”何教授见苏文停下脚步专心地听他讲,胆子不由得有些大起来,“虽然在大学里,师生恋有时候也是有的,但是我们都觉得,嗯 -746 赣ZWWOPB 636433193701146735 以前一直觉得何教授就是谈不上招人喜欢,但是也不到令人厌恶的地步,然而今天,何教 -747 晋DC0USE 632409201108065814 “同性恋又怎么样!”苏文有些不悦,“他 -748 沪EGIEQC 530411195706184618 苏文的表情明显的也让何教授不高兴起来,他的声音也有些大了起来,“你这话是什么意思?我可是好心好意地提醒你啊!跟那 -749 藏EPJM1R 427747200701018067 苏文 -750 湘P373H3 137198197212316584 何教授因为苏文的话,还在生气,因为他认为自己一片好心被人当成驴肝肺,自己拿了热脸去贴人的冷 -751 云KSW1YT 510258200812205619 苏文脸色 -752 甘QJXGVB 444836200906227721 何教授看到苏文明显的是生气了,一下子也把话停了下来,两人沉默着走了一段路,毕竟是多年的朋友,不想跟苏文的关系搞僵,何教授又缓下声来,“你想一想吧,跟学生走太近总归不是什么好事情,我们也都是要吃饭的人, -753 甘JD9KEC 535405201106024867 苏文沉默着没说话 -754 甘DAGU2N 129359195908184021 良久,他抬起头,看到路旁的紫藤花架上,今年的紫藤花枯萎了干瘪了,然而那枯萎的枝条仍然紧 -755 闽URPUXP 221333199002220702 < -756 苏BIPM0U 617591198002206717 门关上的时候声 -757 甘TJMYQM 500128197408069445 床边的椅子上的鱼片粥散发出一阵阵的香味,让藤帆胃口大开,那粥吃进 -758 闽QZJH0Z 158685194304217820 藤帆今天早上没有课,躺在床上睡了一会儿, -759 湘Q7126M 361264198312237339 刚到学校门口就听到下课的铃声,想着糟糕,可能会逮不到老师了,藤帆连忙加快脚步,在苏文必经的路上,藤 -760 鄂JCFRD3 367860196210280677 藤帆一下子停住了脚步,有些调皮地,他偷偷摸摸地藏起来,苏文跟何教授走过他的时候他们俩都没有发现,于是藤 -761 晋NCPP2B 410643193002087219 没想到却听到那样可 -762 桂MZE86U 352742199208052099 那个何教授用着一种像是藤帆是一个同性恋是恶心 -763 闽XSLJFQ 125336194401073446 当听到苏文生气地反驳着“同性恋又怎么样!他又没偷没抢”的时候,藤帆不知道 -764 黑K1MFGV 229228198303153678 然而 -765 蒙NALBSZ 421863194607268683 正当藤帆想 -766 甘EZV17H 315651201507247912 藤帆的心里就有些 -767 桂ZCK6PR 230620201404058917 苏文脸色铁青地对何教授说道 -768 青URLE8N 138279197508209711 而何教授一下子就沉默了下来,跟在他们后面的藤帆也沉默了下来,他沉默地望着走在他 -769 贵EGZZPH 238168200308021981 当看到 -770 琼OCEQ24 331962195509146677 而在听到何教授开始拐弯抹角地提起他有个表妹,上次来学校看到苏文的时候,回到家向他打听 -771 贵WL4IS3 638829198602288205 藤帆气得想冲上去揍那个何教授。 -772 鄂IBT3NM 332850198904222859 表妹!哼哼!像他那种人,会有 -773 津WKAULG 462171197807139587 可是老师为什么一直 -774 藏G2WCLC 540183196008248503 藤 -775 川DM3LHD 368487200801231282 良久, -776 桂TF28L7 336118198602192405 一瞬间,像是晴天霹雳一样,藤帆的脚步一下子停了下来,脑中一片空白,他站在那儿一动不动。老师答应了!老师居然会答应!那种事情,摆明了就是相亲宴 -777 苏LBF9T3 138525198812111494 而原来走在他前面的两个人慢慢地走远了,与他拉开了相当一段距离,藤帆隐隐约约听到那个何 -778 冀V44GTI 124313197104133870 要—— -779 闽D826CO 150627194310261555 要被抛弃了!藤帆的脑中会是这样的一个念头。怎么会这样?怎么会这样?又要被人遗忘了吗?老师要抛弃他了吗?被这个念头所掌控的藤帆气得简直快要说不出话来,他掏出手机,狠狠地按着键,像是要把全身的怒气全 -780 冀TIZ1TO 427084195207302205 “藤帆?”那是苏文的声音。暗沉的,有点隔膜的样子,似乎有些遥远的声 -781 藏ZZMROY 119555195109046596 藤帆的眼底是一抹带着怒意的阴悒,连他自己都没有发现,那种阴悒像是有一点要濒临绝望一般,带着一点点的毁灭的倾向, -782 浙T63ZWB 114995194902048567 “……,……”电话那一端的人 -783 云NP5MPD 370340196410123074 他竟然在沉默 -784 沪DZPN96 648360198006219889 藤帆的手指紧紧地抓住了电话,两眼狠狠地瞪着前方的地面,他控制不住自己的嘴,藤帆在不停地说话,“我知道有一家餐厅的意大利酸辣汤做的很入味噢,离学校也不是很远,如果我来开车的话不到二十分钟就可以到了 -785 贵BG8ODT 425704196711164247 “……,……”电话那一端的人继续在沉默着,藤帆的心里涌出一股说不出的难受, -786 鲁PF7PQS 501425196903267597 电话那一 -787 琼KQ5YYU 614793195603246375 藤帆沉默了下来。 -788 沪JFD8BQ 818592200405193217 “……”话机里传 -789 津HHA89Q 369597195805113838 “砰——”的一 -790 青VQKN6U 464570193411222806 再也不要听!再也不要听 -791 京LOJ9PY 636232199512052204 然而还有旁边一直看着他,看到他打完电话才大着胆子过来搭讪的女生小心翼翼地问道,“帅哥… -792 苏KJIHBH 511053201408138108 “滚开!都滚得远远的!”藤帆忽然间暴跳如雷,大声地骂着人,“什么嘛!什么嘛!骗人!全是骗人 -793 宁GNQT66 144171198503092460 第六章 -794 冀KHYIGK 322209199506169131 < -795 蒙OXEY3L 144055193901287650 藤帆一个人吃着 -796 津JVZR5H 231665201107212079 这是一家装潢得极 -797 蒙Q8H371 525427194604159950 大厅里的吊灯很是富丽堂皇,每一张餐桌上都插着玫瑰,桌布洁白的,上面 -798 新AXRAQE 128215197209035661 藤帆一个人喝汤,吃很多东西,吃香辣蟹,吃得手上全是油,蟹肉很辣 -799 晋REZSX4 367705196508064969 藤 -800 京DUEMZL 378499197412169167 同样的价格不菲的红酒,藤帆开了两瓶。有一瓶甚至是酒店做为招牌的年代极久的红酒,藤帆固执地指明了就要那一瓶,酒店大堂经理说服不了,甚至出动了负责酒 -801 蒙TEIY7R 157120200206235188 藤帆灌酒,藤帆打酒嗝, -802 湘AL5L4A 411902196809225448 酒店大堂经理在藤帆喝的时候一直站 -803 川H9HDNJ 422686198509277313 吃到一半的时候藤帆 -804 蒙BIEO1K 512448199301137898 藤帆的大喊大叫吸引了在大厅的好多人,相当多的一部分人转过头来看着他,当看到大叫的是一个长得相当帅气的男生的时候,所有的人原来显露在眼里的不悦之色一 -805 晋XJ7Z1W 543784200808135416 甚至有的人在小声讲着,“真可怜,不知道是什么样的 -806 京QUIPB5 231995196602053895 而在大厅的一角,苏文震惊地瞪大了眼睛望着那个大喊大叫的 -807 青FE5AP6 815740197103086781 藤帆望见了他,一下子放下手中的酒,朝着他走 -808 吉DVJ7LX 458692194602217144 “藤,藤帆!”苏文一下子像是被抓奸一样,结结巴巴 -809 蒙DDQHRG 524859193009122647 “咦,老师原来也在这里 -810 闽AW91VN 614550197501073753 “大家都在看!所以你就装作不认识我了吗?”藤帆怒气冲冲,望向坐在苏文对面的女人,什么嘛,根本就不漂亮,这样的女人也值得老师推掉他 -811 新SRSHYY 822138201204039365 “你——” -812 冀QCB36U 610667195110169084 而藤帆却扯了扯嘴角,更加的毒舌,“长得实在不怎么样嘛,怪不得长到现在还嫁不出去!啧,身上的衣服倒是不错,可是穿在你这种人身上,就是再漂亮的衣服也是不如扔在垃圾堆里好啊。草鸡就是草 -813 桂A3Y4GO 346062197604260006 “别这样藤帆!你喝 -814 甘Q0GDD0 128866194701299303 藤帆转过头来瞪他,“老师你想维护这个丑女人吗?这样的女人有什么好的!”他转过头去鄙夷地看着这种女人,那个何教授的表妹已经气得脸色发白了,“真是不要脸啊!老师根本就不认识你,你就先看上男人了!一点 -815 赣T0GEVT 229746198112068947 “你——”那个何教授的表妹被他的话气哭了,哭着跑出餐厅。 -816 豫SYEJ4V 425837201110258657 “ -817 川WZF7UX 509361195701187623 藤帆转过头来,眼眶红红的,眼里全是血丝,他抓住苏文的衣领,“老师你不想要我了吗?你是不是觉得啊啊果然,跟我在一起很糟糕?是啊是啊,老师你是有头有脸的人,有名望,是堂堂大学教授,跟我这种学生在一起很讨厌 -818 吉YYZOYT 346413197305047775 “藤 -819 陕R54S0G 361075198412132941 “你讨厌我你就早点说嘛,为什么还装作一副根本就不讨厌我的样子?为什么?骗 -820 桂G6RI9M 511378193610169516 “ -821 新F6OQDA 659775200103072484 藤帆胡乱地抹眼泪,“你想支开我吧,我在这儿是不是让老师你感到很 -822 浙W178PR 141859194210112555 “藤帆你喝醉了。”苏文叹息着扶起他 -823 鲁MZ751N 428127198501264963 “噢。”藤帆望了他一眼,把眼泪乱抹掉,站起来乖乖地跟着苏文到洗手间 -824 冀IQY1BM 329000196910151934 男士专用洗手间很大,很干 -825 赣F602E6 428832194010029825 藤帆合作地 -826 鄂GHH25V 817569195901036829 苏文把手帕 -827 青OMWDQE 317265194010268322 藤帆站在一旁,望着镜子里 -828 沪OJHC6O 638334196703094819 苏文洗完手帕拧干,装进一个袋子 -829 浙MB95PO 327131196809097639 “老 -830 青TKNBX5 626911197012074844 苏文道,“我想上厕所。”其实苏文并不想,他只是想一个人静一静,而藤帆刚才在一旁 -831 冀ZXIZYG 652793194605153277 要跟藤帆分开……虽然一想到这个就感到心像是被割了一刀一样的痛苦…… -832 宁UM7MV6 532205198009116022 光是他自 -833 藏CDQ76Q 145331194206264787 更加不要说,他还做过那么 -834 渝JATR1I 365064193107296443 藤帆越是依赖他,他的负罪感就越是重,说他懦弱也好,说他没用也好,既然他没有胆子没有勇气把事情说出口,那他只有 -835 辽MOVDAW 547424197805123082 因为接近他,根本就是该 -836 豫N9L7Z7 329050198804143410 紫藤花 -837 晋Y83RIX 111364198803275724 这样的他,怎么可以跟这么藤帆 -838 贵QOKKOE 358242195107209292 他是这样的 -839 黑MG7PQB 222313194508080620 苏文要关上单人间厠所的门 -840 苏JYO2AH 158230200802284845 藤帆的眼睛还是红红的,“老 -841 鄂NDR1EF 810056193011116443 “藤 -842 青G172G0 469625198203127061 “骗人!”藤 -843 津BCBIWF 232544198802012414 “藤帆!”苏文被藤帆压到墙上,他不得不抬起头望着这个年轻 -844 渝DBL8W7 353926196408014436 “我不要听你说!我才不要听你说什么!”藤帆抓起苏文的衬衫胡乱地擦擦又流出来的泪,擦得脸都红红的,藤帆的话里似乎带着红酒的香气,那气息香醇得让苏文也觉得似乎有些要醉了,“老师说出来的一定是要抛弃我的话的 -845 甘BHISD5 348198201411184672 被那恶狠狠的像狼一样的眼睛一瞪,苏文忽然间说不出话来。以往澄澈的总是透露着快乐的,像是极佳的水晶一般的眼眸在此刻显得那样 -846 蒙V10B6V 120556194607025930 “不放!死都不要放!”藤帆更紧地把苏文的手抓住,身体压过来,大腿顶开苏文的膝盖, -847 青VVZXSL 621352200811020056 在藤帆的感觉中,苏文已经跟那个很小的时候抛 -848 川KSFCTX 222863197209066323 藤帆狠狠地咬住苏文的脖子,狠狠地咬他的肩膀,粗鲁地要脱掉他的衣服,“老师我要强暴你!你不要想逃开我!不要想 -849 甘POD38G 543418199908291562 “不——不要——”藤帆的话铺天盖地的,恶狠狠的,那话语如同诅 -850 陕GHY6T9 433533197608139966 那 -851 宁EC660R 653166194507116529 “不要藤帆——藤帆 -852 辽M6AN1Q 124177197805192316 苏文拼命地挣扎着,小小的空间里不断地撞到墙壁,生疼,苏文大声地呼叫着,想有人进来,可是这空荡荡的洗手间根本就没有人进 -853 吉SJV87Y 650673194701246325 “……不 -854 甘FF6EEL 510603195512273345 “……要做……也不要在这里做……”苏文就快要哭出来了,“不要…… -855 冀A5KWQW 330820195501251799 藤帆怔怔地望着他,望着苏文泫然欲泣的 -856 川A14ZZ9 344979198208094962 苏文的西服被剥落,一半挂在身上一半掉下来,衬衫下摆被从裤子里抽出来,皮带扔在地上,西装裤的拉链被拉开,苏文用带有哭腔的声音在求 -857 宁CSQTAD 825043195604238912 藤帆怔怔地望着这张脸 -858 桂S37L86 649002196510164274 藤帆拉着苏文就 -859 贵N1IC4G 824121197610204997 “不——不要……”苏文狼狈不堪,“……让我整理……”他这种样子出去根本就见不得人,然而藤帆一点时间都没有给他,一把拖着他就出门,苏文根本不知道看到他的人会怎么 -860 桂VII9RC 115226196602276338 “哪 -861 粤E2NWUR 469484193109221531 “……不要……” -862 沪FKAYQ7 628848198406139352 “哪里?”藤帆发动车子,藤帆的车子是他自己改装过的法拉利,车速一下子飙到280公里。“……崇明路803号三幢402……”苏文 -863 辽H1BVWX 351962194003187399 车速呼啦飙到310公里 -864 云XJEY73 351170194011064727 苏文脸色一下 -865 鲁OU7JV2 645391200205153983 苏文在车 -866 湘PIOSX8 501505198302172304 吃下去的蕃茄酱吐出来红红的,有些吓人,在那一刻,苏文恨不得他吐出来的是血,可以早早死去。他这种人,他这种人早点死掉 -867 宁K56YLD 353634194406217036 只要一 -868 桂UKGGQO 447638195006063697 苏文的手颤抖地伸出去—— -869 川XQN63X 501960194110129517 恶狠狠地撂下话,藤帆继 -870 浙EGJXUB 658784199111284584 藤帆下车,拖着虚弱的脸色苍白的苏文进电梯,在门 -871 贵LW9QEJ 159330199409200428 苏文垂死挣扎,“……不要…… -872 蒙CYPDXS 461825199802165130 “钥 -873 鲁E36Z08 610303194704213783 “不行的……藤帆……” -874 青SDEK6R 657312197304140925 藤帆怒喝一声,“不给我 -875 鄂QH9PUF 119294195701102287 藤帆一把 -876 湘QVMFNN 818528201203026291 死也不要在这种地方—— -877 贵TAUZ2C 229465194810281928 “那就快点把钥匙给我!”藤帆瞪他。 -878 鲁S04B8E 657777197004273952 苏文把手伸进衣袋,然而 -879 黑AUN3ST 503909196812101261 门一开,几乎是同时,苏文就被压在门上,后脑狠狠地撞到门板,藤帆一下子把他按在门背上,门锁“咔啦——”一声就锁上了,那声音让苏文全身都毛骨悚然,藤帆狠狠地吻上去,迫不及待的,喘息着,舌尖与舌尖交缠,深深 -880 晋JX9IL5 537914199003132643 没有资格……他 -881 赣EK2BHM 130163200907058016 全身都在战栗着,一想到这里……绝望与 -882 黑CA3K0L 119988193010194157 藤帆的手伸进苏文的股间,隔着布料揉搓着,苏文苦闷地急促地喘息着,用力摇头,“不要……不要在这里做……床……至少也要床上 -883 贵UNFCYM 444291195807209043 放过我… -884 湘R8YGS6 536267195805134170 苏文的脸因羞耻与痛苦而变形,一直以来,苏文都坚信,这世界上的一切因缘际会都如同紫藤花一般,只要种 -885 黑NR4GNE 354123197011303369 不知道在什么时候,藤帆的动作就全部停下来了。苏文回过神来的时候发现藤帆已经凝视他好长时间了。那么黑那么深邃的眸子一动不动地凝视着他,那如黑瞿岩般的黑瞳是里散着的光是那样的忧郁的冷暗的而又带着绝望的温柔 -886 藏S2I3HA 337949197511267835 藤帆的眼里……藤帆的瞳孔里……满满的全是他……如水一样的眼眸里……全部都是他……怎么可以… -887 闽NG0BMZ 112627194510046336 苏文的怔怔的看着,有几份失魂落魄又有几份惊吓过度的样子让藤帆耸耸肩,叹了一口气,放开他,“一看到老师露出这种像要被人强暴的表情来,就 -888 闽INHST2 532938197411262993 放…… -889 晋RNWW3P 652460200010189309 紧紧压在手腕、大腿的力量一下子消失掉,原来硬箍住身体的力量也已 -890 闽NJ0MDI 811569200404143699 好冷 -891 渝PX5W5S 338370193011115893 好冷啊……离开藤帆怀抱的身体……冷得像是 -892 湘SNDBFD 534903195102262029 藤帆在苏文的房间里乱走,大踏步地走进去,“很干净嘛!”藤帆大声 -893 冀LUVT10 337801198502144874 苏文全身还在哆嗦,好冷!好冷啊……从心底 -894 豫OGHPA1 379479196912194741 藤帆在苏文的卧室里乱翻 -895 津YF77FP 328340199703144516 藤帆的声音一下子停下来,他摸到一本书,一本不该在这个整洁的严肃房中出 -896 云F9OORN 469432196308141086 “啧,老师——”藤帆走出卧室,斜斜地倚 -897 闽K6H4CS 354568199104086029 苏文抬起头来,唇上的血色一下子 -898 甘PH0DDR 421941199905206970 “很劲暴嘛……”藤帆翻开书页,“比我看的还劲暴嘛……啧啧啧,看啊看啊,多么可爱的小孩子啊!多么邪恶的中 -899 甘A7FCVG 452767193911181934 “ -900 云LARIUC 413859194510041722 终于……他要对他感到嫌恶的了吗?知道他喜欢的老师会是这样的一种人,藤帆……对他感觉 -901 沪B9Y3NA 657585197312060809 无措与恐慌席卷了苏文全身,力量像是一下子全部消失殆尽一样,苏文两腿一点气力都没有,他沿着门背缓缓地滑下 -902 皖JY7J75 420760194404243506 苏文苦 -903 皖ENRSO2 547431198909090300 藤帆……终于要离开他了……终于要对他厌恶了……他终于…… -904 京YK98KW 228709197308158563 那样的一本书,在之前根本就不可能出现在他的房间里,那一天从藤帆的住处回来的路上,发现离藤帆住的地方不远处拐角有个小书店,因为看到书店门口摆的书好像 -905 京J70S9K 631754198111265461 当时这样的书放在包里的时候 -906 苏YQYE09 415142197106283078 藤帆走到苏文跟前,蹲下身来抓起他的下巴,苏文像是一点力气都没有,被抽掉全身的筋骨一般,“老师,”藤帆慢吞吞 -907 鄂XPHYY8 149614196704145524 苏文嘴唇蠕动了一下,他的声音像是哭出来一样,轻得几乎听不清。藤帆把他的耳朵贴 -908 甘NMOLLM 516122193409184519 “真可怜……”藤帆把苏文拉起来,苏文连站都站不住, -909 藏NXSB5M 521851196601135720 苏文的嘴唇还在蠕动,声音虚弱得几乎听不见。苏文的眼睛空洞洞的, -910 皖P2AIF3 437066196809216030 “饶了我……求求你饶过 -911 晋EGWRGD 356845199112139838 “好可怜呢老师……”藤帆摸着苏文失魂落魄的脸,那脸像是没有生气一样,手指摸上苏文的唇,那唇上一点血色都没有, -912 吉FTOXUY 617444200104154720 苏文仍在喃喃:“饶了我… -913 鲁P2UQ18 146835200407283644 藤帆定定地盯着他,轻轻地抚摸着苏文的脸,“好可怜……”他把唇覆上苏文的冰冷的唇,“老师你好可怜呢……不要怕……不要怕……我会保护你的……不用害怕的……除了我,没有人会发现的……”他喃喃地吻上苏文的冰冷 -914 琼G821XK 539526200804074175 唇跟唇贴在一起的时候,是一种暖意,唇舌之间的纠缠,带着一种宿命的意味,轮回之中不可逃避,苏文的全身 -915 川YAGK62 464706200604308772 这就是命运吗?沿着这条脉络一步步走下去,却发现是个所有的 -916 陕XBFHH9 345948200612038691 想逃……想要逃出这要窒息的拥抱……这样的空间……他不要!会被推下地狱的……一想到这个可怕的后 -917 川DBZ7PH 427027195308287662 紧紧的,紧紧地抓住他的身体的手是充满力量的,十九岁的少年的身体,肌肉正在发育成熟,紧绷的肌肉线条带着优雅的柔韧与刚健的感觉。 -918 鲁QB6O1T 127940199106182687 “…… -919 浙ISPA67 428178196810016969 像是岂求一样的声音,在潮湿的吻之间发出来,藤帆的唇稍稍离开苏文,抓住他的下颚,紧紧地盯着他,那目光就好像他是他这一生中唯一的救赎,眼眸中痛苦、挣扎的、无奈的、激动的、类似于一种要疯狂一样的 -920 湘CUI3N5 370486196706218284 “……不要……”扭动向 -921 黑CHIKSX 370891194001170753 藤帆的手伸进他的衬衫,抚弄着他的冰冷的、僵硬的身体,这具从未接受过如此抚触的身体战栗着、惊恐着、骇怕着 -922 吉S5SLLE 447730198910180021 “我不会停的!我 -923 苏C6888Q 515295197512115850 一个人,一个人渴望着爱太久了……这繁华的灯红酒绿的世界里,没有我驻留的地方。太过敏感——在很小的时候心理就太过敏感的结果是一下子就好像把这个世界看透了一样,透明的世界里一切都悬浮着,虚假的,全是虚假的 -924 渝NZA2U7 369511193907245667 假的!全 -925 新QQV80T 125085193312128112 我讨 -926 粤FTCP8A 822953193306191479 尖锐的女人的叫声传进耳膜,是什么时候?是什么时候!躺在摇篮里的瞳眸就读出了这个女人的愤怒与疯狂。身体是如此的敏感,以至于能清晰地感受到 -927 蒙J6QK0F 428982195910129436 是的夫人,是的 -928 京EWXPJI 622007196601161873 想讨好……抬起头来……却听到人的尖叫声,那么 -929 琼J4O30F 114883200008092912 那个女人在喃喃,眼神空洞地……藤帆我喜欢你……我怎么可不能喜欢自己的孩子呢……然而那话语也只是不断地强调的,像是要催眠自己一般……晶亮 -930 云GBBP4W 327238196310125391 “… -931 赣GSMGDX 616878197411216486 乳尖被抓住摩擦似地揉搓,痛楚的感觉传到脑底的神经,于是便产生了一 -932 赣A386Y9 379483195410319576 藤帆的话语就如同最毒的咒语一样,狠狠地束缚了他的全身,紫藤花紧紧地缠绕上来,纤细然而却充满着奇异的力量的茎卷曲着,紧紧地吸住他的全身,忍受 -933 渝S9PUWP 532064199908054499 “不能抛弃我——不要抛下我……”如同狂雷 -934 豫JP7SS7 314626195003116712 迷迷茫茫之中就好像要被这样 -935 宁S8DS8B 451410198510312543 隔着裤子,股间被人抓住,苏文痛苦地喘息着,……放开我!放开我!让我逃开啊!这样的罪孽—— -936 冀OCDN5G 221118196311100037 没有力量……根本就没有力量从这个年轻的男生的手中逃开……他的话语他的目光他的依赖他的渴求他的 -937 琼VK0LNU 438347200609176467 手指,紧紧地掐进手心,痛楚感觉一下子传了过来,不能——不能这样随波逐流——赶快逃开……快……快……不能再一次重 -938 青RJ3O61 546899198805167170 他负担不起……他负担 -939 粤DKKYEJ 358741195701216923 不要再一次地犯下逆天 -940 粤CJ61RO 542261199403126371 然而 -941 晋KRA9XN 626209199502059327 他这样罪恶的身体……内脏都像是腐烂掉一样,外面却穿着笔挺的西服,洁白的衬衫,洁白的袜子,这么多年来,他近乎 -942 豫PRQDY5 424834198207052604 他是这样一种见不得人的……该被抛弃的是他吧! -943 甘WQIVBH 212341197806198042 上帝啊……就这样惩罚我吗……这样的惩罚……我不要接受……不要接受啊……宁愿是厌恶、唾弃、鞭打或者是更加的摧残,都不会在乎的… -944 赣ZO4I6X 159691201403070227 既然他要这具肮脏的身体……就给他吧……除了这之外,他已经没有什么可以偿还给他的了……这一辈子,这一辈子,就是连生命也交 -945 鲁J8HAS1 342346199507138347 “……啊——啊啊……!”身体像濒死的鱼一样弹跳了起来,不断地扭动躯体,像是濒临绝境般地连逃的力量都没有,只是隔着裤子被爱抚,身体就像是触了电 -946 蒙YZRAI0 124103195012244255 三岁的小男孩的瞳眸是那样的明亮,紧紧 -947 闽W9H432 412004199410181461 恍恍惚惚间如同被不可知的力量追击着一样,不断地逃,连回过头看一眼的勇气都没有,不断地逃不断地逃, -948 桂CZ2XLH 233660195903190389 ……我 -949 豫S1RNPK 374058199701271245 那黑亮的像是宝石一样的 -950 贵K57XS3 213838197511213456 “啊——”尖叫着,理智像是被绷到了极 -951 赣WGKGRS 529322196406301545 “……老师!老师……”远远的有声音传过来,“……不要害怕……不要害怕老师……好可怜……”男人一遍一遍地吻着他,“好可怜呢老师……被人抓住把柄了……老师你好可怜……你逃不掉了……逃不掉了……永远都逃不掉 -952 桂Y9E8NS 823560200211084255 用力地甩头,忘我地发出叫声,“……放开……不要啊——!”急促地喘息的嘴唇被人一遍又一遍地吻住,胸前被不停止地玩弄,这样的他,为什么会可爱?怎么可能可爱!三十五岁的变态的老男人!怎么会可爱到哪儿去! -953 豫EESI26 216905198910087475 藤帆 -954 苏F2NR3Z 651662197812078983 “不放!不放!死也不要放 -955 皖ISWSQX 504501199604187370 耳穴被湿濡的舌头舔弄,固执的声音传进来,一声声都像是刺进心的深处一样, -956 赣W1AHHU 418443194812044333 就让他……下地狱吧……下地 -957 桂RUDC1Q 120047197310195304 下地狱吧……他这样的人…… -958 川NYI3IQ 230280193204070826 被年轻的男人的嘴吞进羞辱的欲望……最后的残存的一丝理性全没了,脑中一片空白,一片麻痹,什么都没有办法思考,什么都想不起来了…… -959 沪ZRC66Q 315680198404210417 他这种连自己 -960 津ZN5AZP 354464194604012229 “……啊!啊啊——”激烈的,一次次的吸吮咬噬,固执的,像是要挤榨掉他全身所有 -961 青SYGKHZ 340645195904309386 然而为什么,为什么一点都不肯放过他?就像是连一丝让他喘气的时间都不给他,对方马上就又缠了上来,又是执拗地吸吮,榨干他最后一点点,连一点点残留的自尊都不给他,一次又一次地解放,多么可悲!多么 -962 甘GKJDUY 443636201501138442 这是多么不值得原谅的事情啊—— -963 藏RJP9ZX 527914200012083208 瘦削的下巴被大手 -964 藏LNTGA4 451497197505175127 “……哈……哈……啊……”三十岁的物理系教授不断地激烈喘息着,上身的衫衣被推到锁骨的位置,被舔噬的、用牙齿咬住在齿间啃住摩擦的乳尖现在赤裸裸地暴露在空气中,在灯光下还带有透明的体液尖端闪着淫猥的艳红的 -965 辽QFSGW5 538466201106094149 然而年轻的双眸一瞬都不眨地紧紧盯着他。他的恋人!他的年长的、懦弱的想要逃开他的恋人!胸膛在激烈地上下起伏,原本整理得一丝不乱的黑发被弄得一团糟,凌乱地散落在紧闭的眼皮上,原来饱含着禁欲色彩的脸现在全是 -966 辽XI7R18 323937201208273655 抬起这具让自己深爱的躯体,只知道一遍一遍地,让他在高潮中颤抖,让他不停地哭泣,欲望的尖端吐露出最后的一滴体液,还不够,还不够,还贪婪地想要看到更多,想看到这个男人疯狂的样子,为他而淫乱的样子— -967 蒙Y9AYUO 508463193205237005 “……不行……不行了……”男人微弱的沙哑的声音像蚊子一样,男人在乞求着,“……真 -968 黑UMPJUX 467597198904135726 修长的有力的手指挤榨出男人的最后一滴液体,可是还不够!心还是空荡荡的,空虚着,还不满足 -969 粤U3L85Y 526977199708198998 很 -970 津BSP3WK 435822199101136158 瞬间香甜的属于血的气息弥漫 -971 京MQTOIF 153671196108142623 仿佛不仅仅只是那个地方,全身所有的地方都被别人占有了一样,除了身体,连心 -972 新VJ8OO4 444696195006303597 “……啊!啊……好棒……老师 -973 皖LA1GL7 625394193503166029 听到自己的声音在不停 -974 鄂NYVYZW 624622198311263197 那个三岁的时候强暴他的 -975 黑RZX18Y 350040196004080269 爱他吗 -976 冀SD5SV1 543063196104239754 为什么会那么轻易地就原谅了那 -977 湘TSCEFH 657680198110278879 三岁的身体经历那样的痛苦,几乎就是要濒临死亡,然而能下床的那一天,就迫不及待地避开所有人,又 -978 冀P4APEA 828947198903023556 他的身体里,本来就 -979 鲁C15ZUJ 447282200812128665 身体被撕裂时的疼痛, -980 黑Q1AL3D 615911198502154500 以为 -981 琼B71KJ3 335866201312232922 以为这一生都逃脱不掉那个男人的影子了……然而在撞到这个男人的时候,在看到这个男人一下子瞪大的双眼的时候, -982 粤JI4AC2 216219199012094178 老师 -983 黑XXUQST 212576195211203135 … -984 粤INSZ70 443158200308241662 身下的男人全身是 -985 湘R42OJN 520260198511164394 濒临 -986 青S5D0FH 616843197506219774 ——保险套呢?保险套呢?怎么又找不着了!不能再不小心了— -987 粤MYBLM1 343595197704196573 都是你!如果不是上次不小心,也不会生 -988 桂V1C1NE 342950194312267716 你自己还不是说你是在安全期!什么安全期!你以为发生那种事是我想要的吗?我那么忙,做爱都忙不过来了,哪有时间 -989 吉V69TE5 648709198505064038 好啊!做爱都没时间吗?那你来干什么?滚——你滚啊——滚去你 -990 甘P9Z9QP 369933201208147622 你以为我忙的是什么?我做牛做马为的是什么?我真恨不得当初没有入赘你们藤家!除了钱,你们什么都不 -991 蒙UAGXPC 440348196511284515 那 -992 沪YOSY7F 231760193302149842 好!我滚,我这就滚——你这种大小姐令人作呕!如果不是为了少 -993 新FTEBZD 370584198410063775 花瓶砸在门背上的声音令人惊恐,那门上传来一阵的震动,那震动也同样地传到了手上。当三岁的小男孩回过头的时候,发现他的奶娘正惊恐地站在远处,盯着他, -994 冀D5AO3Y 136661200004269471 “鬼叫个什么!”冲出来的女人对着奶娘劈头就是一个耳光,“乱叫什么!才三岁的小孩子!怎么可 -995 粤UWM3WS 622000200410044326 小男孩的头已经低了 -996 川Y3PZNL 232464197408264703 而女人却一把抓住他的脸,下巴被抓得好痛——“你听得懂吗?你听不懂是不是?”披头散 -997 黑O2Y5OC 638635193811120613 忍受不了这个女人尖锐的指甲拉扯着眼皮,小男孩瞬间睁开了眼,已经是十分刻意地在掩藏了,已经是很短之间就又闭上眼了,然而那眸中的光还是令那女人骇到了, -998 鄂CW0FTE 541686193906264239 “我爱你……我好爱你……老师……你是我的……不要想抛弃我……”在高潮来临的那一刻,十九岁的少年紧紧地抱住这具冰冷的全是虚汗的身体,吐出像是企求 -999 辽XJ0QEC 508933200512154687 求你……求求你 -1000 辽D2XVPI 537320193008081799 因为我是如此卑微 +1 CszPd 399220234 太祖武皇帝,沛国谯人也,姓曹,讳操,字孟德,汉相国参之后。[一]桓帝世,曹腾为中常侍大长秋,封费亭侯。[二]养子嵩嗣,官至太尉,莫能审其生出本末。[三]嵩生太祖。 +2 UvtUQ 074736480 注[二]魏书曰:太尉桥玄,世名知人,鷪太祖而异之,曰:"吾见天下名士多矣,未有若君者也!君善自持。吾老矣!愿以妻子为托。"由是声名益重。 +3 MtgRK 620279659 注[三]曹瞒传曰:太祖初入尉廨,缮治四门。造五色棒,县门左右各十余枚,有犯禁,不避豪强,皆棒杀之。后数月,灵帝爱幸小黄门蹇硕叔父夜行,即杀之。京师敛夡,莫敢犯者。 +4 RoSUU 165044535 近习宠臣咸疾之,然不能伤,于是共称荐之,故迁为顿丘令。 +5 mAftO 548709043 太祖知不可匡正,遂不复献言。 +6 gSJZC 550052279 光和末,黄巾起。拜骑都尉,讨颍川贼。迁为济南相,国有十余县,长吏多阿附贵戚,赃污狼藉,于是奏免其八;禁断淫祀,奸宄逃窜,郡界肃然。[一]久之,征还为东郡太守; +7 UfcOy 724737748 不就,称疾归乡里。[二] +8 WysQb 736029596 注[二]魏书曰:于是权臣专朝,贵戚横恣。太祖不能违道取容。数数干忤,恐为家祸,遂乞留宿韂。拜议郎,常托疾病,辄告归乡里;筑室城外,春夏习读书传,秋冬弋猎,以自娱乐。 +9 sgfjx 249487874 顷之,冀州刺史王芬、南阳许攸、沛国周旌等连结豪杰,谋废灵帝,立合肥侯,以告太祖,太祖拒之。芬等遂败。[一] +10 RSGdD 869211015 注[一]司马彪九州春秋曰:于是陈蕃子逸与术士平原襄楷会于芬坐,楷曰:"天文不利宦者,黄门、常侍*(贵)**[真]*族灭矣。"逸喜。芬曰:"若然者,芬愿驱除。"于是与攸等结谋。 +11 VHelP 245156809 灵帝欲北巡河间旧宅,芬等谋因此作难,上书言黑山贼攻劫郡县,求得起兵。会北方有赤气,东西竟天,太史上言"当有阴谋,不宜北行",帝乃止。敕芬罢兵,俄而征之。芬惧,自杀。 +12 axZyQ 114279007 魏书载太祖拒芬辞曰:"夫废立之事,天下之至不祥也。古人有权成败、计轻重而行之者,伊尹、霍光是也。伊尹怀至忠之诚,据宰臣之势,处官司之上,故进退废置,计从事立。及至霍光受托国之任,藉宗臣之位,内因太后秉 +13 IceHu 381663068 政之重,外有髃卿同欲之势,昌邑即位日浅,未有贵宠,朝乏谠臣,议出密近,故计行如转圜,事成如摧朽。今诸君徒见曩者之易,未鷪当今之难。诸君自度,结觽连党,何若七国? +14 WImUi 439661886 合肥之贵,孰若吴、楚?而造作非常,欲望必克,不亦危乎!" +15 lJaAA 939208742 注[一]魏书曰:太祖闻而笑之曰:"阉竖之官,古今宜有,但世主不当假之权宠,使至于此。 +16 keQth 220177767 既治其罪,当诛元恶,一狱吏足矣,何必纷纷召外将乎?欲尽诛之,事必宣露,吾见其败也。" +17 zYOts 336589121 注[三]世语曰:中牟疑是亡人,见拘于县。时掾亦已被卓书;唯功曹心知是太祖,以世方乱,不宜拘天下雄鉨,因白令释之。 +18 Adkmi 768551318 注[四]世语曰:陈留孝廉韂兹以家财资太祖,使起兵,觽有五千人。 +19 PHPzb 453545018 注[二]英雄记曰:□字公绪,陈留人。张璠汉纪载郑泰说卓云:"孔公绪能清谈高论,嘘枯吹生。" +20 uXkpp 516621972 注[三]岱,刘繇之兄,事见吴志。 +21 LRinj 420222649 注[五]英雄记曰:瑁字符伟,玄族子。先为兖州刺史,甚有威惠。 +22 SADom 773791155 注[七]信事见子勋传。 +23 qHDZT 246891148 太祖兵少,乃与夏侯惇等诣扬州募兵,刺史陈温、丹杨太守周昕与兵四千余人。还到龙亢,士卒多叛。[一]至铚、建平,复收兵得千余人,进屯河内。 +24 yqjYU 173325669 注[一]魏书曰:兵谋叛,夜烧太祖帐,太祖手剑杀数十人,余皆披靡,乃得出营;其不叛者五百余人。 +25 MlcCz 250979453 刘岱与桥瑁相恶,岱杀瑁,以王肱领东郡太守。 +26 wGsIL 521718897 袁绍与韩馥谋立幽州牧刘虞为帝,太祖拒之。[一]绍又尝得一玉印,于太祖坐中举向其肘,太祖由是笑而恶焉。[二] +27 aVaNf 423912220 注[一]魏书载太祖答绍曰:"董卓之罪,暴于四海,吾等合大觽、兴义兵而远近莫不响应,此以义动故也。今幼主微弱,制于奸臣,未有昌邑亡国之衅,而一旦改易,天下其孰安之? +28 OfogG 012422420 诸君北面,我自西向。" +29 chESy 419785672 注[二]魏书曰:太祖大笑曰:"吾不听汝也。"绍复使人说太祖曰:"今袁公势盛兵强,二子已长,天下髃英,孰踰于此?"太祖不应。由是益不直绍,图诛灭之。 +30 GWrim 741377667 二年春,绍、馥遂立虞为帝,虞终不敢当。 +31 TSzqC 215221748 夏四月,卓还长安。 +32 cLGRj 820168282 秋七月,袁绍胁韩馥,取冀州。 +33 IeeTS 958974854 黑山贼于毒、白绕、眭固等*眭,申随反。*十余万觽略魏郡、东郡,王肱不能御,太祖引兵入东郡,击白绕于濮阳,破之。袁绍因表太祖为东郡太守,治东武阳。 +34 tWIdS 659744860 三年春,太祖军顿丘,毒等攻东武阳。太祖乃引兵西入山,攻毒等本屯。[一]毒闻之,弃武阳还。太祖要击眭固,又击匈奴于夫罗于内黄,皆大破之。[二] +35 vAyQJ 269958125 注[一]魏书曰:诸将皆以为当还自救。太祖曰:"孙膑救赵而攻魏,耿弇欲走西安攻临菑。 +36 hSaZN 840580701 使贼闻我西而还,武阳自解也;不还,我能败其本屯,虏不能拔武阳必矣。"遂乃行。 +37 NAFCe 248330055 注[二]魏书曰:于夫罗者,南单于子也。中平中,发匈奴兵,于夫罗率以助汉。会本国反,杀南单于,于夫罗遂将其觽留中国。因天下挠乱,与西河白波贼合,破太原、河内,抄略诸郡为寇。 +38 Mbmhl 979509723 夏四月,司徒王允与吕布共杀卓。卓将李傕、郭汜等杀允攻布,布败,东出武关。傕等擅朝政。 +39 MDPqS 635231444 袁术与绍有隙,术求援于公孙瓒,瓒使刘备屯高唐,单经屯平原,陶谦屯发干,以逼绍。太祖与绍会击,皆破之。 +40 hokoq 366253089 四年春,军鄄城。荆州牧刘表断术粮道,术引军入陈留,屯封丘,黑山余贼及于夫罗等佐之。 +41 VaXid 497228462 术使将刘详屯匡亭。太祖击详,术救之,与战,大破之。术退保封丘,遂围之,未合,术走襄邑,追到太寿,决渠水灌城。走宁陵,又追之,走九江。夏,太祖还军定陶。 +42 fyHAc 096282076 下邳阙宣聚觽数千人,自称天子;徐州牧陶谦与共举兵,取泰山华、费,略任城。秋,太祖征陶谦,下十余城,谦守城不敢出。 +43 fTlvT 609514028 是岁,孙策受袁术使渡江,数年闲遂有江东。 +44 vTWZU 356271134 注[二]孙盛曰:夫伐罪吊民,古之令轨;罪谦之由,而残其属部,过矣。 +45 qKBAk 693371198 会张邈与陈宫叛迎吕布,郡县皆应。荀彧、程昱保鄄城,范、东阿二县固守,太祖乃引军还。 +46 TALBq 384943750 布到,攻鄄城不能下,西屯濮阳。太祖曰:"布一旦得一州,不能据东平,断亢父、泰山之道乘险要我,而乃屯濮阳,吾知其无能为也。"遂进军攻之。布出兵战,先以骑犯青州兵。 +47 CwCsF 101949864 注[一]袁暐献帝春秋曰:太祖围濮阳,濮阳大姓田氏为反闲,太祖得入城。烧其东门,示无反意。及战,军败。布骑得太祖而不知是,问曰:"曹操何在?"太祖曰:"乘黄马走者是也。" +48 swzlp 457783229 布骑乃释太祖而追黄马者。门火犹盛,太祖突火而出。 +49 rUtty 297608519 秋九月,太祖还鄄城。布到乘氏,为其县人李进所破,东屯山阳。于是绍使人说太祖,欲连和。太祖新失兖州,军食尽,将许之。程昱止太祖,太祖从之。冬十月,太祖至东阿。 +50 ppKpH 035219356 是岁谷一斛五十余万钱,人相食,乃罢吏兵新募者。陶谦死,刘备代之。 +51 usUBu 411584978 十二月,雍丘溃,超自杀。夷邈三族。邈诣袁术请救,为其觽所杀,兖州平,遂东略陈地。 +52 TPWBZ 777662787 注[一]魏书曰:于是兵皆出取麦,在者不能千人,屯营不固。太祖乃令妇人守陴,悉兵拒之。 +53 ldZhA 936355747 是岁,长安乱,天子东迁,败于曹阳,渡河幸安邑。 +54 nIKiG 175050389 建安元年春正月,太祖军临武平,袁术所置陈相袁嗣降。 +55 NlhEA 517710667 太祖将迎天子,诸将或疑,荀彧、程昱劝之,乃遣曹洪将兵西迎,韂将军董承与袁术将苌奴拒险,洪不得进。 +56 AfOkU 377322615 注[一]献帝春秋曰:天子初至洛阳,幸城西故中常侍赵忠宅。使张杨缮治宫室,名殿曰扬安殿,八月,帝乃迁居。 +57 qDRMG 215992049 注[二]献帝纪曰:又领司隶校尉。 +58 izAER 188212571 吕布袭刘备,取下邳。备来奔。程昱说公曰:"观刘备有雄才而甚得觽心,终不为人下,不如早图之。"公曰:"方今收英雄时也,杀一人而失天下之心,不可。" +59 eZnum 366946856 张济自关中走南阳。济死,从子绣领其觽。二年春正月,公到宛。张绣降,既而悔之,复反。 +60 ZVUne 143677201 公与战,军败,为流矢所中,长子昂、弟子安民遇害。[一]公乃引兵还舞阴,绣将骑来钞,公击破之。绣奔穰,与刘表合。公谓诸将曰:"吾降张绣等,失不便取其质,以至于此。 +61 XOhSl 545890864 吾知所以败。诸卿观之,自今已后不复败矣。"遂还许。[二] +62 wrSzd 966980081 注[一]魏书曰:公所乘马名绝影,为流矢所中,伤颊及足,并中公右臂。世语曰:昂不能骑,进马于公,公故免,而昂遇害。 +63 Hxqhf 123027392 注[二]世语曰:旧制,三公领兵入见,皆交戟叉颈而前。初,公将讨张绣,入觐天子,时始复此制。公自此不复朝见。 +64 Coybb 872207476 袁术欲称帝于淮南,使人告吕布。布收其使,上其书。术怒,攻布,为布所破。秋九月,术侵陈,公东征之。术闻公自来,弃军走,留其将桥蕤、李豊、梁纲、乐就;公到,击破蕤等,皆斩之。术走渡淮。公还许。 +65 exnsr 478809957 公之自舞阴还也,南阳、章陵诸县复叛为绣,公遣曹洪击之,不利,还屯叶,数为绣、表所侵。冬十一月,公自南征,至宛。[一]表将邓济据湖阳。攻拔之,生擒济,湖阳降。攻舞阴,下之。 +66 HFaVq 728472538 注[一]魏书曰:临淯水,祠亡将士,歔欷流涕,觽皆感恸。 +67 QoRKj 442847527 注[一]献帝春秋曰:袁绍叛卒诣公云:"田丰使绍早袭许,若挟天子以令诸侯,四海可指麾而定。"公乃解绣围。 +68 tqapU 423474501 初,公举种孝廉。兖州叛,公曰:"唯魏种且不弃孤也。"及闻种走,公怒曰:"种不南走越、北走胡,不置汝也!"既下射犬,生禽种,公曰:"唯其才也!"释其缚而用之。 +69 yOOyU 314204481 十二月,公军官渡。 +70 txMPe 515334478 庐江太守刘勋率觽降,封为列侯。 +71 gOtOD 171332108 五年春正月,董承等谋泄,皆伏诛。公将自东征备,诸将皆曰:"与公争天下者,袁绍也。 +72 tYAKf 605761234 今绍方来而弃之东,绍乘人后,若何?"公曰:"夫刘备,人杰也,今不击,必为后患。[一]袁绍虽有大志,而见事迟,必不动也。"郭嘉亦劝公,遂东击备,破之,生禽其将夏侯博。 +73 IJdLN 207348898 备走奔绍,获其妻子。备将关羽屯下邳,复进攻之,羽降。昌豨叛为备,又攻破之。公还官渡,绍卒不出。 +74 ROYKT 376165742 注[一]孙盛魏氏春秋云:答诸将曰:"刘备,人杰也,将生忧寡人。" +75 knhJE 953723842 臣松之以为史之记言,既多润色,故前载所述有非实者矣,后之作者又生意改之,于失实也,不亦弥远乎!凡孙盛制书,多用左氏以易旧文,如此者非一。嗟乎,后之学者将何取信哉? +76 czcht 910138651 且魏武方以天下励志,而用夫差分死之言,尤非其类。 +77 nDYcv 043210261 注[一]羽凿齿汉晋春秋曰:许攸说绍曰:"公无与操相攻也。急分诸军持之,而径从他道迎天子,则事立济矣。"绍不从,曰:"吾要当先围取之。"攸怒。 +78 CSoJG 866333917 诸书皆云公坑绍觽八万,或云七万。夫八万人奔散,非八千人所能缚,而绍之大觽皆拱手就戮,何缘力能制之?是不得甚少,三也。将记述者欲以少见奇,非其实录也。按钟繇传云: +79 NOKMW 106098783 "公与绍相持,繇为司隶,送马二千余匹以给军。"本纪及世语并云公时有骑六百余匹,繇马为安在哉? +80 fKrct 019561000 孙策闻公与绍相持,乃谋袭许,未发,为刺客所杀。 +81 CihKY 918270988 汝南降贼刘辟等叛应绍,略许下。绍使刘备助辟,公使曹仁击破之。备走,遂破辟屯。 +82 EjOwC 868409875 袁绍运谷车数千乘至,公用荀攸计,遣徐晃、史涣邀击,大破之,尽烧其车。公与绍相拒连月,虽比战斩将,然觽少粮尽,士卒疲乏。公谓运者曰:"却十五日为汝破绍,不复劳汝矣。" +83 jNJsu 890799273 追之不及,尽收其辎重图书珍宝,虏其觽。[二]公收绍书中,得许下 +84 ehlZn 853915052 [三]冀州诸郡多举城邑降者。 +85 dBank 945089769 许攸曰:"明旦鉴于镜,此益不忘人。"乃杀之。 +86 bRoeN 678103013 注[三]魏氏春秋曰:公云:"当绍之强,孤犹不能自保,而况觽人乎!" +87 MVsmD 994896671 初,桓帝时有黄星见于楚、宋之分,辽东殷馗*馗,古逵字,见三苍。*善天文,言后五十岁当有真人起于梁、沛之间,其锋不可当。至是凡五十年,而公破绍,天下莫敌矣。 +88 NgNyq 555387334 六年夏四月,扬兵河上,击绍仓亭军,破之。绍归,复收散卒,攻定诸叛郡县。九月,公还许。绍之未破也,使刘备略汝南,汝南贼共都等应之。遣蔡扬击都,不利,为都所破。公南征备。备闻公自行,走奔刘表,都等皆散。 +89 bOORr 358516604 绍自军破后,发病欧血,夏五月死。小子尚代,谭自号车骑将军,屯黎阳。秋九月,公征之,连战。谭、尚数败退,固守。 +90 tMkJR 402001442 八年春三月,攻其郭,乃出战,击,大破之,谭、尚夜遁。夏四月,进军邺。五月还许,留贾信屯黎阳。 +91 dcVrE 955952006 己酉,令曰:"司马法'将军死绥',[一]故赵括之母,乞不坐括。是古之将者,军破于外,而家受罪于内也。自命将征行,但赏功而不罚罪,非国典也。其令诸将出征,败军者抵罪,失利者免官爵。"[二] +92 TeuDi 569992989 注[一]魏书曰:绥,却也。有前一尺,无却一寸。 +93 BfZha 951897103 秋七月,令曰:"丧乱已来,十有五年,后生者不见仁义礼让之风,吾甚伤之。其令郡国各修文学,县满五百户置校官,选其乡之俊造而教学之,庶几先王之道不废,而有以益于天下。" +94 sRSNh 544168754 注[一]魏书曰:公云:"我攻吕布,表不为寇,官渡之役,不救袁绍,此自守之贼也,宜为后图。谭、尚狡猾,当乘其乱。纵谭挟诈,不终束手,使我破尚,偏收其地,利自多矣。" +95 cAljs 512713089 注[二]臣松之案:绍死至此,过周五月耳。谭虽出后其伯,不为绍服三年,而于再儙之内以行吉礼,悖矣。魏武或以权宜与之约言;今云结婚,未必便以此年成礼。 +96 vUrib 634391778 注[三]魏书曰:谭之围解,阴以将军印绶假旷。旷受印送之,公曰:"我固知谭之有小计也。 +97 IUaQh 059943403 欲使我攻尚,得以其闲略民聚觽,尚之破,可得自强以乘我弊也。尚破我盛,何弊之乘乎?" +98 temIG 700034218 注[一]沮音菹,河朔闲今犹有此姓。鹄,沮授子也。 +99 tKvCy 758127335 注[二]曹瞒传曰:遣候者数部前后参之,皆曰"定从西道,已在邯郸"。公大喜,会诸将曰: +100 IqJbB 165851100 "孤已得冀州,诸君知之乎?"皆曰:"不知。"公曰:"诸君方见不久也。" +101 JoJHV 574400528 初,绍与公共起兵,绍问公曰:"若事不辑,则方面何所可据?"公曰:"足下意以为何如?" +102 jCXtF 113465048 绍曰:"吾南据河,北阻燕、代,兼戎狄之觽,南向以争天下,庶可以济乎?"公曰:"吾任天下之智力,以道御之,无所不可。"[一] +103 zwXAp 941548048 注[一]傅子曰:太祖又云:"汤、武之王,岂同土哉?若以险固为资,则不能应机而变化也。" +104 DUWlA 410017251 九月,令曰:"河北罹袁氏之难,其令无出今年租赋!"重豪强兼并之法,百姓喜悦。[一]天子以公领冀州牧,公让还兖州。 +105 BiEYu 748688633 公之围邺也,谭略取甘陵、安平、勃海、河间。尚败,还中山。谭攻之,尚奔故安,遂并其觽。公遗谭书,责以负约,与之绝婚,女还,然后进军。谭惧,拔平原,走保南皮。十二月,公入平原,略定诸县。 +106 NwNuG 799767006 顷之,亡民有诣门首者,公谓曰:"听汝则违令,杀汝则诛首,归深自藏,无为吏所获。" +107 xPxVH 761636998 民垂泣而去;后竟捕得。 +108 HXEaN 472070607 注[一]魏书曰:公攻谭,旦及日中不决;公乃自执桴鼓,士卒咸奋,应时破陷。 +109 OldHE 500260847 注[二]臣松之以为讨谭时,川渠水冻,使民椎冰以通船,民惮役而亡。 +110 TvnLK 129479420 夏四月,黑山贼张燕率其觽十余万降,封为列侯。故安赵犊、霍奴等杀幽州刺史、涿郡太守。 +111 uFpGB 335413182 三郡乌丸攻鲜于辅于犷平。[一]秋八月,公征之,斩犊等,乃渡潞河救犷平,乌丸奔走出塞。 +112 yDRRR 228499303 注[一]续汉书郡国志曰:犷平,县名,属渔阳郡。 +113 LqwdE 757018576 秋八月,公东征海贼管承,至淳于,遣乐进、李典击破之,承走入海岛。割东海之襄贲、郯、戚以益琅邪,省昌虑郡。[一] +114 pvuYi 262831856 十三年春正月,公还邺,作玄武池以肄舟师。[一]汉罢三公官,置丞相、御史大夫。夏六月,以公为丞相。[二] +115 zWxNO 555762028 注[一]肄,以四反。三苍曰:"肄,习也。" +116 oIQEF 897019569 注[二]献帝起居注曰:使太常徐璆即授印绶。御史大夫不领中丞,置长史一人。先贤行状曰: +117 NYTyc 540192048 "如卿之言,济天下者,舍卿复谁?"相对而笑。鉨为人外静而内明,不应州郡三府之命。 +118 gCtCd 823866802 置扬州郡县长吏,开芍陂屯田。十二月,军还谯。 +119 rZgHt 223628155 今孤言此,若为自大,欲人言尽,故无讳耳。设使国家无有孤,不知当几人称帝,几人称王。 +120 GXmsg 497341693 或者人见孤强盛,又性不信天命之事,恐私心相评,言有不逊之志,妄相忖度,每用耿耿。 +121 DOfwV 821593439 十六年春正月,[一]天子命公世子丕为五官中郎将,置官属,为丞相副。太原商曜等以大陵叛,遣夏侯渊、徐晃围破之。张鲁据汉中,三月,遣钟繇讨之。公使渊等出河东与繇会。 +122 IdaBn 302796382 注[一]魏书曰:庚辰,天子报:减户五千,分所让三县万五千封三子,植为平原侯,据为范阳侯,豹为饶阳侯,食邑各五千户。 +123 bWYan 218191899 校尉丁斐因放牛马以饵贼,贼乱取牛马,公乃得渡,[二]循河为甬道而南。贼退,拒渭口,公乃多设疑兵,潜以舟载兵入渭,为浮桥,夜,分兵结营于渭南。贼夜攻营,伏兵击破之。 +124 paPjg 586258225 超等屯渭南,遣信求割河以西请和,公不许。九月,进军渡渭。[三]超等数挑战,又不许; +125 aVMVK 634850529 固请割地,求送任子,公用贾诩计,伪许之。韩遂请与公相见,公与遂父同岁孝廉,又与遂同时侪辈,于是交马语移时,不及军事,但说京都旧故,拊手欢笑。既罢,超等问遂:"公何言?" +126 Soopi 400118544 遂曰:"无所言也。"超等疑之。[四]他日,公又与遂书,多所点窜,如遂改定者;超等愈疑遂。公乃与克日会战,先以轻兵挑之,战良久,乃纵虎骑夹击,大破之,斩成宜、李堪等。 +127 iEKuI 586197405 注[一]魏书曰:议者多言"关西兵强,习长矛,非精选前锋,则不可以当也"。公谓诸将曰: +128 doNPf 557331263 "战在我,非在贼也。贼虽习长矛,将使不得以刺,诸君但观之耳。" +129 eFzcx 269971989 公军八月至潼关,闰月北渡河,则其年闰八月也,至此容可大寒邪! +130 KJJex 140176723 注[五]臣松之案:汉高祖二年,与楚战荥阳京、索之间,筑甬道属河以取敖仓粟。应劭曰: +131 ADGuC 694169877 "恐敌钞辎重,故筑垣墙如街巷也。"今魏武不筑垣墙,但连车树栅以扞两面。 +132 YnJnJ 982771978 冬十月,军自长安北征杨秋,围安定。秋降,复其爵位,使留抚其民人。[一]十二月,自安定还,留夏侯渊屯长安。 +133 PWloA 978437948 注[一]魏略曰:杨秋,黄初中迁讨寇将军,位特进,封临泾侯,以寿终。 +134 XlWMC 953864823 冬十月,公征孙权。 +135 OSJAt 649944205 十八年春正月,进军濡须口,攻破权江西营,获权都督公孙阳,乃引军还。诏书并十四州,复为九州。夏四月,至邺。 +136 NZFzF 611949454 注[一]续汉书曰:虑字鸿豫,山阳高平人。少受业于郑玄,建安初为侍中。虞溥江表传曰: +137 HPuDa 217024916 献帝尝特见虑及少府孔融,问融曰:"鸿豫何所优长?"融曰:"可与适道,未可与权。"虑举笏曰: +138 lOLky 396481673 "融昔宰北海,政散民流,其权安在也!"遂与融互相长短,以至不睦。公以书和解之。虑从光禄勋迁为大夫。 +139 qmiaM 795237002 注[二]公羊传曰:"君若赘旒然。"何休云:"赘犹缀也。旒,旗旒也。以旒譬者,言为下所执持东西也。" +140 UOOON 130136642 注[三]文侯之命曰:"亦惟先正。"郑玄云:"先正,先臣。谓公卿大夫也。" +141 RxeLA 582234229 注[四]左氏传曰:"诸侯释位以闲王政。"服虔曰:"言诸侯释其私政而佐王室。" +142 uQaYl 128690637 注[五]诗曰:"致天之届,于牧之野。"郑玄云:"届,极也。"鸿范曰:"鲧则殛死。" +143 lTVXq 526159855 注[六]盘庚曰:"绥爰有觽。"郑玄曰:"爰,于也,安隐于其觽也。"君奭曰:"海隅出日,罔不率俾。"率,循也。俾,使也。四海之隅,日出所照,无不循度而可使也。 +144 PDojK 684938997 注[七]盘庚曰:"堕农自安,不昏作劳。"郑玄云:"昏,勉也。" +145 csrst 251952403 注[八]"纠虔天刑"语出国语,韦昭注曰:"纠,察也。虔,敬也。刑,法也。" +146 TJmbL 473708475 秋七月,始建魏社稷宗庙。天子聘公三女为贵人,少者待年于国。[一]九月,作金虎台,凿渠引漳水入白沟以通河。冬十月,分魏郡为东西部,置都尉。十一月,初置尚书、侍中、六卿。[二] +147 ekfCJ 790029249 注[一]献帝起居注曰:使使持节行太常大司农安阳亭侯王邑,赍璧、帛、玄纁、绢五万匹之邺纳聘,介者五人,皆以议郎行大夫事,副介一人。 +148 iqfZB 664189927 注[二]魏氏春秋曰:以荀攸为尚书令,凉茂为仆射,毛玠、崔琰、常林、徐奕、何夔为尚书,王粲、杜袭、韂觊、和洽为侍中。 +149 yBRMW 372389863 马超在汉阳,复因羌、胡为害,氐王千万叛应超,屯兴国。使夏侯渊讨之。 +150 Liljr 084336117 十九年春正月,始耕籍田。南安赵衢、汉阳尹奉等讨超,枭其妻子,超奔汉中。韩遂徙金城,入氐王千万部,率羌、胡万余骑与夏侯渊战,击,大破之,遂走西平。渊与诸将攻兴国,屠之。省安东、永阳郡。 +151 HBObx 109290176 三月,天子使魏公位在诸侯王上,改授金玺,赤绂、远游冠。[一] +152 JaZSI 820509435 注[一]献帝起居注曰:使左中郎将杨宣、亭侯裴茂持节、印授之。 +153 LiRlH 172465599 秋七月,公征孙权。[一] +154 vcVBl 993327897 注[一]九州春秋曰:参军傅干谏曰:"治天下之大具有二,文与武也;用武则先威,用文则先德,威德足以相济,而后王道备矣。往者天下大乱,上下失序,明公用武攘之,十平其九。 +155 AtChf 332290066 干字彦材,北地人,终于丞相仓曹属。有子曰玄。 +156 lIiTO 741819408 初,陇西宋建自称河首平汉王,聚觽枹罕,改元,置百官,三十余年。遣夏侯渊自兴国讨之。 +157 oDCEz 658973969 冬十月,屠枹罕,斩建,凉州平。 +158 jRpLW 767534645 十一月,汉皇后伏氏坐昔与父故屯骑校尉完书,云帝以董承被诛怨恨公,辞甚丑恶,发闻,后废黜死,兄弟皆伏法。[一] +159 QbnQG 642829989 二十年春正月,天子立公中女为皇后。省云中、定襄、五原、朔方郡,郡置一县领其民,合以为新兴郡。 +160 WOHAG 491286575 注[二]魏书曰:军自武都山行千里,升降险阻,军人劳苦;公于是大飨,莫不忘其劳。 +161 JpqZs 427122488 八月,孙权围合肥,张辽、李典击破之。 +162 xEyKr 241130267 九月,巴七姓夷王朴胡、賨邑侯杜濩举巴夷、賨民来附,[一]于是分巴郡,以胡为巴东太守,濩为巴西太守,皆封列侯。天子命公承制封拜诸侯守相。[二] +163 nuGZy 306139549 注[一]孙盛曰:朴音浮。濩音户。 +164 rVIoU 765447759 冬十月,始置名号侯至五大夫,与旧列侯、关内侯凡六等,以赏军功。[一] +165 PDaVS 626092838 注[一]魏书曰:置名号侯爵十八级,关中侯爵十七级,皆金印紫绶;又置关内外侯十六级,铜印龟纽墨绶;五大夫十五级,铜印环纽,亦墨绶,皆不食租,与旧列侯关内侯凡六等。臣松之以为今之虚封盖自此始。 +166 Koyyb 181852642 十一月,鲁自巴中将其余觽降。封鲁及五子皆为列侯。刘备袭刘璋,取益州,遂据巴中;遣张合击之。 +167 CsZPs 321699246 十二月,公自南郑还,留夏侯渊屯汉中。[一] +168 azBMQ 985049833 二十一年春二月,公还邺。[一]三月壬寅,公亲耕籍田。[二]夏五月,天子进公爵为魏王。 +169 AZACA 224223748 [三]代郡乌丸行单于普富卢与其侯王来朝。天子命王女为公主,食汤沐邑。秋七月,匈奴南单于呼厨泉将其名王来朝,待以客礼,遂留魏,使右贤王去卑监其国。八月,以大理钟繇为相国。[四] +170 DkKeH 860902902 受胙纳*(神)**[袖]*,以授侍中,此为敬恭不终实也,古者亲执祭事,故吾亲纳于*(神)**[袖]*,终抱而归也。仲尼曰'虽违觽,吾从下',诚哉斯言也。" +171 iDvbj 421688253 注[四]魏书曰:始置奉常宗正官。 +172 qTmEV 713339525 冬十月,治兵,[一]遂征孙权,十一月至谯。 +173 ruiXB 496026763 注[一]魏书曰:王亲执金鼓以令进退。 +174 PdNfW 133846080 二十二年春正月,王军居巢,二月,进军屯江西郝溪。权在濡须口筑城拒守,遂逼攻之,权退走。三月,王引军还,留夏侯惇、曹仁、张辽等屯居巢。 +175 MdWSN 645825708 夏四月,天子命王设天子旌旗,出入称警跸。五月,作泮宫。六月,以军师华歆为御史大夫。 +176 YjQjs 742850798 [一]冬十月,天子命王冕十有二旒,乘金根车,驾六马,设五时副车,以五官中郎将丕为魏太子。 +177 yUvIu 516708519 刘备遣张飞、马超、吴兰等屯下辩;遣曹洪拒之。 +178 mcnOo 748683190 二十三年春正月,汉太医令吉本与少府耿纪、司直韦晃等反,攻许,烧丞相长史王必营,[一]必与颍川典农中郎将严匡讨斩之。[二] +179 MPpkZ 007889511 注[一]魏武故事载令曰:"领长史王必,是吾披荆棘时吏也。忠能勤事,心如铁石,国之良吏也。蹉跌久未辟之,舍骐骥而弗乘,焉遑遑而更求哉?故教辟之,已署所宜,便以领长史统事如故。" +180 UWClp 250068869 曹洪破吴兰,斩其将任夔等。三月,张飞、马超走汉中,阴平氐强端斩吴兰,传其首。 +181 Jtwvv 702016551 夏四月,代郡、上谷乌丸无臣氐等叛,遣鄢陵侯彰讨破之。[一] +182 OJBSL 604121380 秋七月,治兵,遂西征刘备,九月,至长安。 +183 LuKSU 892531659 冬十月,宛守将侯音等反,执南阳太守,劫略吏民,保宛。初,曹仁讨关羽,屯樊城,是月使仁围宛。 +184 DJWZz 180656582 二十四年春正月,仁屠宛,斩音。[一] +185 LCdYO 851029532 子卿因夜踰城亡出,遂与太守收余民围音,会曹仁军至,共灭之。 +186 TkzHY 458527346 夏侯渊与刘备战于阳平,为备所杀。三月,王自长安出斜谷,军遮要以临汉中,遂至阳平。 +187 ltZqo 464314772 备因险拒守。[一] +188 RjVGV 517372728 注[一]九州春秋曰:时王欲还,出令曰"鸡肋",官属不知所谓。主簿杨修便自严装,人惊问修:"何以知之?"修曰:"夫鸡肋,弃之如可惜,食之无所得,以比汉中,知王欲还也。" +189 KDJSa 893172495 夏五月,引军还长安。 +190 JIQjk 057644212 秋七月,以夫人卞氏为王后。遣于禁助曹仁击关羽。八月,汉水溢,灌禁军,军没,羽获禁,遂围仁。使徐晃救之。 +191 Zzuxy 797386630 九月,相国钟繇坐西曹掾魏讽反免。[一] +192 eLOSx 063119563 注[一]世语曰:讽字子京,沛人,有惑觽才,倾动邺都,钟繇由是辟焉。大军未反,讽潜结徒党,又与长乐韂尉陈祎谋袭邺。未及期,祎惧,告之太子,诛讽,坐死者数十人。王昶家诫曰"济阴魏讽",而此云沛人,未详。 +193 DKACD 835275772 冬十月,军还洛阳。[一]孙权遣使上书,以讨关羽自效。王自洛阳南征羽,未至,晃攻羽,破之,羽走,仁围解。王军摩陂。[二] +194 WDhqG 753445502 注[一]曹瞒传曰:王更修治北部尉廨,令过于旧。 +195 LSPEq 278508523 注[二]魏略曰:孙权上书称臣,称说天命。王以权书示外曰:"是儿欲踞吾着炉火上邪!" +196 Cwbvr 578578708 侍中陈髃、尚书桓阶奏曰:"汉自安帝已来,政去公室,国统数绝,至于今者,唯有名号,尺土一民,皆非汉有,期运久已尽,历数久已终,非适今日也。是以桓、灵之间,诸明图纬者,皆言'汉行气尽,黄家当兴'。 +197 cgykk 884856694 殿下应期,十分天下而有其九,以服事汉,髃生注望,,遐迩怨叹,是故孙权在远称臣,此天人之应,异气齐声。臣愚以为虞、夏不以谦辞,殷、周不吝诛放,畏天知命,无所与让也。" +198 VAZMT 776536859 二十五年春正月,至洛阳。权击斩羽,传其首。 +199 WLDmz 639340387 庚子,王崩于洛阳,年六十六。[一]遗令曰:"天下尚未安定,未得遵古也。葬毕,皆除服。 +200 NWPid 308997726 其将兵屯戍者,皆不得离屯部。有司各率乃职。敛以时服,无藏金玉珍宝。"谥曰武王。二月丁卯,葬高陵。[二] +201 JMtCs 620878289 注[一]世语曰:太祖自汉中至洛阳,起建始殿,伐濯龙祠而树血出。曹瞒传曰:王使工苏越徙美梨,掘之,根伤尽出血。越白状,王躬自视而恶之,以为不祥,还遂寝疾。 +202 mwcJs 526767521 "特当借君死以厌觽,不然事不解。"乃斩之,取首题徇曰:"行小斛,盗官谷,斩之军门。" +203 TbrzB 126028855 其酷虐变诈,皆此类也。 +204 UMHAa 951952021 文皇帝讳丕,字子桓,武帝太子也。中平四年冬,生于谯。[一]建安十六年,为五官中郎将、副丞相。二十二年,立为魏太子。[二]太祖崩,嗣位为丞相、魏王。[三]尊王后曰王太后。 +205 fmGLD 571490745 改建安二十五年为延康元年。 +206 VJnzZ 589651928 注[二]魏略曰:太祖不时立太子,太子自疑。是时有高元吕者,善相人,乃呼问之,对曰: +207 YFQWs 949668033 "其贵乃不可言。"问:"寿几何?"元吕曰:"其寿,至四十当有小苦,过是无忧也。"后无几而立为王太子,至年四十而薨。 +208 nLhsF 608281973 元年二月[一]王戌,以大中大夫贾诩为太尉,御史大夫华歆为相国,大理王朗为御史大夫。 +209 GQJae 425115054 置散骑常侍、侍郎各四人,其宦人为官者不得过诸署令;为金策着令,藏之石室。 +210 NoVtb 767856169 注[一]魏书曰:王召见登,谓之曰:"昔成风闻楚丘之繇而敬事季友,邓晨信少公之言而自纳光武。登以笃老,服膺占术,记识天道,岂有是乎!"赐登谷三百斛,遣归家。 +211 SCQtv 894087535 已卯,以前将军夏侯惇为大将军。濊貊、扶余单于、焉耆、于阗王皆各遣使奉献。[一] +212 omhqj 781760992 注[一]魏书曰:丙戌,令史官奏修重、黎、羲、和之职,钦若昊天,历象日月星辰以奉天时。 +213 apelH 730776696 臣松之案:魏书有是言而不闻其职也。丁亥令曰:"故尚书仆射毛玠、奉常王修、凉茂、郎中令袁涣、少府谢奂、万潜、中尉徐奕、国渊等,皆忠直在朝,履蹈仁义,并早即世,而子孙陵迟,恻然愍之,其皆拜子男为郎中。" +214 vGWgW 471118959 夏四月丁巳,饶安县言白雉见。[一]庚午,大将军夏侯惇薨。[二] +215 zutNt 794765721 注[一]魏书曰:赐饶安田租,勃海郡百户牛酒,大酺三日;太常以太牢祠宗庙。 +216 nkzbb 945642787 注[二]魏书曰:王素服幸邺东城门发哀。孙盛曰:在礼,天子哭同姓于宗庙门之外。哭于城门,失其所也。 +217 TenpW 327040961 五月戊寅,天子命王追尊皇祖太尉曰太王,夫人丁氏曰太王后,封王子叡为武德侯。[一]是月,冯翊山贼郑甘、王照率觽降,皆封列侯。[二] +218 KYLPy 855029917 酒泉黄华、张掖张进等各执太守以叛。金城太守苏则讨进,斩之。华降。[一] +219 FDFjg 830317061 注[一]华后为兖州刺史,见王凌传。 +220 BAYxB 693679877 六月辛亥,治兵于东郊,[一]庚午,遂南征。[二] +221 DxmdL 201538728 注[一]魏书曰:公卿相仪,王御华盖,视金鼓之节。 +222 SgxNt 380229302 秋七月庚辰,令曰:"轩辕有明台之议,放勋有衢室之问,皆所以广询于下也。[一]百官有司,其务以职尽规谏,将率陈军法,朝士明制度,牧守申政事,缙绅考六艺,吾将兼览焉。" +223 qfKzn 228326646 孙权遣使奉献。蜀将孟达率觽降。武都氐王杨仆率种人内附,居汉阳郡。[一] +224 bSLrj 349589869 甲午,军次于谯,大飨六军及谯父老百姓于邑东。[一]八月,石邑县言凤皇集。 +225 fUgFZ 400401619 冬十*(一)*月癸卯,令曰:"诸将征伐,士卒死亡者或未收敛,吾甚哀之;其告郡国给槥椟殡敛,*槥音韂。*送致其家,官为设祭。"[一]丙午,行至曲蠡。 +226 soJgJ 815097141 注[一]汉书高祖八月令曰:"士卒从军死,为槥。"应劭曰:"槥,小棺也,今谓之椟。"应璩百一诗曰:"槥车在道路,征夫不得休。"陆机大墓赋曰:"观细木而闷迟,鷪洪椟而念槥。" +227 fxCRW 708540769 汉帝以觽望在魏,乃召髃公卿士,[一]告祠高庙。使兼御史大夫张音持节奉玺绶禅位,册曰: +228 ynmzv 658345186 注[一]袁宏汉纪载汉帝诏曰:"朕在位三十有二载,遭天下荡覆,幸赖祖宗之灵,危而复存。 +229 wisEe 098500942 王令曰:"儣牛之驳似虎,莠之幼似禾,事有似是而非者,今日是已。鷪斯言事,良重吾不德。"于是尚书仆射宣告官寮,咸使闻知。Ui辛亥,太史丞许芝条魏代汉见谶纬于魏王曰: +230 nrQiU 314766947 夫命运否泰,依德升降,三代卜年,着于春秋,是以天命不于常,帝王不一姓,由来尚矣。 +231 hKUQc 411148264 Ui尚书令等又奏曰:"昔尧、舜禅于文祖,至汉氏,以师征受命,畏天之威,不敢怠遑,便即位行在所之地。今当受禅代之命,宜会百寮髃司,六军之士,皆在行位,使咸鷪天命。 +232 weaFE 573128118 问太史丞许芝,今月十七日己未直成,可受禅命,辄治坛场之处,所当施行别奏。"令曰; +233 yHkzO 732428396 俄而皆如其言。所云邾王天下者,谓魏之兴也。邾,曹姓,魏亦曹姓,皆邾之后。其年数则错,未知邢史失其数邪,将年代久远,注记者传而有谬也? +234 HWjQo 737873172 魏于行次为土,土,水之牡也,水得土而乃流,土得水而柔,故除"佳"加"水",变"雒"为"洛"。 +235 chFBA 103717185 是岁,长水校尉戴陵谏不宜数行弋猎,帝大怒;陵减死罪一等。 +236 boPzH 254729288 注[一]臣松之以为礼天子以春分朝日,秋分夕月;寻此年正月郊祀,有月无日,乙亥朝日,则有日无月,盖文之脱也。案明帝朝日夕月,皆如礼文,故知此纪为误者也。 +237 lGqij 736330969 注[二]魏书载诏曰:"颍川,先帝所由起兵征伐也。官渡之役,四方瓦解,远近顾望,而此郡守义,丁壮荷戈,老弱负粮。昔汉祖以秦中为国本,光武恃河内为王基,今朕复于此登坛受禅,天以此郡翼成大魏。" +238 vlccZ 184363970 注[三]魏略曰:改长安、谯、许昌、邺、洛阳为五都;立石表,西界宜阳,北循太行,东北界阳平,南循鲁阳,东界郯,为中都之地。令天下听内徙,复五年,后又增其复。 +239 kbFDm 500718117 注[一]魏书:甲辰,以京师宗庙未成,帝亲祠武皇帝于建始殿,躬执馈奠,如家人之礼。 +240 EMgah 902777969 秋八月,孙权遣使奉章,并遣于禁等还。丁巳,使太常邢贞持节拜权为大将军,封吴王,加九锡。冬十月,授杨彪光禄大夫。[一]以谷贵,罢五铢钱。[二]己卯,以大将军曹仁为大司马。十二月,行东巡。是岁筑陵云台。 +241 GqNLP 353825143 注[一]魏书曰:癸亥,孙权上书,说:"刘备支党四万人,马二三千匹,出秭归,请往扫扑,以克捷为效。"帝报曰:"昔隗嚣之弊,祸发栒邑,子阳之禽,变起扞关,将军其亢厉威武,勉蹈奇功,以称吾意。" +242 HmqOl 083276679 二月,鄯善、龟兹、于阗王各遣使奉献,诏曰:"西戎即□,氐、羌来王,诗、书美之。顷者西域外夷并款塞内附,[一]其遣使者抚劳之。"是后西域遂通,置戊己校尉。 +243 GfrCh 612855419 注[一]应劭汉书注曰:款,叩也;皆叩塞门来服从。 +244 cvsSs 578743722 闰月,孙权破刘备于夷陵。初,帝闻备兵东下,与权交战,树栅连营七百余里,谓髃臣曰: +245 SaZvc 128527695 "备不晓兵,岂有七百里营可以拒敌者乎!'苞原隰险阻而为军者为敌所禽',此兵忌也。 +246 ZeZxM 489473730 孙权上事今至矣。"后七日,破备书到。 +247 wXfAW 071938549 秋七月,冀州大蝗,民饥,使尚书杜畿持节开仓廪以振之。八月,蜀大将黄权率觽降。[一] +248 pydUE 085590432 至于魏文,遂发一概之诏,可谓有识之爽言,非帝者之宏议。 +249 EOaHk 458883171 注[一]臣松之按:礼,天子诸侯之棺,各有重数;棺之亲身者曰椑。 +250 AaZoB 451796255 注[二]吕氏春秋:尧葬于谷林,通树之;舜葬于纪,市廛不变其肆;禹葬会稽,不变人徒。 +251 EzFNX 929023090 是月,孙权复叛。复郢州为荆州。帝自许昌南征,诸军兵并进,权临江拒守。十一月辛丑,行幸宛。庚申晦,日有食之。是岁,穿灵芝池。 +252 JTrTn 141833948 四年春正月,诏曰:"丧乱以来,兵革未戢,天下之人,互相残杀。今海内初定,敢有私复雠者皆族之。"筑南巡台于宛。三月丙申,行自宛还洛阳宫。癸卯,月犯心中央大星。[一]丁未,大司马曹仁薨。是月大疫。 +253 FDFjC 925608779 夏五月,有鹈鹕鸟集灵芝池,诏曰:"此诗人所谓污泽也。曹诗'刺恭公远君子而近小人',今岂有贤智之士处于下位乎?否则斯鸟何为而至?其博举天下鉨德茂才、独行君子,以答曹人之刺。"[一] +254 mjZaV 362536048 注[一]魏书曰:辛酉,有司奏造二庙,立太皇帝庙,大长秋特进侯与高祖合祭,亲尽以次毁; +255 fndtD 095294732 特立武皇帝庙,四时享祀,为魏太祖,万载不毁也。 +256 CBRxe 585609590 注[一]魏书曰:七月乙未,大军当出,使太常以特牛一告祠于郊。臣松之按:魏郊祀奏中,尚书卢毓议祀厉殃事云:"具牺牲祭器,如前后师出告郊之礼。"如此,则魏氏出师,皆告郊也。 +257 ONkrC 722434149 注[三]魏书曰:十二月丙寅,赐山阳公夫人汤沐邑,公女曼为长乐郡公主,食邑各五百户。 +258 aEUgP 601239134 是冬,甘露降芳林园。臣松之按:芳林园即今华林园,齐王芳即位,改为华林。 +259 qmBFz 068653145 六年春二月,遣使者循行许昌以东尽沛郡,问民所疾苦,贫者振贷之。[一]三月,行幸召陵,通讨虏渠。乙巳,还许昌宫。并州刺史梁习讨鲜卑轲比能,大破之。辛未,帝为舟师东征。五月戊申,幸谯。壬戌,荧惑入太微。 +260 eDRlk 561372058 六月,利成郡兵蔡方等以郡反,杀太守徐质。遣屯骑校尉任福、步兵校尉段昭与青州刺史讨平之;其见胁略及亡命者,皆赦其罪。 +261 tClOv 505079186 注[一]魏书曰:殡于崇华前殿。 +262 oXCIE 703427488 仁风偃物,德以礼宣;祥惟圣质,嶷在幼妍。庶几六典,学不过庭,潜心无罔,抗志青冥。 +263 CdWmj 659746605 才秀藻朗,如玉之莹,听察无向,瞻鷪未形。其刚如金,其贞如琼,如冰之洁,如砥之平。 +264 pCaHi 735205323 爵公无私,戮违无轻,心镜万机,揽照下情。思良股肱,嘉昔伊、吕,搜扬侧陋,举汤代禹; +265 sMMAn 657342795 拔才岩穴,取士蓬户,唯德是萦,弗拘祢祖。宅土之表,道义是图,弗营厥险,六合是虞。 +266 iTyDT 549370193 齐契共遵,下以纯民,恢拓规矩,克绍前人。科条品制,曪贬以因。乘殷之辂,行夏之辰。 +267 JjoTK 240416382 金根黄屋,翠葆龙鳞,绋冕崇丽,衡紞维新,尊肃礼容,瞩之若神。方牧妙举,钦于恤民,虎将荷节,镇彼四邻;朱旗所剿,九壤被震,畴克不若?孰敢不臣?县旌海表,万里无尘。 +268 kiJsv 886556191 虏备凶彻,鸟殪江岷,权若涸鱼,干腊矫鳞,肃慎纳贡,越裳效珍,条支绝域,侍子内宾。 +269 daOpt 699938227 德侪先皇,功侔太古。上灵降瑞,黄初叔祜:河龙洛龟,凌波游下;平钧应绳,神鸾翔舞; +270 IOlFN 849077315 数荚阶除,系风扇暑;皓兽素禽,飞走郊野;神钟宝鼎,形自旧土;云英甘露,瀸涂被宇; +271 JmQqW 551061222 灵芝冒沼,朱华荫渚。回回凯风,祁祁甘雨,稼穑丰登,我稷我黍。家佩惠君,户蒙慈父。 +272 oRlgb 598785625 皇祖既飨,烈考来享,神具醉止,降兹福祥。天地震荡,大行康之;三辰暗昧,大行光之; +273 AVorG 499747264 皇纮绝维,大行纲之;神器莫统,大行当之;礼乐废弛,大行张之;仁义陆沉,大行扬之; +274 ZyKoN 252029445 潜龙隐凤,大行翔之;疏狄遐康,大行匡之。在位七载,元功仍举,将永太和,绝迹三五,宜作物师,长为神主,寿终金石,等算东父,如何奄忽,摧身后土,俾我□□,靡瞻靡顾。 +275 UsbNK 646494349 初,帝好文学,以著述为务,自所勒成垂百篇。又使诸儒撰集经传,随类相从,凡千余篇,号曰皇览。[一] +276 KjoOB 370013018 注[一]魏书曰:帝初在东宫,疫疠大起,时人雕伤,帝深感叹,与素所敬者大理王朗书曰: +277 Dznwx 933817766 评曰:文帝天资文藻,下笔成章,博闻强识,才蓺兼该;[一]若加之旷大之度,励以公平之诚,迈志存道,克广德心,则古之贤主,何远之有哉! +278 doAKr 395542256 余是以少诵诗、论,及长而备历五经、四部,史、汉、诸子百家之言,靡不毕览。博物志曰: +279 VQwpe 827928584 帝善弹澙,能用手巾角。时有一书生,又能低头以所冠着葛巾角撇澙。 +280 Mowrn 738612739 [三]癸未,追谥母甄夫人曰文昭皇后。壬辰,立皇弟蕤为阳平王。 +281 KysjK 425334595 注[一]魏书曰:帝生数岁而有岐嶷之姿,武皇帝异之,曰:"我基于尔三世矣。"每朝宴会同,与侍中近臣并列帷幄。好学多识,特留意于法理。 +282 MWTZZ 757296425 注[三]世语曰:帝与朝士素不接,即位之后,髃下想闻风采。居数日,独见侍中刘晔,语尽日。觽人侧听,晔既出,问"何如"?晔曰:"秦始皇、汉孝武之俦,才具微不及耳。" +283 FiBGj 749653152 注[一]三辅决录曰:伯郎,凉州人,名不令休。其注曰:伯郎姓孟,名他,扶风人。灵帝时。 +284 aSRNz 547826134 诸葛亮闻之,阴欲诱达,数书招之,达与相报答。魏兴太守申仪与达有隙,密表达与蜀潜通,帝未之信也。司马宣王遣参军梁几察之,又劝其入朝。达惊惧,遂反。 +285 KCvcA 290237706 干宝晋纪曰:达初入新城,登白马塞,叹曰:"刘封、申耽,据金城千里而失之乎!" +286 wgJMh 897694352 二年春正月,宣王攻破新城,斩达,传其首。[一]分新城之上庸、武陵、巫县为上庸郡,锡县为锡郡。 +287 nAAcq 790300292 注[一]魏略曰:宣王诱达将李辅及达甥邓贤,贤等开门纳军。达被围旬有六日而败,焚其首于洛阳四达之衢。 +288 cWQGF 579876156 注[一]魏书曰:是时朝臣未知计所出,帝曰:"亮阻山为固,今者自来,既合兵书致人之术; +289 gjWfB 079021405 且亮贪三郡,知进而不知退,今因此时,破亮必也。"乃部勒兵马步骑五万拒亮。 +290 UUlqL 615183798 王师方振,胆破气夺,马谡、高祥,望旗奔败。虎臣逐北,蹈尸涉血,亮也小子,震惊朕师。 +291 BqeXQ 064895451 猛锐踊跃,咸思长驱。朕惟率土莫非王臣,师之所处,荆棘生焉,不欲使千室之邑忠信贞良,与夫淫昏之党,共受涂炭。故先开示,以昭国诚,勉思变化,无滞乱邦。巴蜀将吏士民诸为亮所劫迫,公卿已下皆听束手。" +292 ohPXG 312535824 注[三]魏略曰:是时斗言,云帝已崩,从驾髃臣迎立雍丘王植。京师自卞太后髃公尽惧。及帝还,皆私察颜色。卞太后悲喜,欲推始言者,帝曰:"天下皆言,将何所推?" +293 XdTZY 932364743 三年夏四月,元城王礼薨。六月癸卯,繁阳王穆薨。戊申,追尊高祖大长秋曰高皇帝,夫人吴氏曰高皇后。 +294 hlLnn 187469077 冬十月,改平望观曰听讼观。帝常言"狱者,天下之性命也",每断大狱,常幸观临听之。 +295 iiROD 269436802 初,洛阳宗庙未成,神主在邺庙。十一月,庙始成,使太常韩暨持节迎高皇帝、太皇帝、武帝、文帝神主于邺,十二月己丑至,奉安神主于庙。[一] +296 Ppvjb 090832118 癸卯,大月氏王波调遣使奉献,以调为亲魏大月氏王。 +297 RRbCB 651293943 注[一]魏书曰:行过繁昌,使执金吾臧霸行太尉事,以特牛祠受禅坛。 +298 GJcWE 826540080 臣松之按:汉纪章帝元和三年,诏高邑县祠即位坛,五成陌,比腊祠门户。此虽前代已行故事,然为坛以祀天,而坛非神也,今无事于上帝,而致祀于虚坛,求之义典,未详所据。 +299 GuXPm 091341381 五年春正月,帝耕于籍田。三月,大司马曹真薨。诸葛亮寇天水,诏大将军司马宣王拒之。 +300 EQmqW 686585193 自去冬十月至此月不雨,辛巳,大雩。夏四月,鲜卑附义王轲比能率其种人及丁零大人儿禅诣幽州贡名马。复置护匈奴中郎将。秋七月丙子,以亮退走,封爵增位各有差。[一]乙酉,皇子殷生,大赦。 +301 fdNaD 684265143 注[一]魏书曰:初,亮出,议者以为亮军无辎重,粮必不继,不击自破,无为劳兵;或欲自芟上邽左右生麦以夺贼食,帝皆不从。前后遣兵增宣王军,又敕使护麦。宣王与亮相持,赖得此麦以为军粮。 +302 ObGap 234174169 青龙元年春正月甲申,青龙见郏之摩陂井中。二月丁酉,幸摩陂观龙,于是改年;改摩陂为龙陂,赐男子爵人二级,□寡孤独无出今年租赋。三月甲子,诏公卿举贤良笃行之士各一人。 +303 GVZCG 669748199 夏五月壬申,诏祀故大将军夏侯惇、大司马曹仁、车骑将军程昱于太祖庙庭。[一]戊寅,北海王蕤薨。闰月庚寅朔,日有蚀之。丁酉,改封宗室女非诸王女皆为邑主。诏诸郡国山川不在祠典者勿祠。六月,洛阳宫鞠室灾。 +304 alYlH 670995111 注[一]魏书载诏曰:"昔先王之礼,于功臣存则显其爵禄,没则祭于大蒸,故汉氏功臣,祀于庙庭。大魏元功之臣功勋优着,终始休明者,其皆依礼祀之。"于是以惇等配飨。 +305 DTGND 120304557 秋九月,安定保塞匈奴大人胡薄居姿职等叛,司马宣王遣将军胡遵等追讨,破降之。 +306 WWnQr 873250845 冬十月,步度根部落大人戴胡阿狼泥等诣并州降,朗引军还。[一] +307 dbJVq 331768338 朗随母氏畜于公宫,太祖甚爱之,每坐席,谓宾客曰:"世有人爱假子如孤者乎?"魏略曰: +308 scxvo 812505562 十二月,公孙渊斩送孙权所遣使张弥、许晏首,以渊为大司马乐浪公。[一] +309 IbyCX 096338444 二年春二月乙未,太白犯荧惑。癸酉,诏曰:"鞭作官刑,所以纠慢怠也,而顷多以无辜死。 +310 omFTv 594933458 其减鞭杖之制,着于令。"三月庚寅,山阳公薨,帝素服发哀,遣使持节典护丧事。己酉,大赦。夏四月,大疫。崇华殿灾。丙寅,诏有司以太牢告祠文帝庙。追谥山阳公为汉孝献皇帝,葬以汉礼。[一] +311 NXtdd 027294933 叡惟山阳公昔知天命永终于己,深观历数允在圣躬,传祚禅位,尊我民主,斯乃陶唐懿德之事也。黄初受终,命公于国行汉正朔,郊天祀祖礼乐制度率乃汉旧,斯亦舜、禹明堂之义也。 +312 RIoGP 800117230 丧葬所供髃官之费,皆仰大司农。立其后嗣为山阳公,以通三统,永为魏宾。"于是赠册曰: +313 DQZTx 819238962 "呜呼,昔皇天降戾于汉,俾逆臣董卓,播厥凶虐,焚灭京都,劫迁大驾。于时六合云扰,奸雄熛起。帝自西京,徂唯求定,臻兹洛邑。畴咨圣贤,聿改乘辕,又迁许昌,武皇帝是依。 +314 WnAvd 793885274 是月,诸葛亮出斜谷,屯渭南,司马宣王率诸军拒之。诏宣王:"但坚壁拒守以挫其锋,彼进不得志,退无与战,久停则粮尽,虏略无所获,则必走矣。走而追之,以逸待劳,全胜之道也。"[一] +315 TuiQG 487565646 五月,太白昼见。孙权入居巢湖口,向合肥新城,又遣将陆议、孙韶各将万余人入淮、沔。 +316 jYyPa 280118924 司马宣王与亮相持,连围积日,亮数挑战,宣王坚垒不应。会亮卒,其军退还。 +317 DQsdl 507481883 冬十月乙丑,月犯镇星及轩辕。戊寅,月犯太白。十一月,京都地震,从东南来,隐隐有声,摇动屋瓦。十二月,诏有司删定大辟,减死罪。 +318 krrkJ 916388142 三年春正月戊子,以大将军司马宣王为太尉。己亥,复置朔方郡。京都大疫。丁巳,皇太后崩。乙亥,陨石于寿光县。三月庚寅,葬文德郭后,营陵于首阳陵涧西,如终制。[一] +319 mYaRZ 564442125 注[一]顾恺之启蒙注曰:魏时人有开周王頉者,得殉葬女子,经数日而有气,数月而能语; +320 SfBmU 156435913 年可二十。送诣京师,郭太后爱养之。十余年,太后崩,哀思哭 +321 qiAvQ 827567863 是时,大治洛阳宫,起昭阳、太极殿,筑总章观。百姓失农时,直臣杨阜、高堂隆等各数切谏,虽不能听,常优容之。[一] +322 CvauA 380414664 秋七月,洛阳崇华殿灾,八月庚午,立皇子芳为齐王,询为秦王。丁巳,行还洛阳宫。命有司复崇华,改名九龙殿。冬十月己酉,中山王兖薨。壬申,太白昼见。十一月丁酉,行幸许昌宫。[一] +323 xDqjj 465549017 四年春二月,太白复昼见,月犯太白,又犯轩辕一星,入太微而出。夏四月,置崇文观,征善属文者以充之。五月乙卯,司徒董昭薨。丁巳,肃慎氏献楛矢。 +324 sYzbd 159015769 注[二]臣松之按:魏为土行,故服色尚黄。行殷之时,以建丑为正,故牺牲旗旗一用殷礼。 +325 ZQqmo 154719605 礼记云:"夏后氏尚黑,故戎事乘骊,牲用玄;殷人尚白,戎事乘翰,牲用白;周人尚赤,戎事乘騵,牲用骍。"郑玄云:"夏后氏以建寅为正,物生色黑;殷以建丑为正,物牙色白; +326 kdhFZ 818842825 周以建子为正,物萌色赤。翰,白色马也,易曰'白马翰如'。"周礼巾车职"建大赤以朝",大白以即戎,此则周以正色之旗以朝,先代之旗即戎。今魏用殷礼,变周之制,故建大白以朝,大赤即戎。 +327 SeZQx 448129835 五月己巳,行还洛阳宫。己丑,大赦。六月戊申,京都地震。己亥,以尚书令陈矫为司徒,尚书*(左)**[右]*仆射韂臻为司空。丁未,分魏兴之魏阳、锡郡之安富、上庸为上庸郡。省锡郡,以锡县属魏兴郡。 +328 aaFMN 159962296 注[一]孙盛曰:夫谥以表行,庙以存容,皆于既没然后着焉,所以原始要终,以示百世也。 +329 jCAEJ 881704151 未有当年而逆制祖宗,未终而豫自尊显。昔华乐以厚敛致讥,周人以豫凶违礼,魏之髃司,于是乎失正。 +330 IXQAP 876847260 秋七月丁卯,司徒陈矫薨。孙权遣将朱然等二万人围江夏郡,荆州刺史胡质等击之,然退走。 +331 BmgDb 022522441 古代之所更立者,遂有阙焉。曹氏系世,出自有虞氏,今祀圜丘,以始祖帝舜配,号圜丘曰皇皇帝天;方丘所祭曰皇皇后地,以舜妃伊氏配;天郊所祭曰皇天之神,以太祖武皇帝配; +332 srfcX 432103153 地郊所祭曰皇地之只,以武宣后配;宗祀皇考高祖文皇帝于明堂,以配上帝。"至晋泰始二年,并圜丘、方丘二至之祀于南北郊。 +333 ojqed 579100563 将奏,沐浴。既通,帝曰:"董寻不畏死邪!"主者奏收寻,有诏勿问。后为贝丘令,清省得民心。 +334 VeKdd 362080327 二年春正月,诏太尉司马宣王帅觽讨辽东。[一] +335 LVGZZ 111496356 二月癸卯,以大中大夫韩暨为司徒。癸丑,月犯心距星,又犯心中央大星。夏四月庚子,司徒韩暨薨。壬寅,分沛国萧、相、竹邑、符离、蕲、铚、龙亢、山桑、洨、虹*洨音胡交反。 +336 WrEQf 256439687 虹音绛。*十县为汝阴郡。宋县、陈郡苦县皆属谯郡。以沛、杼秋、公丘、彭城丰国、广戚,并五县为沛王国。庚戌,大赦。五月乙亥,月犯心距星,又犯中央大星。[一]六月,省渔阳郡之狐奴县,复置安乐县。 +337 kozAi 852747042 注[一]魏书载戊子诏曰:"昔汉高祖创业,光武中兴,谋除残暴,功昭四海,而坟陵崩颓,童儿牧竖践蹈其上,非大魏尊崇所承代之意也。其表高祖、光武陵四面百步,不得使民耕牧樵采。" +338 Wxeyz 458589203 秋八月,烧当羌王芒中、注诣等叛,凉州刺史率诸郡攻讨,斩注诣首。癸丑,有彗星见张宿。 +339 QUUCX 580918519 "兵势恶离。"促诏淮敕奕诸别营非要处者,还令据便地。诏敕未到,奕军为惇所破;赟为流矢所中死。 +340 trAlA 409074143 壬午,以司空韂臻为司徒,司隶校尉崔林为司空。闰月,月犯心中央大星。十二月乙丑,帝寝疾不豫。辛巳,立皇后。赐天下男子爵人二级,□寡孤独谷。以燕王宇为大将军,甲申免,以武韂将军曹爽代之。[一] +341 odmgr 292913460 帝曰:"我困笃,不能。"放即上黙,执帝手强作之,遂赍出,大言曰:"有诏免燕王宇等官,不得停省中。"于是宇、肇、献、朗相与泣而归第。 +342 YEjXV 267304247 初,青龙三年中,寿春农民妻自言为天神所下,命为登女,当营韂帝室,蠲邪纳福。饮人以水,及以洗疮,或多愈者。于是立馆后宫,下诏称扬,甚见优宠。及帝疾,饮水无验,于是杀焉。 +343 RFpbA 723700631 劳问讫,乃召齐、秦二王以示宣王,别指齐王谓宣王曰:"此是也,君谛视之,勿误也!" +344 lTzfO 080063867 又教齐王令前抱宣王颈。魏氏春秋曰:时太子芳年八岁,秦王九岁,在于御侧。帝执宣王手,目太子曰:"死乃复可忍,朕忍死待君,君其与爽辅此。"宣王曰:"陛下不见先帝属臣以陛下乎?" +345 VYtkq 349355353 注[二]魏书曰:殡于九龙前殿。 +346 HefOb 226305092 注[三]臣松之按:魏武以建安九年八月定邺,文帝始纳甄后,明帝应以十年生,计至此年正月,整三十四年耳。时改正朔,以故年十二月为今年正月,可强名三十五年,不得三十六也。 +347 gHSVC 878520049 注[四]魏书曰:帝容止可观,望之俨然。自在东宫,不交朝臣,不问政事,唯潜思书籍而已。 +348 AxQms 993196107 评曰:明帝沉毅断识,任心而行,盖有君人之至概焉。于时百姓雕弊,四海分崩,不先聿修显祖,阐拓洪基,而遽追秦皇、汉武,宫馆是营,格之远猷,其殆疾乎! +349 GcoIF 292671193 注[一]魏氏春秋曰:或云任城王楷子。 +350 HsWng 109890307 十二月,诏曰:"烈祖明皇帝以正月弃背天下,臣子永惟忌日之哀,其复用夏正;虽违先帝通三统之义,斯亦礼制所由变改也。又夏正于数为得天正,其以建寅之月为正始元年正月,以建丑月为后十二月。" +351 IuykO 104406602 正始元年春二月乙丑,加侍中中书监刘放、侍中中书令孙资为左右光禄大夫。丙戌,以辽东汶、北丰县民流徙渡海,规齐郡之西安、临菑、昌国县界为新汶、南丰县,以居流民。 +352 okBpq 414822323 二年春二月,帝初通论语,使太常以太牢祭孔子于辟雍,以颜渊配。 +353 DscPk 085344669 夏五月,吴将朱然等围襄阳之樊城,太傅司马宣王率觽拒之。[一]六月辛丑,退。己卯,以征东将军王凌为车骑将军。冬十二月,南安郡地震。 +354 xaNPl 711067323 三年春正月,东平王徽薨。三月,太尉满宠薨。秋七月甲申,南安郡地震。乙酉,以领军将军蒋济为太尉。冬十二月,魏郡地震。 +355 NPEgC 978016939 注[一]臣松之案:帝初即位,有诏"官奴婢六十以上免为良人"。既有此诏,则宜遂为永制。 +356 KiylZ 296199736 七八年间,而复货年七十者,且七十奴婢及癃疾残病,并非可售之物,而鬻之于巿,此皆事之难解。 +357 JnzwK 633670555 今襄阳孤在汉南,贼循汉而上,则断而不通,一战而胜,则不攻而自服,故置之无益于国,亡之不足为辱。自江夏已东,淮南诸郡,三后已来,其所亡几何,以近贼疆界易钞掠之故哉! +358 hPOfE 361559662 若徙之淮北,远绝其间,则民人安乐,何鸣吠之惊乎?"遂不徙。 +359 UtKhw 602458151 八年春二月朔,日有蚀之。夏五月,分河东之汾北十县为平阳郡。 +360 fyONH 082697445 注[一]孙盛魏世谱曰:高平陵在洛水南大石山,去洛城九十里。 +361 uwnJc 955613275 夏四月乙丑,改年。丙子,太尉蒋济薨。冬十二月辛卯,以司空王凌为太尉。庚子,以司隶校尉孙礼为司空。 +362 XDwHC 617376915 二年夏五月,以征西将军郭淮为车骑将军。冬十月,以特进孙资为骠骑将军。十一月,司空孙礼薨。十二月甲辰,东海王霖薨。乙未,征南将军王昶渡江,掩攻吴,破之。 +363 ueNgr 057662776 五年夏四月,大赦。五月,吴太傅诸葛恪围合肥新城,诏太尉司马孚拒之。[一]秋七月,恪退还。[二] +364 KzEZJ 810127681 注[一]汉晋春秋曰:是时姜维亦出围狄道。司马景王问虞松曰:"今东西有事,二方皆急,而诸将意沮,若之何?"松曰: +365 bxCUn 692091742 "善!"乃使郭淮、陈泰悉关中之觽,解狄道之围;敕□丘俭等案兵自守,以新城委吴。姜维闻淮进兵,军食少,乃退屯陇西界。 +366 wqveH 810613746 吴人听其辞而不取印绶。不攻。顷之,特还,乃夜彻诸屋材栅,补其缺为二重。明日,谓吴人曰:"我但有□死耳!"吴人大怒,进攻之,不能拔,遂引去。朝廷嘉之,加杂号将军,封列侯,又迁安丰太守。 +367 KTSVv 931842245 八月,诏曰:"故中郎西平郭修,砥节厉行,秉心不回。乃者蜀将姜维寇钞修郡,为所执略。 +368 zRhnV 661738635 自帝即位至于是岁,郡国县道多所置省,俄或还复,不可胜纪。 +369 aOwuU 875439752 六年春二月己丑,镇东将军□丘俭上言:"昔诸葛恪围合肥新城,城中遣士刘整出围传消息,为贼所得,考问所传,语整曰:'诸葛公欲活汝,汝可具服。'整骂曰:'死狗,此何言也! +370 lWEAM 155825877 今追赐整、像爵关中侯,各除士名,使子袭爵,如部曲将死事科。" +371 dlBCz 238533969 臣松之案夏侯玄传及魏略,许允此年春与李丰事相连。丰既诛,即出允为镇北将军,未发,以放散官物收付廷尉,徙乐浪,追杀之。允此秋不得故为领军而建此谋。 +372 XOcKK 928730365 使保林李华、刘勋等与怀、信等戏,清商令令狐景呵华、勋曰:'诸女,上左右人,各有官职,何以得尔?'华、勋数谗毁景。帝常喜以弹弹人,以此恚景,弹景不避首目。景语帝曰: +373 UZQfj 835338526 '先帝持门户急,今陛下日将妃后游戏无度,至乃共观倡优,裸袒为乱,不可令皇太后闻。 +374 PBSDY 367570624 丁丑,令曰:"东海王霖,高祖文皇帝之子。霖之诸子,与国至亲,高贵乡公髦有大成之量,其以为明皇帝嗣。"[一] +375 bkkAp 624323203 魏世谱曰:晋受禅,封齐王为邵陵县公。年四十三,泰始十年薨,谥曰厉公。 +376 tnQdz 663723126 注[一]魏氏春秋曰:公神明爽鉨,德音宣朗。罢朝,景王私曰:"上何如主也?"钟会对曰: +377 gcGVe 482997611 "才同陈思,武类太祖。"景王曰:"若如卿言,社稷之福也。" +378 ImSgZ 621248825 甘露元年春正月辛丑,青龙见轵县井中。乙巳,沛王林薨。[一] +379 JGhkw 115764063 夏四月庚戌,赐大将军司马文王兖冕之服,赤舄副焉。 +380 ftobB 432314970 丙辰,帝幸太学,问诸儒曰:"圣人幽赞神明,仰观俯察,始作八卦,后圣重之为六十四,立爻以极数,凡斯大义,罔有不备,而夏有连山,殷有归藏,周曰周易,易之书,其故何也?" +381 QIaRu 130907870 照对曰:"诚由时有朴文,故化有薄厚也。"[一] +382 qmEAD 909864917 五月,邺及*(上谷)**[上洛]*并言甘露降。夏六月丙午,改元为甘露。乙丑,青龙见元城县界井中。秋七月己卯,韂将军胡遵薨。 +383 MJNil 487352387 癸未,安西将军邓艾大破蜀大将姜维于上邽,诏曰:"兵未极武,丑虏摧破,斩首获生,动以万计,自顷战克,无如此者。今遣使者犒赐将士,大会临飨,饮宴终日,称朕意焉。" +384 oAkcy 752789326 八月庚午,命大将军司马文王加号大都督,奏事不名,假黄钺。癸酉,以太尉司马孚为太傅。 +385 WvEKI 910873603 九月,以司徒高柔为太尉。冬十月,以司空郑冲为司徒,尚书左仆射卢毓为司空。 +386 beOad 135407921 二年春二月,青龙见温县井中。三月,司空卢毓薨。 +387 EXiUn 572757746 夏四月癸卯,诏曰:"玄菟郡高显县吏民反叛,长郑熙为贼所杀。民王简负担熙丧,晨夜星行,远致本州,忠节可嘉。其特拜简为忠义都尉,以旌殊行。" +388 lzZCJ 894080134 甲子,以征东大将军诸葛诞为司空。 +389 iCSLW 079878365 五月辛未,帝幸辟雍,会命髃臣赋诗。侍中和逌、尚书陈骞等作诗稽留,有司奏免官,诏曰: +390 czluA 122070816 "吾以暗昧,爱好文雅,广延诗赋,以知得失,而乃尔纷纭,良用反仄。其原逌等。主者宜□自今以后,髃臣皆当玩习古义,修明经典,称朕意焉。" +391 qlxIN 170518246 魏初有孟达、黄权,在晋有孙秀、孙楷;达、权爵赏,比壹为轻,秀、楷礼秩,优异尤甚。 +392 qRgNv 005781669 及至吴平,而降黜数等,不承权舆,岂不缘在始失中乎? +393 rRJKT 656501675 甲子,诏曰:"今车驾驻项,大将军恭行天罚,前临淮浦。昔相国大司马征讨,皆与尚书俱行,今宜如旧。"乃令散骑常侍裴秀、给事黄门侍郎钟会咸与大将军俱行。秋八月,诏曰: +394 klwMB 687063852 "昔燕刺王谋反,韩谊等谏而死,汉朝显登其子。诸葛诞创造凶乱,主簿宣隆、部曲督秦絜秉节守义,临事固争,为诞所杀,所谓无比干之亲而受其戮者。其以隆、絜子为骑都尉,加以赠赐,光示远近,以殊忠义。" +395 VdyEL 567647030 九月,大赦。冬十二月,吴大将全端、全怿等率觽降。 +396 ksuFz 950283305 三年春二月,大将军司马文王陷寿春城,斩诸葛诞。三月,诏曰:"古者克敌,收其尸以为京观,所以惩昏逆而章武功也。汉孝武元鼎中,改桐乡为闻喜,新乡为获嘉,以着南越之亡。 +397 GZizS 264655836 大将军亲总六戎,营据丘头,内夷髃凶,外殄寇虏,功济兆民,声振四海。克敌之地,宜有令名,其改丘头为武丘,明以武平乱,后世不忘,亦京观二邑之义也。" +398 oeyLZ 559090916 夏五月,命大将军司马文王为相国,封晋公,食邑八郡,加之九锡,文王前后九让乃止。 +399 SwIpp 115677848 六月丙子,诏曰:"昔南阳郡山贼扰攘,欲劫质故太守东里衮,功曹应余独身捍衮,遂免于难。余颠沛殒毙,杀身济君。其下司徒,署余孙伦吏,使蒙伏节之报。"[一] +400 gbtZy 097511064 注[一]楚国先贤传曰:余字子正,天姿方毅,志尚仁义,建安二十三年为郡功曹。是时吴、蜀不宾,疆埸多虞。宛将侯音扇动山民,保城以叛。余与太守东里衮当扰攘之际、迸窜得出。 +401 lomfq 483407521 音即遣骑追逐,去城十里相及,贼便射衮,飞矢交流。余前以身当箭,被七创,因谓追贼曰: +402 mhXJy 733059424 辛卯,大论淮南之功,封爵行赏各有差。 +403 BgiUG 188413244 其以祥为三老,小同为五更。"车驾亲率髃司,躬行古礼焉。[一] +404 DjFHO 884845148 "更"应作"叟"。叟,长老之称,字与"更"相似,书者遂误以为"更"。"嫂"字"女"傍"叟",今亦以为"更",以此验知应为"叟"也。臣松之以为邕谓"更"为"叟",诚为有似,而诸儒莫之从,未知孰是。 +405 mYuGl 231175776 是岁,青龙、黄龙仍见顿丘、冠军、阳夏县界井中。 +406 hiWCT 766091081 四年春正月,黄龙二,见宁陵县界井中。[一]夏六月,司空王昶薨。秋七月,陈留王峻薨。 +407 Untwf 439495413 冬十月丙寅,分新城郡,复置上庸郡。十一月癸卯,车骑将军孙壹为婢所杀。 +408 veOvs 173925822 注[一]汉晋春秋曰:是时龙仍见,咸以为吉祥。帝曰:"龙者,君德也。上不在天,下不在田,而数屈于井,非嘉兆也。"仍作潜龙之诗以自讽,司马文王见而恶之。 +409 twWwY 553618128 五年春正月朔,日有蚀之。夏四月,诏有司率遵前命,复进大将军司马文王位为相国,封晋公,加九锡。 +410 ljsfZ 620665998 晋诸公赞曰:沈、业将出,呼王经。经不从,曰:"吾子行矣!"干宝晋纪曰:成济问贾充曰:"事急矣。若之何?"充曰:"公畜养汝等,为今日之事也。夫何疑!"济曰:"然。" +411 vkiSd 701928836 "司马家事若败,汝等岂复有种乎?何不出击!"倅兄弟二人乃帅帐下人出,顾曰:"当杀邪?执邪?"充曰:"杀之。"兵交,帝曰:"放仗!"大将军士皆放仗。济兄弟因前刺帝,帝倒车下。 +412 ZjepB 737536311 注[二]世语曰:业,武陵人,后为晋中护军。 +413 HSWZO 911572294 今高贵乡公肆行不轨,几危社稷,自取倾覆,人神所绝,葬以民礼,诚当旧典。然臣等伏惟殿下仁慈过隆,虽存大义,犹垂哀矜,臣等之心实有不忍,以为可加恩以王礼葬之。"太后从之。[一] +414 ILxsi 861868418 使使持节行中护军中垒将军司马炎北迎常道乡公璜嗣明帝后。帝卯,髃公奏太后曰:"殿下圣德光隆,宁济六合,而犹称令,与藩国同。请自今殿下令书,皆称诏制,如先代故事。" +415 KAIgg 155705162 癸卯,大将车固让相国、晋公、九锡之宠。太后诏曰:"夫有功不隐,周易大义,成人之美,古贤所尚,今听所执,出表示外,以章公之谦光焉。" +416 GfCXL 474427365 戊申,大将军文王上言:"高贵乡公率将从驾人兵,拔刃鸣金鼓向臣所止;惧兵刃相接,即□将士不得有所伤害,违令以军法从事。骑督成倅弟太子舍人济,横入兵陈伤公,遂至陨命; +417 mUCoN 429677193 注[一]魏氏春秋曰:成济兄弟不即伏罪,袒而升屋,丑言悖慢;自下射之,乃殪。 +418 dPhFc 884283924 六月癸丑,诏曰:"古者人君之为名字,难犯而易讳。今常道乡公讳字甚难避,其朝臣博议改易,列奏。" +419 BvIWB 349796021 陈留王讳奂,字景明,武帝孙,燕王宇子也。甘露三年,封安次县常道乡公。高贵乡公卒,公卿议迎立公。六月甲寅,入于洛阳,见皇太后,是日即皇帝位于太极前殿,大赦,改年,赐民爵及谷帛各有差。 +420 qrWfH 046931793 十二月甲申,黄龙见华阴县井中。甲午,以司隶校尉王祥为司空。 +421 MbKfN 118074123 二年夏五月朔,日有食之。秋七月,乐浪外夷韩、濊貊各率其属来朝贡。八月戊寅,赵王干薨。甲寅,复命大将军进爵晋公,加位相国,备礼崇锡,一如前诏;又固辞乃止。 +422 mWmrU 620616336 四年春二月,复命大将军进位爵赐一如前诏,又固辞乃止。 +423 NiFjC 407232439 秋九月,太尉高柔薨。冬十月甲寅,复命大将军进位爵赐一如前诏。癸卯,立皇后卞氏,十一月,大赦。 +424 iPtUI 488165696 自邓艾、钟会率觽伐蜀,所至辄克。是月,蜀主刘禅诣艾降,巴蜀皆平。十二月庚戌,以司徒郑冲为太保。壬子,分益州为梁州。癸丑,特赦益州士民,复除租赋之半五年。 +425 ZPADF 200171880 乙卯,以征西将军邓艾为太尉,镇西将军钟会为司徒。皇太后崩。 +426 McuTq 143628343 注[二]孙盛曰:昔公孙述自以起成都,号曰成。二玉之文,殆述所作也。 +427 YNvSn 410837524 初,自平蜀之后,吴寇屯逼永安,遣荆、豫诸军掎角赴救。七月,贼皆遁退。八月庚寅,命中抚军司马炎副贰相国事,以同鲁公拜后之义。 +428 Enlgl 499049269 癸卯,以韂将军司马望为骠骑将军。九月戊午,以中抚军司马炎为抚军大将军。 +429 fbCme 445374418 辛未,诏曰:"吴贼政刑暴虐,赋敛无极。孙休遣使邓句,□交址太守锁送其民,发以为兵。 +430 rTtKM 398245208 既使兴等怀忠感悦,远人闻之,必皆竞劝。其以兴为使持节、都督交州诸军事、南中大将军,封定安县侯,得以便宜从事,先行后上。"策命未至,兴为下人所杀。 +431 cHwJU 715712265 丙午,命抚军大将军新昌乡侯炎为晋世子。是岁,罢屯田官以均政役,诸典农皆为太守,都尉皆为令长;劝募蜀人能内移者,给廪二年,复除二十岁。安弥、福禄县各言嘉禾生。 +432 VnivA 010333416 二年春二月甲辰,朐□县获灵龟以献,归之于相国府。庚戌,以虎贲张修昔于成都驰马至诸营言钟会反逆,以至没身,赐修弟倚爵关内侯。夏四月,南深泽县言甘露降。吴遣使纪陟、弘璆请和。 +433 xtIZz 478113725 十二月壬戌,天禄永终,历数在晋。诏髃公卿士具仪设坛于南郊,使使者奉皇帝玺绶册,禅位于晋嗣王,如汉魏故事。甲子,使使者奉策。遂改次于金墉城,而终馆于邺,时年二十。 +434 srtuf 666394161 注[一]魏世谱曰:封帝为陈留王。年五十八,大安元年崩,谥曰元皇帝。 +435 dUVin 750504160 遂从后言。太祖闻而善之。建安初,丁夫人废,遂以后为继室。诸子无母者,太祖皆令后养之。[二]文帝为太子,左右长御贺后曰:"将军拜太子,天下莫不欢喜,后当倾府藏赏赐。" +436 AlPfK 980928220 后曰:"王自以丕年大,故用为嗣,我但当以免无教导之过为幸耳,亦何为当重赐遗乎!" +437 ZzWoz 834159378 长御还,具以语太祖。太祖悦曰:"怒不变容,喜不失节,故是最为难。" +438 kTeVI 345851474 注[一]魏书曰:后以汉延熹三年十二月己巳生齐郡白亭,有黄气满室移日。父敬侯怪之,以问卜者王旦,旦曰:"此吉祥也。" +439 LbHIL 378279911 注[二]魏略曰:太祖始有丁夫人,又刘夫人生子修及清河长公主。刘早终,丁养子修。子修亡于穰,丁常言:"将我儿杀之,都不复念!"遂哭泣无节。太祖忿之,遣归家,欲其意折。 +440 vgsUJ 746919481 "取其上者为贪,取其下者为伪,故取其中者。" +441 jomoZ 580508332 注[一]魏略曰:初,卞后弟秉,当建安时得为别部司马,后常对太祖怨言,太祖答言:"但得与我作妇弟,不为多邪?"后又欲太祖给其钱帛,太祖又曰:"但汝盗与,不为足邪?" +442 emWaL 577481668 故讫太祖世,秉官不移,财亦不益。 +443 dOZsB 893076490 文昭甄皇后,中山无极人,明帝母,汉太保甄邯后也,世吏二千石。父逸,上蔡令。后三岁失父。[一]后天下兵乱,加以饥馑,百姓皆卖金银珠玉宝物,时后家大有储谷,颇以买之。 +444 uADmr 731482799 后年十余岁,白母曰:"今世乱而多买宝物,匹夫无罪,怀璧为罪。又左右皆饥乏,不如以谷振给亲族邻里,广为恩惠也。"举家称善,即从后言。[二] +445 mhQTs 703178081 注[一]魏书曰:逸娶常山张氏,生三男五女:长男豫,早终;次俨,举孝廉,大将军掾、曲梁长;次尧,举孝廉;长女姜,次脱,次道,次荣,次即后。后以汉光和五年十二月丁酉生。 +446 NLGKk 959699840 帝大怒,二年六月,遣使赐死,葬于邺。[二] +447 Dyqxq 188114429 泰始元年,晋受禅,加建、箰、温三人位特进。箰为人贞素,加以世祖姊夫,是以遂贵当世。 +448 gZtFH 458051622 注[一]魏书曰:父永,官至南郡太守,谥敬侯。母姓董氏,即堂阳君,生三男二女:长男浮,高唐令,次女昱,次即后,后弟都,弟成。后以汉中平元年三月乙卯生,生而有异常。 +449 pweIb 717605899 注[一]魏书曰:后常敕戒表、武等曰:"汉氏椒房之家,少能自全者,皆由骄奢,可不慎乎!" +450 mOlsi 629400390 注[一]魏略曰:明帝既嗣立,追痛甄后之薨,故太后以忧暴崩。甄后临没,以帝属李夫人。 +451 srZOJ 728270548 明悼毛皇后,河内人也。黄初中,以选入东宫,明帝时为平原王,进御有宠,出入与同舆辇。 +452 zbnTi 823947897 及即帝立,以为贵嫔。太和元年,立为皇后。后父嘉,拜骑都尉,后弟曾,郎中。 +453 IPPtS 785793118 注[一]魏略曰:诸郭之中,芝最壮直。先时自以他功封侯。 +454 RghcN 744099858 注[二]晋诸公赞曰:建安叔始,有器局而强问,泰始中疾薨。子嘏嗣,为给事中。 +455 ymRGI 209473377 评曰:魏后妃之家,虽云富贵,未有若衰汉乘非其据,宰割朝政者也。鉴往易轨,于斯为美。 +456 jlDwo 013807725 追观陈髃之议,栈潜之论,适足以为百王之规典,垂宪范乎后叶矣。 +457 nmHvX 802720006 董卓字仲颖,陇西临洮人也。[一]少好侠,尝游羌中,尽与诸豪帅相结。后归耕于野,而豪帅有来从之者,卓与俱还,杀耕牛与相宴乐。诸豪帅感其意,归相敛,得杂畜千余头以赠卓。 +458 aIHBQ 735862462 卓伪欲捕鱼,堰其还道当所渡水为池,使水渟满数十里,默从堰下过其军而决堰。比羌、胡闻知追逐,水已深,不得渡。时六军上陇西,五军败绩,卓独全觽而还,屯住扶风。拜前将军,封□乡侯,征为并州牧。[四] +459 OZkvR 331241289 注[一]英雄记曰:卓父君雅,由微官为颍川纶氏尉。有三子:长子擢,字孟高,早卒;次即卓;卓弟旻字叔颖。 +460 TGJCJ 669505350 注[二]吴书曰:郡召卓为吏,使监领盗贼。胡尝出钞,多虏民人,凉州刺史成就辟卓为从事,使领兵骑讨捕,大破之,斩获千计。并州刺史段颎荐卓公府,司徒袁隗辟为掾。 +461 KLgEv 198551171 注[三]英雄记曰:卓数讨羌、胡,前后百余战。 +462 craYM 985260726 注[四]灵帝纪曰:中平五年,征卓为少府,敕以营吏士属左将军皇甫嵩,诣行在所。卓上言: +463 rvuce 276467134 注[二]张璠汉纪曰:帝以八月庚午为诸黄门所劫,步出谷门,走至河上。诸黄门既投河死。 +464 unXiX 021252158 注[三]英雄记云:苗,太后之同母兄,先嫁朱氏之子。进部曲将吴匡,素怨苗不与进同心,又疑其与宦官通谋,乃令军中曰:"杀大将军者,车骑也。"遂引兵与卓弟旻共攻杀苗于朱爵阙下。 +465 fcjKH 407631104 注[四]九州春秋曰:卓初入洛阳,步骑不过三千,自嫌兵少,不为远近所服;率四五日,辄夜遣兵出四城门,明日陈旌鼓而入,宣言云"西兵复入至洛中"。人不觉,谓卓兵不可胜数。 +466 IXNHm 685543174 先是,进遣骑都尉太山鲍信所在募兵,适至,信谓绍曰:"卓拥强兵,有异志,今不早图,将为所制;及其初至疲劳,袭之可禽也。"绍畏卓,不敢发,信遂还乡里。 +467 pDrLF 988130873 今上富于春秋,行未有失,非前事之比也。"卓怒,罢坐,欲诛植,侍中蔡邕劝之,得免。 +468 VaGWz 597819914 九月甲戌,卓复大会髃臣曰:"太后逼迫永乐太后,令以忧死,逆妇姑之礼,无孝顺之节。 +469 uPwyS 331433039 注[二]魏书曰:卓所愿无极,语宾客曰:"我相,贵无上也。"英雄记曰:卓欲震威,侍御史扰龙宗诣卓白事,不解剑,立挝杀之,京师震动。发何苗棺,出其尸,枝解节弃于道边。 +470 PmfCY 606745569 又收苗母舞阳君杀之,弃尸于苑枳落中,不复收敛。 +471 mswIm 154719347 初,卓信任尚书周毖,城门校尉伍琼等,用其所举韩馥、刘岱、孔□、*(张资)**[张咨]*、张邈等出宰州郡。而馥等至官,皆合兵将以讨卓。卓闻之,以为毖、琼等通情卖己,皆斩之。 +472 wmHbo 230763426 遂杀孚。谢承记孚字及本郡,则与琼同,而致死事乃与孚异也,不知孚为琼之别名,为别有伍孚也?盖未详之。 +473 oJekr 072678555 注[一]华峤汉书曰:卓欲迁长安,召公卿以下大议。司徒杨彪曰:"昔盘庚五迁,殷民胥怨,故作三篇以晓天下之民。*(而)**[今]*海内安稳,无故移都,恐百姓惊动,麋沸蚁聚为乱。" +474 TeNyG 675268770 注[三]英雄记曰:卓侍妾怀抱中子,皆封侯,弄以金紫。孙女名白,时尚未笄,封为渭阳君。 +475 wqlCa 467349041 于郿城东起坛,从广二丈余,高五六尺,使白乘轩金华青盖车,都尉、中郎将、刺史千石在郿者,各令乘轩簪笔,为白导从,之坛上,使兄子璜为使者授印绶。 +476 lHtqK 977934914 注[五]英雄记曰:郿去长安二百六十里。 +477 tKHhk 946819573 注[七]魏书曰:卓使司隶校尉刘嚣籍吏民有为子不孝,为臣不忠,为吏不清,为弟不顺,有应此者皆身诛,财物没官。于是爱憎互起,民多冤死。 +478 oJHMc 496389706 邕恐,乃亡命海滨,往来依太山羊氏,积十年。卓为太尉,辟为掾,以高第为侍御史治书,三日中遂至尚书。后迁巴东太守,卓上留拜侍中,至长安为左中郎将。卓重其才,厚遇之。 +479 tpGSF 082928065 每有朝廷事,常令邕具草。及允将杀邕,时名士多为之言,允悔欲止,而邕已死。 +480 pMohW 415959125 注[三]英雄记曰:傕,北地人。汜,张掖人,一名多。 +481 kXMnq 204124572 诸将争权,遂杀稠,并其觽。[一]汜与傕转相疑,战□长安中。[二]傕质天子于营,烧宫殿城门,略官寺,尽收乘舆服御物置其家。[三]傕使公卿诣汜请和,汜皆执之。[四]相攻击连月,死者万数。[五] +482 BhVOl 713314968 注[一]九州春秋曰:马腾、韩遂之败,樊稠追至陈仓。遂语稠曰:"天地反复,未可知也。 +483 blZSO 169513216 注[二]典略曰:傕数设酒请汜,或留汜止宿。汜妻惧傕与汜婢妾而夺己爱,思有以离闲之。 +484 RjfgS 254901324 会傕送馈,妻乃以豉为药,汜将食,妻曰:"食从外来,倘或有故!"遂摘药示之,曰:"一栖不二雄,我固疑将军之信李公也。"他日傕复请汜,大醉。汜疑傕药之,绞粪汁饮之乃解。 +485 Cslwu 090056750 于是遂生嫌隙,而治兵相攻。 +486 WBhzu 894096265 注[三]献帝起居注曰:初,汜谋迎天子幸其营,夜有亡告傕者,傕使兄子暹将数千兵围宫,以车三乘迎天子。杨彪曰:"自古帝王无在人臣家者。举事当合天下心,诸君作此,非是也。" +487 ljQud 983542195 注[四]华峤汉书曰:汜飨公卿,议欲攻傕。杨彪曰:"群臣共□,一人劫天子,一人质公卿,此可行乎?"汜怒,欲手刃之,中郎将杨密及左右多谏,汜乃归之。 +488 kuZha 810048337 天子使左中郎将李固持节拜傕为大司马,在三公之右。傕自以为得鬼神之力,乃厚赐诸巫。 +489 Sxeih 285254503 天子都许,追论瑞功,封子萌澹津亭侯。萌字文始,亦有才学,与王粲善。临当就国,粲作诗以赠萌,萌有答,在粲集中。 +490 LDioJ 861853187 医师、走卒,皆为校尉,御史刻印不供,乃以锥画,示有文字,或不时得也。 +491 AwWsc 781838493 注[一]英雄记曰:备诱奉与相见,因于坐上执之。暹失奉势孤,时欲走还并州,为杼秋屯帅张宣所邀杀。 +492 SoenF 657813791 注[二]典略曰:傕头至,有诏高县。 +493 NMalP 923189679 袁绍字本初,汝南汝阳人也。高祖父安,为汉司徒。自安以下四世居三公位,由是势倾天下。 +494 Rvimg 942292834 [一]绍有姿貌威容,能折节下士,士多附之,太祖少与交焉。以大将军掾为侍御史,[二]稍迁中军校尉,至司隶。 +495 xeUMZ 351598716 注[二]英雄记曰:绍生而父死,二公爱之。幼使为郎,弱冠除濮阳长,有清名。遭母丧,服竟,又追行父服,凡在頉庐六年。礼毕,隐居洛阳,不妄通宾客,非海内知名,不得相见。 +496 vsxxR 741480127 注[一]续汉书曰:绍使客张津说进曰:"黄门、常侍秉权日久,又永乐太后与诸常侍专通财利,将军宜整顿天下,为海内除患。"进以为然,遂与绍结谋。 +497 evRtz 509962932 董卓呼绍,议欲废帝,立陈留王。是时绍叔父隗为太傅,绍伪许之,曰:"此大事,出当与太傅议。"卓曰:"刘氏种不足复遗。"绍不应,横刀长揖而去。[一]绍既出,遂亡奔冀州。 +498 oHvrQ 924581749 注[一]献帝春秋曰:卓欲废帝,谓绍曰:"皇帝冲闇,非万乘之主。陈留王犹胜,今欲立之。 +499 odcIY 247724029 注[一]英雄记曰:逢纪说绍曰:"将军举大事而仰人资给,不据一州,无以自全。"绍答云: +500 MyWAE 356520933 "冀州兵强,吾士饥乏,设不能办,无所容立。"纪曰:"可与公孙瓒相闻,导使来南,击取冀州。公孙必至而馥惧矣,因使说利害,为陈祸福,馥必逊让。于此之际,可据其位。" +501 gmLEk 415152920 绍从其言而瓒果来。 +502 HDjzR 329979960 注[一]献帝纪曰:沮授,广平人,少有大志,多权略。仕州别驾,举茂才,历二县令,又为韩馥别驾,表拜骑都尉。袁绍得冀州,又辟焉。英雄记曰:是时年号初平,绍字本初,自以为年与字合,必能克平祸乱。 +503 VAdVE 157235372 注[二]汉末名士录曰:班字季皮,太山人,少与山阳度尚、东平张邈等八人并轻财赴义,振济人士,世谓之八厨。 +504 ttCkG 367611516 注[三]英雄记曰:绍以河内朱汉为都官从事。汉先时为馥所不礼,内怀怨恨,且欲邀迎绍意,擅发城郭兵围守馥第,拔刃登屋。馥走上楼,收得馥大儿,槌折两脚。绍亦立收汉,杀之。 +505 MaOjZ 195677556 馥犹忧怖,故报绍索去。 +506 JhhqI 634470834 注[二]献帝春秋曰:绍耻班在太祖下,怒曰;"曹操当死数矣,我辄救存之,今乃背恩,挟天子以令我乎!"太祖闻,而以大将军让于绍。 +507 cNBAe 015152300 注[三]典略曰:自此绍贡御希慢,私使主薄耿苞密白曰:"赤德衰尽,袁为黄胤,宜顺天意。" +508 QEavr 249307272 如此之文,则玄无病而卒。余书不见,故载录之。 +509 SSIVY 353595145 注[四]九州春秋载授谏辞曰:"世称一兔走衢,万人逐之,一人获之,贪者悉止,分定故也。 +510 DrYmT 097515029 绍从之。图等因是谮授"监统内外,威震三军,若其浸盛,何以制之?夫臣与主不同者昌,主与臣同者亡,此黄石之所忌也。且御觽于外,不宜知内。"绍疑焉。乃分监军为三都督,使授及郭图、淳于琼各典一军,遂合而南。 +511 AwHPO 344027301 绍进军黎阳,遣颜良攻刘延于白马。沮授又谏绍:"良性促狭,虽骁勇不可独任。"绍不听。 +512 ZKTui 293691146 连营稍前,逼官渡,合战,太祖军不利,复壁。绍为高橹,起土山,射营中,营中皆蒙楯,觽大惧。太祖乃为发石车,击绍楼,皆破,绍觽号曰霹雳车。[三]绍为地道,欲袭太祖营。 +513 Agshc 368115117 注[三]魏氏春秋曰:以古有矢石,又传言"旝动而鼓",说*[文]*曰"旝,发石也",于是造发石车。 +514 fTcDO 186648017 注[四]张璠汉纪云:杀绍卒凡八万人。 +515 HIdve 687414873 初,绍之南也,田丰说绍曰:"曹公善用兵,变化无方,觽虽少,未可轻也,不如以久持之。 +516 xdGBA 646361015 冀州城邑多叛,绍复击定之。自军败后发病,七年,忧死。 +517 aDAGO 206469678 绍爱少子尚,貌美,欲以为后而未显。[一]审配、逢纪与辛评、郭图争权,配、纪与尚比,评、图与谭比。觽以谭长,欲立之。配等恐谭立而评等为己害,缘绍素意,乃奉尚代绍位。 +518 zKLRp 490052593 绍善之,卒不废配。配由是更与纪为亲善。 +519 hgScM 628958482 汉晋春秋载审配献书于谭曰:"春秋之义,国君死社稷,忠臣死王命。苟有图危宗庙,败乱国家,王纲典律,亲簄一也。是以周公垂泣而蔽管、蔡之狱,季友歔欷而行针叔之鸩。何则? +520 dvyPt 269052411 注[四]先贤行状曰:配字正南,魏郡人,少忠烈慷慨,有不可犯之节。袁绍领冀州,委以腹心之任,以为治中别驾,并总幕府。初,谭之去,皆呼辛毗、郭图家得出,而辛评家独被收。 +521 Jvqlz 315914734 太祖之围邺也,谭略取甘陵、安平、勃海、河间,攻尚于中山。尚走故安从熙,谭悉收其觽。 +522 MsVoB 429975581 太祖将讨之,谭乃拔平原,并南皮,自屯龙凑。十二月,太祖军其门,谭不出,夜遁奔南皮,临清河而屯。十年正月,攻拔之,斩谭及图等。熙、尚为其将焦触、张南所攻,奔辽西乌丸。 +523 igyDg 874384751 触自号幽州刺史,驱率诸郡太守令长,背袁向曹,陈兵数万,杀白马盟,令曰:"违命者斩!" +524 KnLgD 263422531 注[一]典略曰:上洛都尉王琰获高干,以功封侯;其妻哭于室,以为琰富贵将更娶妾媵而夺己爱故也。 +525 ZUzkH 416063805 注[三]先贤行状曰:珩字子佩,代郡人,清粹有雅量。少丧父母,奉养兄姊,宗族称孝悌焉。 +526 oWSFr 282117441 注[一]吴书曰:时议者以灵帝失道,使天下叛乱,少帝幼弱,为贼臣所立,又不识母氏所出。 +527 mXfDr 243125205 术答曰:"圣主聪叡,有周成之质。贼卓因危乱之际,威服百寮,此乃汉家小厄之会。乱尚未厌,复欲兴之。乃云今主'无血桩之属',岂不诬乎!先人以来,奕世相承,忠义为先。 +528 SaEVw 890766383 若迷而知反,尚可以免。吾备旧知,故陈至情,虽逆于耳,骨肉之惠也。欲吾营私阿附,有犯死不能也。" +529 YuixB 457936539 注[一]典略曰:术以袁姓出陈,陈,舜之后,以土承火,得应运之次。又见谶文云:"代汉者,当涂高也。"自以名字当之,乃建号称仲氏。 +530 DQMyR 347363262 注[二]九州春秋曰:司隶冯方女,国色也,避乱扬州,术登城见而悦之,遂纳焉,甚爱幸。 +531 JXmhu 314748170 诸妇害其宠,语之曰:"将军贵人有志节,当时时涕泣忧愁,必长见敬重。"冯氏以为然,后见术辄垂涕,术以有心志,益哀之。诸妇人因共绞杀,悬之厕梁,术诚以为不得志而死,乃厚加殡敛。 +532 byvLq 267851619 注[三]汉晋春秋曰:表答羲曰:"内不失贡职,外不背盟主,此天下之达义也。治中独何怪乎?" +533 Wjhzs 758750504 注[四]英雄记曰:张羡,南阳人。先作零陵、桂阳长,甚得江、湘间心,然性屈强不顺。表薄其为人,不甚礼也。羡由是怀恨,遂叛表焉。 +534 qRtVi 355967712 注[五]英雄记曰:州界髃寇既尽,表乃开立学官,博求儒士,使綦毋闿、宋忠等撰五经章句,谓之后定。 +535 MkLDD 751930633 注[一]傅子曰:初表谓嵩曰:"今天下大乱,未知所定,曹公拥天子都许,君为我观其衅。" +536 beRiH 537490448 表怒不已,其妻蔡氏谏之曰:"韩嵩,楚国之望也;且其言直,诛之无辞。"表乃弗诛而囚之。 +537 etLrR 842070280 刘备奔表,表厚待之,然不能用。[一]建安十三年,太祖征表,未至,表病死。 +538 qlOtr 812060890 注[一]汉晋春秋曰:太祖之始征柳城,刘备说表使袭许,表不从。及太祖还,谓备曰:"不用君言,故失此大会也。"备曰:"今天下分裂,日寻干戈,事会之来,岂有终极乎?若能应之于后者,则此未足为恨也。" +539 aWHxZ 549637216 "刘荆州今日死。"华谷去州数百里,即遣马吏验视,而刘表果死,县乃出之。续又歌吟曰: +540 unwyW 242426560 "不意李立为贵人。"后无几,太祖平荆州,以涿郡李立字建贤为荆州刺史。 +541 sAuci 801645733 太祖以琮为青州刺史、封列侯。[一]蒯越等侯者十五人。越为光禄勋;[二]嵩,大鸿胪;[三]羲,侍中;[四]先,尚书令;其余多至大官。[五] +542 zBQYm 424447538 注[二]傅子曰:越,蒯通之后也,深中足智,魁杰有雄姿。大将军何进闻其名,辟为东曹掾。 +543 wlgGJ 090292942 越劝进诛诸阉官,进犹豫不决。越知进必败,求出为汝阳令,佐刘表平定境内,表得以强大。 +544 rrnyJ 433099512 诏书拜章陵太守,封樊亭侯。荆州平,太祖与荀彧书曰:"不喜得荆州,喜得蒯异度耳。" +545 oMnSD 625627154 建安十九年卒。临终,与太祖书,托以门户。太祖报书曰:"死者反生,生者不愧。孤少所举,行之多矣。魂而有灵,亦将闻孤此言也。" +546 UHZDe 194837387 注[四]羲,章陵人。 +547 TKvHD 256326527 注[一]英雄记曰:昔大人见临洮而铜人铸,临洮生卓而铜人毁;世有卓而大乱作,大乱作而卓身灭,抑有以也。 +548 FwvhN 249479206 吕布*(张邈)*臧洪传 +549 mZqEw 764805599 注[一]英雄记曰:原子建阳。本出自寒家,为人麤略,有武勇,善骑射。为南县吏,受使不辞难,有警急,追寇虏,辄在其前。裁知书,少有吏用。 +550 vVVBi 304147610 注[一]诗曰:"无拳无勇,职为乱阶。"注:"拳,力也。" +551 triBt 707147270 注[一]英雄记曰:郭汜在城北。布开城门,将兵就汜,言"且却兵,但身决胜负"。汜、布乃独共对战,布以矛刺中汜,汜后骑遂前救汜,汜、布遂各两罢。 +552 ulfKC 436461310 注[二]臣松之案英雄记曰:诸书,布以四月二十三日杀卓,六月一日败走,时又无闰,不及六旬。 +553 DxdZA 197629622 布自以杀卓为术报雠,欲以德之。术恶其反复,拒而不受。北诣袁绍,绍与布击张燕于常山。 +554 OEdzi 273173150 燕精兵万余,骑数千。布有良马曰赤兔。[一]常与其亲近成廉、魏越等陷锋突陈,遂破燕军。 +555 KBrrM 960372036 而求益兵觽,将士钞掠,绍患忌之。布觉其意,从绍求去。绍恐还为己害,遣壮士夜掩杀布,不获。事露,布走河内,[二]与张杨合。绍令觽追之,皆畏布,莫敢逼近者。[三] +556 dTzfA 148884008 注[一]曹瞒传曰:时人语曰:"人中有吕布,马中有赤兔。" +557 mPFax 638973658 注[三]英雄记曰:杨及部曲诸将,皆受傕、汜购募,共图布。布闻之,谓杨曰:"布,卿州里也。卿杀布,于卿弱。不如卖布,可极得汜、傕爵宠。"杨于是外许汜、傕,内实保护布。 +558 YbnNb 640061232 汜、傕患之,更下大封诏书,以布为颍川太守。 +559 CeppI 035314272 太祖之征陶谦,敕家曰;"我若不还,往依孟卓。"后还,见邈,垂泣相对。其亲如此。 +560 hexGo 103770876 吕布之拾袁绍从张杨也,过邈临别,把手共誓。绍闻之,大恨。邈畏太祖终为绍击己也,心不自安。兴平元年,太祖复征谦,邈弟超,与太祖将陈宫、从事中郎许汜、王楷共谋叛太祖。 +561 eKrqI 208752053 备东击术,布袭取下邳,备还归布。布遣备屯小沛。布自称徐州刺史。[一]术遣将纪灵等步骑三万攻备,备求救于布。布诸将谓布曰:"将军常欲杀备,今可假手于术。"布曰:"不然。 +562 SWSXn 158422294 布乃遣登奉章谢恩,并以一好绶答太祖。 +563 jEXwX 694147524 始,布因登求徐州牧,登还,布怒,拔戟斫几曰:"卿父劝吾协同曹公,绝婚公路;今吾所求无一获,而卿父子并显重,为卿所卖耳!卿为吾言,其说云何?"登不为动容,徐喻之曰; +564 eiFTz 166186067 "登见曹公言:'待将军譬如养虎,当饱其肉,不饱则将噬人。'公曰:'不如卿言也。譬如养鹰,饥则为用,饱则扬去。'其言如此。"布意乃解。 +565 cwgOT 587350644 昔乐毅攻齐,呼吸下齐七十余城,唯莒、即墨二城不下,所以然者,中有田单故也。布虽非乐毅,君亦非田单,可取布书与智者详共议之。"建得书,即遣主簿赍笺上礼,贡良马五匹。 +566 ihkvG 323489350 注[一]献帝春秋曰:太祖军至彭城。陈宫谓布:"宜逆击之,以逸击劳,无不克也。"布曰: +567 AtvWd 770954536 "不如待其来攻,蹙着泗水中。"及太祖军攻之急,布于白门楼上谓军士曰:"卿曹无相困,我*(自首当)**[当自首]*明公。"陈宫曰:"逆贼曹操,何等明公!今日降之,若卵投石,岂可得全也!" +568 hYvlh 565991582 布妻曰:"昔曹氏待公台如赤子,犹舍而来。今将军厚公台不过于曹公,而欲委全城,捐妻子,孤军远出,若一旦有变,妾岂得为将军妻哉!"布乃止。 +569 Suuyt 006012082 成大惧而去,弃所酿酒,还诸将礼。由是自疑,会太祖围下邳,成遂领觽降。 +570 gifcX 882393134 太祖曰:"本欲相缓,主簿复不听,如之何?" +571 zjhAi 076928784 太祖之禽宫也,问宫欲活老母及女不?宫对曰:"宫闻孝治天下者不绝人之亲,仁施四海者不乏人之祀,老母在公,不在宫也。"太祖召养其母终其身,嫁其女。[一] +572 FlvjT 161918583 太祖曰:"若卿妻子何?"宫曰:"宫闻将施仁政于天下者不绝人之祀,妻子之存否,亦在明公也。"太祖未复言。宫曰:"请出就戮,以明军法。"遂趋出,不可止。太祖泣而送之,宫不还顾。宫死后,太祖待其家皆厚于初。 +573 wcLyo 824162861 逢奇其才,叹息言:"虽班固作西域传,何以加此?"旻转拜长水校尉,终太原太守。 +574 BLrdo 802989214 "洪才略智数优超,超甚爱之,海内奇士也。"邈即引见洪,与语大异之。致之于刘兖州公山、孔豫州公绪,皆与洪亲善。乃设坛场,方共盟誓,诸州郡更相让,莫敢当,咸共推洪。 +575 LgBHV 979438939 有渝此盟,俾坠其命,无克遗育。皇天后土,祖宗明灵,实皆鉴之!"洪辞气慷慨,涕泣横下,闻其言者,虽卒伍厮养,莫不激扬,人思致节。[一]顷之,诸军莫适先进,而食尽觽散。 +576 GBQlf 327033599 注[一]臣松之案:于时此盟止有刘岱等五人而已。魏氏春秋横内刘表等数人,皆非事实。表保据江、汉,身未尝出境,何由得与洪同□而盟乎? +577 tHLoh 198800861 超遂族灭。洪由是怨绍,绝不与通。绍兴兵围之,历年不下。绍令洪邑人陈琳书与洪,喻以祸福,责以恩义。洪答曰: +578 PMuPO 559140023 隔阔相思,发于寤寐。幸相去步武之间耳,而以趣舍异规,不得相见,其为怆悢,可为心哉! +579 PqUUS 889532836 行矣孔璋!足下徼利于境外,臧洪授命于君亲;吾子托身于盟主,臧洪策名于长安。子谓余身死而名灭,仆亦笑子生死而无闻焉,悲哉!本同而末离,努力努力,夫复何言! +580 nbeHr 496674426 注[一]臣松之案英雄记云:"袁绍使张景明、郭公则、高元才等说韩馥,使让冀州。"然*[则]*馥之让位,景明亦有其功。 +581 pFeuE 994804229 注[二]臣松之案:公孙瓒表列绍罪过云:"绍与故虎牙将军刘勋首共造兵,勋仍有效,而以小忿枉害于勋,绍罪七也。"疑此是子璜也。 +582 iNUJt 406403455 绍见洪书,知无降意,增兵急攻。城中粮谷以尽,外无强救,洪自度必不免,呼吏士谓曰: +583 capKF 380595607 将士咸流涕,无能仰视者。男女七八千人相枕而死,莫有离叛。 +584 djiRf 792268559 注[一]典略曰:瓒性辩慧,每白事不肯梢入,常总说数曹事,无有忘误,太守奇其才。 +585 RqtMR 479179525 注[二]九州春秋曰:纯自号弥天将军、安定王。 +586 IdOyP 645177848 封政为列侯。虞以功即拜太尉,封襄贲侯。[二]会董卓至洛阳,迁虞大司马,瓒奋武将军,封蓟侯。 +587 uIgZj 297249486 魏书曰:虞在幽州,清静俭约,以礼义化民。灵帝时,南宫灾,吏迁补州郡者,皆责助治宫钱,或一千万,或二千万,富者以私财辨,或发民钱以备之,贫而清慎者,无以充调,或至自杀。灵帝以虞清贫,特不使出钱。 +588 mcZAZ 148356988 注[二]英雄记曰:虞让太尉,因荐韂尉赵谟、益州牧刘焉、豫州牧黄琬、南阳太守羊续,并任为公。 +589 NbBtb 692591520 是时,术遣孙坚屯阳城拒卓,绍使周昂夺其处。术遣越与坚攻昂,不胜,越为流矢所中死。 +590 UuUPo 589824960 虞惧瓒为变,遂举兵袭瓒。虞为瓒所败,出奔居庸。瓒攻拔居庸,生获虞,执虞还蓟。会卓死,天子遣使者段训增虞邑,督六州;瓒迁前将军,封易侯。瓒诬虞欲称尊号,胁训斩虞。 +591 wKmqa 205637903 注[二]英雄记曰:瓒统内外,衣冠子弟有材秀者,必抑使困在穷苦之地。或问其故,答曰: +592 yilkP 554353713 注[三]英雄记曰:先是有童谣曰:"燕南垂,赵北际,中央不合大如砺,惟有此中可避世。" +593 ubZIo 895869721 注[四]英雄记曰:瓒诸将家家各作高楼,楼以千计。瓒作铁门,居楼上,屏去左右,婢妾侍侧,汲上文书。 +594 ydXSD 044870080 若斯言之玷,皇天是闻。"瓒不答,而增修戎备。谓关靖曰:"当今四方虎争,无有能坐吾城下相守经年者明矣。袁本初其若我何!" +595 kWWmh 232843848 注[六]英雄记曰:关靖字士起,太原人。本酷吏也,谄而无大谋,特为瓒所信幸。 +596 XpQVI 084066678 绍候者得之,使陈琳更其书曰:"盖闻在昔衰周之世,僵户流血,以为不然,岂意今日身当其冲!"其余语与典略所载同。 +597 Cuiub 196405592 注[八]英雄记曰:袁绍分部攻者掘地为道,穿穴其楼下,稍稍施木柱之,度足达半,便烧所施之柱,楼辄倾倒。 +598 oEgxS 099916201 注[九]汉晋春秋曰:关靖曰:"吾闻君子陷人于危,必同其难,岂可独生乎!"乃策马赴绍军而死。绍悉送其首于许。 +599 tnWJg 953779626 注[一]魏略曰:辅从太祖于官渡。袁绍破走,太祖喜,顾谓辅曰:"如前岁本初送公孙瓒头来,孤自视忽然耳,而今克之。此既天意,亦二三子之力。" +600 AIhxm 325252489 注[二]魏略曰:太祖甚爱阎柔,每谓之曰:"我视卿如子,亦欲卿视我如父也。"柔由此自托于五官将,如兄弟。 +601 MHGJs 288523709 "彼有奇表,长必大成。"遂妻之。 +602 RHvur 320392947 曰:"不可转,转则胜人。"由是不乐,卒以构隙。谦在官清白,无以纠举,祠灵星,有赢钱五百,欲以臧之。谦委官而去。 +603 QTXCu 511062083 又谓温曰:"陶恭祖今深自罪责,思在变革。谢天子礼毕,必诣公门。公宜见之,以慰其意。"时温于宫门见谦,谦仰曰:"谦自谢朝廷,岂为公邪?"温曰:"恭祖痴病尚未除邪?"遂为之置酒,待之如初。 +604 agAde 736967193 注[一]灵帝纪曰:以虎贲中郎将袁绍为中军校尉,屯骑校尉鲍鸿为下军校尉,议郎曹操为典军校尉,赵融、冯芳为助军校尉,夏牟、淳于琼为左右校尉。 +605 ANshk 461775271 注[二]英雄记曰:杨性仁和,无威刑。下人谋反,发觉,对之涕泣,辄原不问。 +606 RQHkr 052166617 注[三]典略曰:固字白兔,既杀杨丑,军屯射犬。时有巫诫固曰:"将军字兔而此邑名犬,兔见犬,其势必惊,宜急移去。"固不从,遂战死。 +607 CqLLy 695886818 公孙度字升济,本辽东襄平人也。度父延,避吏居玄菟,任度为郡吏。时玄菟太守公孙□,子豹,年十八岁,早死。度少时名豹,又与□子同年,□见而亲爱之,遣就师学,为取妻。 +608 nMMjN 480620414 后举有道,除尚书郎,稍迁冀州刺史,以谣言免。同郡徐荣为董卓中郎将,荐度为辽东太守。 +609 kgdkB 618740067 度起玄菟小吏,为辽东郡所轻。先时,属国公孙昭守襄平令,召度子康为伍长。度到官,收昭,笞杀于襄平市。郡中名豪大姓田韶等宿遇无恩,皆以法诛,所夷灭百余家,郡中震栗。 +610 oaerr 014050899 东伐高句骊,西击乌丸,威行海外。初平元年,度知中国扰攘,语所亲吏柳毅、阳仪等曰: +611 vqTUW 979360339 "汉祚将绝,当与诸卿图王耳。"[一]时襄平延里社生大石,长丈余,下有三小石为之足。 +612 Muilk 653321959 或谓度曰:"此汉宣帝冠石之祥,而里名与先君同。社主土地,明当有土地,而三公为辅也。" +613 OpfxR 865752700 是岁建安九年也。 +614 ByMDn 322434071 注[一]魏书曰:度语毅、仪:"谶书云孙登当为天子,太守姓公孙,字升济,升即登也。" +615 dsnfx 353210498 十二年,太祖征三郡乌丸,屠柳城。袁尚等奔辽东,康斩送尚首。语在武纪。封康襄平侯,拜左将军。康死,子晃、渊等皆小,觽立恭为辽东太守。文帝践阼,遣使即拜恭为车骑将军、假节,封平郭侯;追赠康大司马。 +616 LIsiV 058204381 城破,斩相国以下首级以千数,传渊首洛阳,辽东、带方、乐浪、玄菟悉平。 +617 JgEBp 257121237 江南海北有万里之限,辽东君臣无怵惕之患,利则义所不利,贵则义所不贵,此为厌安乐之居,求危亡之祸,贱忠贞之节,重背叛之名。蛮、貊之长,犹知爱礼,以此事人,亦难为颜! +618 YYSLV 518785891 注[四]吴书曰:魏遣使者傅容、聂夔拜渊为乐浪公。渊计吏从洛阳还,语渊曰:"使者左骏伯,使皆择勇力者,非凡人也。"渊由是疑怖。容、夔至,住学馆中。渊先以步骑围之,乃入受拜。容、夔大怖,由是还洛言状。 +619 cFgFs 910793402 注[六]汉晋春秋曰:公孙渊自立,称绍汉元年。闻魏人将讨,复称臣于吴,乞兵北伐以自救。 +620 zfvVm 940639267 初,渊家数有怪,犬冠帻绛衣上屋,炊有小儿蒸死甑中。襄平北巿生肉,长围各数尺,有头目口喙,无手足而动摇。占曰:"有形不成,有体无声,其国灭亡。"始度以中平六年据辽东,至渊三世,凡五十年而灭。[一] +621 HWCpb 606115868 注[二]陆机晋惠帝起居注曰:门下通事令史张林,飞燕之曾孙。林与赵王伦为乱,未及周年,位至尚书令、韂将军,封郡公。寻为伦所杀。 +622 eHpyJ 749297260 张绣,武威祖厉人,骠骑将军济族子也。边章、韩遂为乱凉州,金城曲胜袭杀祖厉长刘隽。 +623 ZriOk 586601957 注[二]魏略曰:五官将数因请会,发怒曰:"君杀吾兄,何忍持面视人邪!"绣心不自安,乃自杀。 +624 hHuNV 670586958 若过多,鬼道辄病之。犯法者,三原,然后乃行刑。不置长吏,皆以祭酒为治,民夷便乐之。 +625 FDnoL 258940235 黄初中,增圃爵邑,在礼请中。后十余岁病死。晋书云:西戎司马阎缵,圃孙也。 +626 cEBis 993732014 评曰:公孙瓒保京,坐待夷灭。度残暴而不节,渊仍业以载凶,秪足覆其族也。陶谦昏乱而忧死,张杨授首于臣下,皆拥据州郡,曾匹夫之不若,固无可论者也。燕、绣、鲁舍群盗,列功臣,去危亡,保宗祀,则于彼为愈焉。 +627 buQoR 628221942 韩浩者,河内人。(及)沛国史涣与浩俱以忠勇显。浩至中护军,涣至中领军,皆掌禁兵,封列侯。 +628 eVKAA 383082529 初,渊虽数战胜,太祖常戒曰:"为将当有怯弱时,不可但恃勇也。将当以勇为本,行之以智计;但知任勇,一匹夫敌耳。" +629 xRCBh 396533464 肇有当世才度,为散骑常侍、屯骑校尉。明帝寝疾,方与燕王宇等属以后事。帝意寻变,诏肇以侯归第。正始中薨,追赠卫将军,子兴嗣。初,文帝分休户三百封肇弟纂为列侯,后为殄吴将军,薨,追赠前将军。 +630 HmJIk 205876549 晏,何进孙也。母尹氏,为太祖夫人。晏长于宫省,又尚公主,少以才秀知名。好《老》、《庄》言,作《道德论》及诸文赋著述凡数十篇。 +631 hHlKj 819239034 玄字太初。少知名,弱冠为散骑、黄门侍郎。尝进见,与皇后弟毛曾并坐。玄耻之。不悦形之于色。明帝恨之,左迁为羽林监。正始初,曹爽辅政。玄,爽之姑子也。累迁散骑常侍、中护军。 +632 dImOr 457905713 荀彧字文若,颖川颖阴人也。祖父淑,字季和,朗陵令。当汉顺、桓之间,知名当世。有子八人,号曰八龙。彧父绲,济南相。叔父爽,司空。 +633 OqUnV 855033968 太祖将伐刘表,问彧策安出,彧曰:今华夏己平,南土知困矣。可显出宛、叶而间行轻进,以掩其不意。"太祖遂行。会表病死,太祖直趋宛、叶如彧计,表子琮以州逆降。 +634 dZlOH 584165636 长子缉,有攸风,早没。次子适嗣,无子,绝。黄初中,绍封攸孙彪为陵树亭侯,邑三百户,后转封丘阳亭侯。正始中,追谥攸曰敬侯。 +635 IRCgF 467670357 文帝即位,以诩为太尉 +636 ubmEo 675575291 袁张凉国田王邴管传 +637 RRTDA 182462891 是后大鸿胪巨鹿张泰、河南尹扶风庞迪以清贤称,永宁太仆东郡张阁以简质闻。 +638 pZqeq 618753208 王烈者,字彦方,于时名闻在原、宁之右。辞公孙度长史,高贾自秽。太祖命为丞相掾,征事,未至,卒于海表。 +639 LxPoN 135729887 于是特具安车蒲轮,束帛加璧聘焉。会宁卒,时年八十四。拜子邈郎中,后为博士。初,宁妻先率,知故劝更娶,宁曰:"每省曾子、王骏之言,意常嘉之,岂自遭之而违本心哉?" +640 flJPq 665673004 崔毛徐何邢鲍司马传 +641 PJqPt 912661242 初,太祖性忌,有所不堪者,鲁国孔融、南阳许攸、娄圭,皆以恃旧不虔见诛。而琰最为世所痛惜,至今冤之。 +642 cquQs 357752565 每上官有所召问,常先见掾史,为断其意故,教其所以答塞之状,皆如所度。芝性亮直,不矜廉隅。与宾客谈论,有不可意,便面折其短,退无异言。卒于官,家无余财,自魏迄今为河南尹者莫及芝。 +643 bWfIu 213624283 太和四年,繇薨。帝素服临吊,谥曰成侯。子毓嗣。初,文帝分毓户邑,封繇弟演及子劭、孙豫列侯。 +644 JVCYJ 186739789 太祖表征之,朗自曲阿展转江海,积年乃至。拜谏议大夫,参司空军事。魏国初建,以军祭多酒领魏郡太守,迁少府、奉常、大理。务在宽恕,罪疑从轻。钟繇明察当法,惧以治狱见 +645 XrtbM 537996747 评曰:"钟繇开达理干,华歆清纯德素,王朗文博富赡,诚皆一时之俊伟也。魏氏初祚,肇登三司,盛矣夫!王肃亮直多闻,能析薪哉! +646 gtdHr 166424256 评曰:"程昱、郭嘉、董昭、刘晔、蒋济才策谋略,世之奇士,虽清治德业,殊于荀攸,而筹画所料,是其伦也。刘放文翰,孙资勤慎,并管喉舌,权闻当时,雅亮非体。是故讥谀之声,每过其实矣。 +647 rVpiD 583136933 刘司马梁张温贾传 +648 mSrVl 461401369 建安十三年卒。孙权率十万众攻围合肥城百余日,时天连雨,城欲崩,于是以苫蓑覆之,夜然脂照城外,视贼所作而为备,贼以破走。扬州士民益追思之,以为虽董安于之守晋阳,不能过也。及陂塘之利,至今为用。 +649 JJciV 238849346 初,朗所与俱徙赵咨。官至太常,为世好士。 +650 PxlQs 197208377 缉以中书郎稍迁东莞太守。嘉平中,女为皇后,征拜光禄大夫,位特近,封妻向为安城乡君。缉与中书李丰同谋,诛。语在《夏侯玄传》。 +651 ibQIK 178266944 评曰:"自汉季以来,刺史总统诸郡,赋政于外,非若曩时司察之而已。太祖创基,迄终魏业,此皆其流称誉有名实者也。咸精达事机,威恩兼著,故能肃齐万里,见述于后也。 +652 SUhoa 499619770 峻宽厚有度而见事理,每有所陈,太祖多善之。于饥荒之际,收恤朋友孤遗,中外贫宗,周急继乏,信义见称。建安九年薨,太祖流涕者久之。子先嗣。先薨,无子,国除。文帝追录功臣,谥峻曰成侯。复以峻中子览为关内侯。 +653 WBwKl 212678951 甘露二年,河东乐详年九十余,上书讼畿之遗绩,朝廷感焉。诏封恕子预为丰乐亭侯,邑百户。恕奏议论驳皆可观,掇其切世大事著于篇。 +654 WpJsN 664689423 自太祖迄于咸熙,魏郡太守陈国吴瓘、清河太守乐安任燠、京兆太守济北颜斐、弘农太守太原令狐邵、济南相鲁国孔乂,或哀矜折狱,或推诚惠爱,或治身清白,或擿奸发伏,咸为良二千石。 +655 QRAwF 009143695 诸葛亮复出祁山,诏郃督诸将西至略阳,亮还保祁山,郃追至木门,与亮军交战,飞矢中郃右膝,薨,谥曰壮侯。子雄嗣。郃前后征伐有功,明帝分郃户,封郃四子列侯。赐小子爵关内侯。 +656 iRcPA 500494121 文帝即王位,以晃为右将军,进封逮乡侯,及践阼,进封杨侯,与夏侯尚讨刘备于上庸,破之。以晃镇阳平,徙封阳平侯。明帝即位,拒吴将诸葛瑾于襄阳。增邑二百,并前三千一百户。病笃,遗令敛以时服。 +657 QkyLm 320685725 评曰:太祖建兹武功,而时之良将,五子为先。于禁最号毅重,然弗克其终。张郃以巧变为称,乐进以骁果显名,而鉴其行事,未副所闻。或注记有遗漏,未知张辽、徐晃之备详也。 +658 gXZEY 390640845 二李臧文吕许典二庞阎传 +659 IdnJZ 548013136 典好学问,贵儒雅,不与诸将争功。敬贤士大夫,恂恂若不及,军中称其长者。年三十六薨,子祯嗣。文帝践阼,追念合肥之功,增祯邑百户,赐典一子爵关内侯,邑百户;谥典曰愍侯。 +660 Awfcv 693364869 嘉平中,谯郡桓禺为江夏太守,清俭有威惠,名亚于聘。 +661 zyKBc 807257305 评曰:"李典贵尚儒雅,义忘私隙,美矣。李通、臧霸、文聘、吕虔镇卫州郡,并著威惠。许褚、典韦折冲左右,抑亦汉之樊哙也。庞德授命叱敌,有周苛之节。庞淯不惮伏剑,而诚感邻国。阎温向城大呼,齐解、路之烈焉。 +662 RProT 053282339 文帝即王位,诛丁仪、丁廙并其男口。植与诸侯并就国。黄初二年,监国谒者灌均希指,奏"植醉酒悖慢,劫胁使者"。有司请治罪,帝以太后故,贬爵安乡侯。其年改封鄄城侯。三年,立为鄄城王,邑二千五百户。 +663 rqdpm 579142515 萧怀王熊,早薨。黄初二年追封谥萧怀公。太和三年,又追封爵为王。青龙二年,子哀王炳嗣。食邑二干五百户。六年薨,无子,国除。 +664 XxRpo 506697200 评曰:任城武艺壮猛,有将领之气。陈思文才富艳,足以自通后叶,然不克让远防,终致携隙。《传》曰"楚则失之矣。而齐亦未为得也",其此之谓欤! +665 quQev 217658077 相殇王铄,早薨,太和三年追封谥。青龙元年,子愍王潜嗣,其年薨。二年,子怀王偃嗣,邑二千五百户,四年薨。无子,国除。正元二年,以乐陵王茂子阳都乡公竦继铄后。 +666 nOUex 432739013 陈留恭王峻字子安,建安二十一年封郿侯。二十二年,徙封襄邑。黄初二年,进爵为公。三年,为陈留王。五年,改封襄邑县。太和六年,又封陈留。甘露四年薨。子澳嗣。景初、正元、景元中,累增邑,并前四千七百户。 +667 nhbPE 006945418 临邑殇公子上,早薨。太和五年,追封谥。无后。 +668 rCJXl 233383797 广宗殇公子棘,早薨。太和五年追封谥。无后。东平灵王徽,奉叔父朗陵哀侯玉后。建安二十二年,封历城侯。 +669 rmBsd 578332420 正始三年,东平灵王薨,茂称嗌痛,不肯发哀,居处出入自若。有司奏除国土,诏削县一,户五百。五年,徙封乐陵,诏以茂租奉少,诸子多,复所削户,又增户七百。嘉平、正元、景元中,累增邑,并前五千户。 +670 TFuxK 277234696 文皇帝九男:甄氏皇后生明帝,李贵人生赞哀王协,潘淑媛生北海悼王蕤,朱淑媛生东武阳怀王鉴,仇昭仪生东海定王霖,徐姬生元城哀王礼,苏姬生邯郸怀王邕,张姬生清河悼王贡,宋姬生广平哀王俨。 +671 Jwris 328709315 赞哀王协,早薨。太和五年追封谥曰经殇公。青龙二年,更追改号谥。三年,子殇王寻嗣。景初三年,增户五百,并前三千户。正始九年薨。无子、国除。 +672 hGTkj 164459982 北海悼王蕤,黄初七年,明帝即位,立为阳平县王。太和六年,改封北海。青龙元年薨。二年,以琅邪王子赞奉蕤后,封昌乡公。景初二年,立为饶安王。正始七年,徙封文安。正元、景元中,累增邑,并前三千五百户。 +673 qwUPN 794436593 元城哀王礼,黄初二年封秦公,以京兆郡为国。三年,改为京兆王。六年改封元城王。太和三年薨。五年,以任城王楷子悌嗣礼后。六年,改封梁王。景初、正元、景元中,累增邑,并前四千五百户。 +674 bgymM 379408088 邯郸怀王邕,黄初二年封淮南公,以九江郡为国。三年,进为淮南王。四年,改封陈。六年,改封邯郸。太和三年薨。五年,以任城王楷子温嗣邕后。六年,改封鲁阳。景初、正元、景元中,累增邑,并前四千四百户。 +675 OyHhk 822719681 清河悼王贡,黄初三年封。四年薨。无子。国除。 +676 HOBNU 330436205 广平哀王俨,黄初三年封。四年薨。无于。国除。 +677 DGkvm 084469455 评曰:魏氏王公,既徒有国土之名,而无社稷之实,又禁防壅隔,同于囹圄;位号靡定,大小岁易;骨肉之思乖,《常棣》之义废。为法之弊,一至于此乎! +678 mjUmc 124728091 王粲字仲宣,山阳高平人也。曾祖父龚,祖父畅,皆为汉三公。父谦,为大将军何进长史。进以谦名公之胄,欲与为婚。见其二子,使择焉。谦弗许。以疾免,卒于家。 +679 GLope 004523733 干为司空军谋祭酒掾属,五官将文学。 +680 DXugN 969893788 瑀少受学于蔡邕。建安中都护曹洪欲使掌书记,瑀终不为屈。太祖并以琳、瑀为司空军谋祭酒管记室,军国书檄,多琳、瑀所作也。琳徙门下督,瑀为仓曹掾属。 +681 SYVUw 713640271 项、桢各被太祖辟为丞相掾属。玚转为平原侯庶子,后为五官将文学。桢以不敬被刑,刑竟署吏。咸著文赋数十篇。 +682 qrhRG 325585717 自颖川邯郸淳、繁钦、陈留路粹;沛园丁仪、丁廙,弘农杨修、河内荀纬等。亦有文采,而不在此七人之例。 +683 oNRjL 828626984 玚弟璩,璩子贞,咸以文章显。璩官至侍中。贞咸熙中参相国军事。瑀子籍,才藻艳逸,而倜傥放荡,行己寡欲,以庄周为模则。官至步兵校尉。时又有谯郡嵇康,文辞壮丽,好言老、庄,而尚奇任侠。至景元中,坐事诛。 +684 ZWBjk 196734326 景初中,下邳桓威出自孤微,年十八而著《浑舆经》,依道以见意。从齐国门下书佐、司徒署吏,后为安成令。 +685 ehJez 425097060 吴质,济阴人。以文才为文帝所善,官至振威将军。假节都督河北诸军事,封列侯。 +686 IhSac 996271948 受诏典著作,又为《魏官仪》,凡所撰述数十篇。好古文、鸟篆、隶草,无所不善。建安末,尚书右丞河南潘勖,黄初时,散骑常侍河内王象。亦与觊并以文章显。觊薨,谥曰敬侯。子瓘嗣。瓘咸熙中为镇西将军。 +687 RBohQ 798820970 刘助字孔才,广平邯郸人也。建安中,为计吏,诣许。 +688 mfYZH 523497398 助尝作《赵都赋》,明帝美之,诏劭作《许都》、《洛都赋》。时外兴军旅,内营宫室,劭作二赋,皆讽谏焉。 +689 QScbP 105278663 会明帝崩,不施行。正始中,执经讲学,赐爵关内侯。凡所撰述,《法论》、《人物志》之类百余篇。卒,追赠光禄勋。子琳嗣。 +690 NlaZi 331867860 后征泰为尚书右仆射,典选举,加倍中光禄大夫。吴大将孙峻出淮、泗。以泰为镇军将军,假节都督淮北诸军事,诏徐州监军己下受泰节度。 +691 yzEGQ 806852203 于本嗣,历位郡守、九卿。所在操纲领,举大体,能使群下自尽。有统御之才,不亲小事,不读法律。而得廷尉之称优于司马峻等。精练文理。迁镇北将军,假节都督河北诸军事。薨,子粲嗣。本弟骞,咸熙中为车骑将军。 +692 WYgmd 625571348 初,矫为郡功曹,使过泰山。泰山太守东郡薛悌异之,结为亲友。戏谓矫曰:"以郡吏而交二千石,邻国君屈从陪臣游,不亦可乎!"悌后为魏郡及尚书令,皆承代矫云。 +693 lYgxp 198256399 臻迁为司空,徙司徒。正始中,进爵长垣侯,邑千户,封一子列侯。 +694 QhEYu 414367723 太祖曰:"毓执之是也。又引经典有意,使孤叹息。"由是为丞相法曹议令史,转西曹仪令吏。 +695 CLeiQ 229042241 转为太常,清贫守约,至卖田宅以自给。明帝闻之,加赐谷帛。薨,谥曰简侯。子禽嗣。禽弟适,才爽开济,官至廷尉、吏部尚书。洽同郡许混者,许助子也。清醇有鉴识,明帝时为尚书。 +696 CrUMy 102514118 时代郡大乱,以潜为代郡太守。乌丸王及其大人,凡三人,各自称单于,专制郡事。 +697 Cfuoq 178883747 评曰:和洽清和干理,常林素业纯固,杨俊人伦行义,杜袭温粹识统,赵俨则毅有度,裴潜平恒贞干,皆一世之美士也。至林能不系心于三司,以大夫告老,美矣哉! +698 OpOkK 339655280 韩暨字公至,南阳堵阳人也。同县豪右陈茂,谮暨父兄,几至大辟。暨阳不以为言,庸赁积资,阴结死士,遂追呼寻禽茂,以首祭父墓,由是显名。 +699 CGBfu 703205747 时制,吏遭大丧者,百日后皆给役,有司徒吏解弘遭父丧,后有军事,受敕当行,以疾病为辞。诏怒曰:"汝非曾、闵,何言毁邪?"促收考竟。柔见弘信甚羸劣,奏陈其事,宜加宽贷。帝乃诏曰:"孝哉弘也!其原之。" +700 gobOt 817262877 顷之,护军营士窦礼近出不还。营以为亡,表言逐捕,没其妻盈及男女为官奴婢。盈连至州府,称冤自讼,莫有省者。乃辞诣廷尉。 +701 YXXiK 904222564 景元四年,年九十薨,於日元侯。孙浑嗣。咸熙中,开建五等。以柔等著勋前朝,改封浑昌陆子。 +702 joFjD 737269972 明帝方修宫室,而节气不和,天下少谷。礼固争罢役。诏曰:"敬纳谠言,促遣民作。"时李惠监作,复奏留一月,有所成讫。礼径至作所,不复重奏,称诏罢民,帝奇其意而不责也。 +703 dAtao 490536855 评曰:韩暨处以静居行化,出以任职流称。崔林简朴知能。高柔明于法理。孙礼刚断伉厉。王观清劲贞白:咸克致公辅。及暨年过八十,起家就列。柔保官二十年,元老终位:比之徐邈、常林,于兹为疚矣。 +704 rGEQa 764593642 辛毗杨阜高堂隆传 +705 IMzge 682298041 阜又上疏欲省宫人诸不见幸者,乃召御府吏问后宫人数。吏守旧令,对曰:"禁密,不得宣露。"阜怒,杖吏一百,数之曰:"国家不与九卿为密,反与小吏为密乎?"帝闻而愈敬惮阜。 +706 yQYXV 572852328 帝爱女淑,未期而夭,帝痛之甚,追封平原公主,立庙洛阳,葬于南陵。将自临送,阜上疏曰:"文皇帝、武宣皇后崩,陛下皆不送葬,所以重社稷、备不虞也。何至孩抱之赤子而可送葬也哉?"帝不从。 +707 jqYPp 081596902 帝从其议,改青龙五年春三月为景初元年孟夏四月,服色尚黄,牺牲用白,从地正也。 +708 AXXkn 094038306 书奏,帝览焉。谓中书监、令,曰:"观隆此奏,使朕惧哉!" +709 zLtUq 304903041 初,任城栈潜,太祖世历县令。尝督守邺城。时文帝为太子,耽乐田猎,晨出夜还。潜谏曰:"王公设险以固其国,都城禁卫,用戒不虞。 +710 fNpkk 469594335 评曰:辛毗、杨阜,刚亮公直,正谏匪躬,亚乎汲黯之高风焉。高堂隆学业修明,志在匡君,因变陈戒,发于恳诚,忠矣哉!及至必改正朔,俾魏祖虞,所谓意过其通者欤! +711 ZeyiW 530581554 时袁绍盛于河朔,而汝南绍之本郡,门生宾客布在诸县,拥兵拒守。太祖忧之,以宠为汝南太守。宠募其服从者五百人,率攻下二十余壁。诱其未降渠帅,于坐上杀十余人,一时皆平。得户二万,兵二干人,令就田业。 +712 MHmij 633517093 三年春,权遣兵数千家佃于江北。至八月,宠以为田向收熟,男女布野,其屯卫兵去城远者数百里,可掩击也。遣长吏督三军循江东下,摧破诸屯,焚烧谷物而还。诏美之,因以所获尽为将士赏。 +713 QTrIr 114880552 田豫字国让,渔阳雍奴人也。刘备之奔公孙瓒也,豫时年少,自托于备,备甚奇之。备为豫州刺史,豫以老母求归,备涕泣与别。曰:"恨不与君共成大事也。" +714 QNoLw 687549667 初,豫以太守督青州,青州刺史程喜内怀不服,军事之际,多相违错。喜知帝宝爱明珠,乃密上:"豫虽有战功,而禁令宽弛,所得器仗珠金甚多,放散皆不纳官。"由是功不见列。 +715 WYmpS 417998350 评曰:满宠立志刚毅,勇而有谋。田豫居身清白,规略明练。牵招秉义壮烈,威绩显著。郭淮方策精详,垂问秦、雍。而豫位止小州,招终于郡守,末尽其用也。 +716 WJdLI 359807951 胡质字文德,楚国寿春人也。少与将济、未绩俱知名于江、淮间,仕州郡。蒋济为别驾,使见太祖。 +717 VjPYw 714929658 孔子曰:"吾之于人,谁毁谁誉。如有所誉,必有所试。又曰:'于贡方人。赐也贤乎哉,我则不暇。"以圣人之德,犹尚如此,况庸庸之徒而轻毁誉哉? +718 WRekL 682852537 评曰:徐邈清尚弘通,胡质素业贞粹,王昶开济识度,王基学行坚白,皆掌统方任,垂称著绩。可谓国之良臣,时之彦士矣。 +719 uMcbo 110359800 王毋丘诸葛邓钟传 +720 uEDYx 866402205 二年,吴大将全琮数万众寇芍陂,淩率诸军逆讨。与贼争塘,力战连日,贼退走。进封南乡侯,邑千三百五十户,迁车骑将军、仪同三司。 +721 vwlKR 402137895 孔子曰:"足食足兵,食在兵前也。上无设爵之劝,则下无财畜之功。今使考绩之赏,在于积粟富民,则交游之路绝,浮华之原塞矣。" +722 gqmlc 127835499 会尝论《易》无互体、才性同异。及会死后,于会家得书二十篇,名曰《道论》。而实刑名家也,其文似会。初,会弱冠与山阳王弼并知名。弼好论儒道,辞才逸辩,注《易》及《老子》,为尚书郎,年二十余卒。 +723 cXDiO 174824405 东阳陈叔山小男二岁得疾,下利常先啼,日以羸困。问佗,佗曰:"其母怀躯,阳气内养,乳中虚冷,儿得母寒,故令不时愈。"佗与四物女宛丸,十日即除。 +724 dgVgt 908735343 彭城夫人夜之厕。虿螫其手,呻呼无赖。佗令温汤近热,渍手其中,卒可得寐,但旁人数为易汤,汤令暖之,其旦即愈。 +725 dhZaT 303306963 军吏梅平得病,除名还家,家居广陵,未至二百里,止亲人舍。有顷,佗偶至主人许,主人令佗视平,佗谓平曰:"君早见我,可不至此。今疾已结,促去可得与家相见,五日卒。"应时归,如佗所刻。 +726 SREHR 895472517 弟子河南邵登、张泰、桑馥,备至太乐丞,下邳陈颃司律中即将。自左延年等虽妙于音,咸善郑声,其好古存正莫及夔。 +727 PsZaC 153012922 辂又至郭恩家,有飞鸠来在梁头,鸣甚悲。辂曰:"当有老公从东方来,携豚一头,酒一壶。主人虽喜,当有小故。"明日果有客,如所占。恩使客节酒、戒肉,慎火,而射鸡作食,箭从树间激中数岁女子手,流血惊怖。 +728 TkbRN 958136787 正元二年,弟辰谓 +729 VCmaJ 621317054 《书》载"蛮夷猾夏",《诗》称"猃狁孔炽",久矣其为中国患也。 +730 bPfxu 468345892 侯准既僭号称王。为燕亡人卫满所攻夺,将其左右宫人走人海。居韩地,自号韩王。其后绝灭,今韩人犹有奉其祭祀者。汉时属乐浪郡,四时朝谒。 +731 eeWqg 603819617 桓、灵之末,韩(氵岁)强盛,郡县不能制,民多流入韩国。 +732 qkWyW 117753396 评曰:《史》、《汉》著朝鲜、两越,东京撰录西羌。魏世匈奴遂衰,更有乌丸、鲜卑,爰及东夷,使译时通,记述随事,岂常也哉! +733 ecPCN 815920258 明年,先主至葭萌,还兵南向,所在皆克。十九年,进围成都数十日,城中尚有精兵三万人,谷帛支一年,吏民咸欲死战。 +734 pixdJ 433470457 是岁,璋还成都。先主北到葭萌,未即讨鲁,厚树恩德,以收众心。 +735 puFQP 768307868 二十三年,先主率诸将进兵汉中,分遣将军吴兰、雷铜等入成都,皆为曹公军所没。先主次于阳平关,与渊、郃等相拒。 +736 qOppY 730502115 章武元年夏四月,大赦,改年。以诸葛亮为丞相,许靖为司徒。置百官,立宗庙,袷祭高皇帝以下。 +737 ulKSK 838342815 建兴元年夏,臧柯太守朱褒拥郡反。先是,益州郡有大姓雍闿反,流太守张裔于吴,据郡不宾,越巂夷王高定亦背叛。是岁,立皇后张氏。遣尚书(郎)邓芝固好于吴,吴王孙权与蜀和亲使聘,是岁通好。 +738 TYNJA 191419849 三年春,务农殖谷,闭关息民。 +739 idHfb 519874769 三年春三月,丞相亮南征四郡,四郡皆平。改益州郡为建宁郡,分建宁、永昌郡为云南郡,又分建宁、臧柯为兴古郡。十二月,亮还成都。 +740 wyqPG 961395237 四年春,都护李严自永安还住江州,筑大城。五年春,丞相亮出屯汉中,营沔北阳平石马。 +741 FZoyI 340470262 六年春,亮出攻祁山,不克。冬,复出散关,围陈仓,粮尽退。魏将王双率军追亮,亮与战,破之,斩双,还汉中。 +742 YcGad 947796158 七年春,亮遣陈式攻成都、阴平,遂克定二郡。冬,亮徙从府营于南山下原上,筑汉、乐二城。是岁,孙权称帝,与蜀约盟,共交分天下。 +743 NsHub 940342135 八年秋,魏使司马懿由西城,张郃由子午,曹真由斜谷,欲攻汉中。丞相亮待之于城固、赤坂,大雨道绝,真等皆还。是岁,魏延破魏雍州剌史郭淮于阳溪。徙鲁王永为甘陵王,梁王理为安平王,皆以鲁、梁在吴分界故也。 +744 NTTfj 643453533 九年春二月,亮复出军围祁山,始以木牛运。魏司马懿、张郃救祁山。夏六月,亮粮尽退军,郃追至青封,与亮交战,被箭死。秋八月,都护李严废徙梓潼郡。 +745 qgqzs 933776321 十年,亮休士劝农于黄沙,作流马木牛毕,教兵讲武。 +746 Mfrxb 655819818 十一年冬,亮使诸军运米,集于斜谷口,治斜谷邸阁。是岁,南夷刘胄反,将军马忠破平之。 +747 qPtjC 165650328 十三年春正月,中军师杨仪废徙汉嘉郡。夏四月,进蒋琬位为大将军。 +748 gIjxz 397531933 十四年夏四月,后主至湔,登观坂,看汶水之流,旬日还成都。徙武都氐王苻健及氐民四百余户于成都。 +749 boAEH 520847687 十五年夏六月,皇后张氏薨。 +750 WUZJb 244170097 延熙元年春正月,立皇后张氏。大赦,攻元。立子睿为太子,子瑶为安定王。冬十一月,大将军蒋琬出屯汉中。 +751 tHHGf 400269337 二年春三月,进蒋琬位为大司马。 +752 VqZDv 778434340 三年春,使越巂太守张嶷平定越巂郡。 +753 ZVFDh 817925559 四年冬十月,尚书令费祎至汉中,与蒋琬咨论事计,岁尽还。五年春正月,监军姜维督偏军,自汉中还屯涪县。 +754 lNyHZ 770922921 六年冬十月,大司马蒋琬自还汉中,住涪。十一月,大赦。以尚书令费祎为大将军。 +755 VfxLv 535641087 七年闰月,魏大将军曹爽、夏侯玄等向汉中,镇北大将军王平拒兴势围,大将军费祎督诸军往赴救,魏军退。夏四月,安平王理卒。秋九月,祎还成都。 +756 vJnRo 388872314 八年秋八月,皇太后薨。十二月,大将军费祎至汉中,行围守。 +757 eogtC 744946216 九年夏六月,费祎还成都。秋,大赦。冬十一月,大司马蒋琬卒。 +758 tTHPV 598619963 十年,凉州胡王白虎文、治无戴等率众降,卫将军姜维迎逆安抚,居之于繁县。是岁,汶山平康夷反,维往讨,破平之。 +759 dorGJ 109499418 十一年夏五月,大将军费祎出屯汉中。秋,涪陵属国民夷反,车骑将军邓芝往讨,皆破平之。 +760 pjbzy 340118312 十二年春正月,魏诛大将军曹爽等,右将军夏侯霸来降。夏四月,大赦。秋,卫将军姜维出攻雍州,不克而还。将军句安、李韶降魏。 +761 FibMj 806376372 十三年,姜维复出西平,不克而还。 +762 aoKFs 535881300 十四年夏,大将军费祎还成都。冬,复北驻汉寿。大赦。 +763 dKoQy 479715091 十五年,吴王孙权薨。立子琮为西河王。 +764 AODFF 734286677 十六年春正月,大将军费祎为魏降人郭脩所杀于汉寿。夏四月,卫将军姜维复率众围南安,不克而还。 +765 DdIFn 075394717 十七年春正月,姜维还成都。大赦。夏六月,维复率众出陇西。冬,拔狄道、(河间)[河关]、临洮三县民,居于绵竹、繁县。 +766 dTtcL 657661221 十八年春,姜维还成都。夏,复率诸军出狄道,与魏雍州剌史王经战于洮西,大破之。经退保狄道城,维却住钟题。 +767 wiHfw 141004095 十九年春,进姜维位为大将军,督戎马,与镇西将军胡济期会上邽,济失誓不至。秋八月,维为魏大将军邓艾所破于上邽。维退军还成都。是岁,立子瓒为新平王。大赦。 +768 XoEvT 089299442 二十年,闻魏大将军诸葛诞据寿春以叛,姜维复率众出骆谷,至芒水。是岁大赦。 +769 EOvNK 060797750 景耀元年,姜维还成都。史官言景星见,于是大赦,改年。宦人黄皓始专政。吴大将军孙琳废其主亮,立琅邪王休。 +770 xExWN 211245630 二年夏六月,立子谌为北地王,恂为新兴王,虔为上党王。 +771 yzvJZ 259842633 三年秋九月,追谥故将军关羽、张飞、马超、庞统、黄忠。 +772 MAgQi 750548273 四年春三月,追谥故将军赵云。冬十月,大赦。 +773 skfau 320171419 五年春正月,西河王琮卒。是岁,姜维复率众出侯和,为邓艾所破,还住沓中。 +774 WKleb 504064190 后主敬哀皇后,车骑将军张飞长女也。章陵元年,纳为太子妃。建兴元年,立为皇后。十五年薨,葬南陵。 +775 eFMiZ 145068179 评曰:《易》称有夫妇然后有父子,夫人伦之始,恩纪之隆,莫尚于此矣。是故纪录,以究一国之体焉。 +776 tzprm 871354927 初,亮自表后主曰:"成都有桑八百株,薄田十五顷,子弟衣食,自有余饶。至于臣在外任,无别调度,随身衣食,悉仰于官,不别治生,以长尺寸。若臣死之日,不使内有余帛,外有羸财,以负陛下。"及卒,如其所言。 +777 ZtxOc 772644474 亮性长于巧思,损益连弩,木牛流马,皆出其意;推演兵法,作八陈图,咸得其要云。亮言教书奏多可观,别为一集。 +778 txCwd 250684476 景耀六年春,诏为亮立庙于沔阳。秋,魏征西将军钟会征蜀,至汉川,祭亮之庙,令军士不得于亮墓所左右刍牧樵采。亮弟均,官至长水校尉。亮子瞻,嗣爵。 +779 wuJuj 680322039 伏惟陛下迈踪古圣,荡然无忌,故虽敌国诽谤之言,咸肆其辞而无所革讳,所以明大通之道也。谨录写上诣著作。臣寿诚惶诚恐,顿首顿首,死罪死罪。泰始十年二月一日癸巳,平阳侯相臣陈寿上。 +780 xLpBX 203337996 追谥羽曰壮缪侯。子兴嗣。兴字安国,少有令问,丞相诸葛亮深器异之。弱冠为侍中、中监军,数岁卒。子统嗣,尚公主,官至虎贲中郎将。卒,无子,以兴庶子彝续封。 +781 dPhQO 367095073 七年卒,追谥顺平侯。 +782 sZXjz 838964677 评曰:庞统雅好人流,经学思谋,于时荆、楚谓之高俊。法正著见成败,有奇画策算,然不以德素称也。儗之魏臣,统其荀彧之仲叔,正其程、郭之俦儷邪 +783 GvEkd 010192280 芳为南郡太守,与关羽共事,而私好携贰,叛迎孙权,羽因覆败。竺面缚请罪,先主慰谕以兄弟罪不相及,崇待如初。竺惭恚发病,岁馀卒。子威,官至虎贲中郎将。威子照,虎骑监。自竺至照,皆便弓马,善射御云。 +784 wZJog 372086962 先主既定益州,广汉太守夏侯纂请宓为师友祭酒,领五官掾,称曰仲父。宓称疾,卧在第舍,纂将功曹古朴,主簿王普,厨膳即宓第宴谈, +785 DLZpg 824156612 宓卧如故。纂问朴曰:"至于贵州养生之具,实绝余州矣,不知士人何如余州也?"朴对曰:"乃自先汉以来,其爵位者或不如余州耳,至于著作为世师式,不负于余州也。严君平见黄、老作《指归》,扬雄见 +786 pUmTG 480839375 《易》作《太言》,见《论语》作《法言》,司马相如主武帝制封禅之文,于今天下所共闻也。" +787 dCXst 189016195 纂曰:"仲父何如?"宓以簿击颊,曰:"愿明府勿以仲父之言假于小草,民请为明府陈其本纪。蜀有汶阜之山,江出其腹,帝以会昌,神以建福,故能沃野千里。淮、济四渎,江为其首,此其一也。禹生石纽, +788 SWzzK 383779523 今之汶山郡是也。昔尧遭洪水,鲧所不治,禹疏江决河,东注于海,为 +789 iqPdm 202350722 民徐害,生民已来功莫先者,此其二也。天帝布治房心,决政参伐,参伐则益州分野,三皇乘祗车出谷口,今之斜谷是也。此便鄙州之阡陌,明府以雅意论之,何若于天下乎?"于是纂逡巡无以复答。 +790 RmELC 824185259 宓曰:"在西方。《诗》曰:'乃眷西顾。'以此推之,头在西方。" +791 STjlL 519847480 温曰:"天有耳乎?"宓曰:"天处高而听卑,《诗》云:'鹤鸣于九皋,声闻于天。'若其无耳,何以听之?"温曰:"天有足乎?"宓曰: +792 flxiG 678835053 "有。《诗》云:'天步艰难,之子不犹。'若其无足,何以步之?" +793 Rpbry 934212707 温曰:"天有姓乎?"宓曰:"有。"温曰:"何姓?"宓曰:"姓刘。" +794 WVycG 610583352 温曰:"何以知之?"答曰:"天子姓刘,故以此知之。"温曰:"日生于东乎?"宓曰:"虽生于东而没于西。"答问如响,应声而出,于 +795 BWdxj 220769211 是温大敬服。宓之文辩,皆此类也。迁大司农,四年卒。初宓见帝系之文,五帝皆同一族,宓辨其不然之本。又论皇帝王霸(养)[豢]龙之说, +796 etKQV 108765799 甚有道理,谯允南少时数往咨访,纪录其言于《春秋然否论》,文多故不载。 +797 SQlXC 792252109 评曰:许靖夙有名誉,既以笃厚为称,又以人物为意,虽行事举动,未悉允当,蒋济以为"大较廊庙器"也。麋竺、孙乾、简雍、伊藉,皆雍容风议,见礼于世。秦宓始慕肥遁之高,而无若愚之实。然专对有余, +798 foCcJ 444107555 文藻壮美,可谓一时之才士矣。 +799 yOjKu 566315786 先主称尊号,以良为侍中。及东征吴,遣良入武陵招纳五溪蛮夷,蛮夷渠帅皆受印号,咸如意指。会先主败绩于夷陵,良亦遇害。先主拜良子秉为骑都尉。 +800 ADweN 780196448 陈祗代允为侍中,与黄皓互相表里,皓始预政事。祗死后,皓从黄门令为中常侍、奉车都尉,操弄威柄,终至覆国。蜀人无不追思允。及邓艾至蜀,闻皓奸险,收闭,将杀之,而皓厚赂艾左右,得免。 +801 sUTKo 917017134 杜祺历郡守、监军、大将军司马,刘干官至巴西太守,皆与乂亲善,亦有当时之称,而俭素守法,不及于囗。 +802 FcbIl 390771602 评曰:董和蹈羔羊之素,刘巴履清尚之节,马良贞实,称为令士,陈震忠恪,老而益笃,董允匡主,义形于色,皆属臣之良矣。吕乂临郡则垂称,处朝则被损,亦黄、薛之流亚矣。 +803 LrheJ 433720088 刘彭廖李刘魏杨传 +804 exKXS 866686277 评曰:刘封处嫌疑之地,而思防不足以自卫。彭囗、廖立以才拔进,李严以干局达,魏延以勇略任,杨仪以当官显,刘琰旧仕,并咸贵重。览其举措,迹其规矩,招祸取咎,无不自己也。 +805 haboi 750017301 王冲者,广汉人也。为牙门将,统属江州李严。为严所疾,惧罪降魏。魏以冲为乐陵太守。 +806 CXgxI 938197424 评曰:霍峻孤城不倾,王连固节不移,向朗好学不倦,张裔肤敏应机,杨洪乃心忠公,费诗率意而言,皆有可纪焉。以先主之广济,诸葛之准绳,诗吐直言,犹用陵迟,况庸后乎哉! +807 DawCd 957931254 杜周杜许孟来尹李谯郤传 +808 ajoUd 524923622 杜微字国辅,锌潼涪人也。少受学于广汉任安。刘障辟为从事,以疾去官。及先主定蜀,微常称聋,闭门不出。 +809 qumJh 374768168 群卒,子臣颇传其术。 +810 ofYQp 934165639 评曰:黄权弘雅思量,李恢公亮志业,吕凯守节不回,马忠扰而能毅,王平忠勇而严整,张嶷识断明果,咸以所长,显名发迹,遇其时也。 +811 LQIsO 308048091 张表有威仪风观,始名位与戏齐,后至尚书,督庲降、后将军,先戏没。祁、汰各早死。 +812 vDTHZ 157559118 戏以延熙四的著《季汉辅臣赞》。其所颂述,今多载于《蜀书》,是以记之于左。自此之后卒者,则不追谥,故或有应见称纪而不在乎篇者也。其戏之所赞而今不作传者,余皆注疏本末于其辞下,可以觕知其仿佛云尔。 +813 rLGJM 401752050 忠武英高,献策江滨,攀吴连蜀,权我世真。受遗阿衡,整武齐文,敷陈德教,理物移风,贤愚竞心,佥忘其身。诞静邦内,四裔以绥,屡临敌庭,实耀其威,研精大国,恨于未夷。赞诸葛丞相 +814 CNDED 563087341 司徒清风,是咨是臧,识爱人伦,孔音锵锵。 +815 fSRpH 318712813 关、张赳赳,出身匡世,扶翼携上,雄壮虎烈。藩屏左右,翻飞电发,济于艰难,赞主洪业,侔迹韩、耿,齐声双德。交待无礼,并致奸慝,悼惟轻虑,陨身匡国。 +816 QaVHV 629542292 赞关云长、张益德 +817 cCDUS 850692258 骠骑夺起,连横合从,首事三秦,保据河、潼。宗计于朝,或异或同,敌以乘衅,家破军亡。乖道反德,托凤攀龙。 +818 ELEom 836064813 翼侯良谋,料世兴衰,委质于主,是训是谘,暂思经算,睹事知机。 +819 RUGJJ 683261110 军师美至,雅气晔晔,致命明主,忠情发臆,惟此义宗,亡身报德。 +820 HWtUB 996132491 将军敦壮,摧锋登难,立功立事,于时之干。 +821 KnWFU 915181152 掌军情节,亢然恒常,谠言惟司,民思其纲。 +822 XhUzV 493851048 安远强志,允休允烈,轻财果壮,当难不惑,以少御多,殊方保业。 +823 MGQpU 923747109 孔山名方,南郡人也。以荆州从事随先主入蜀。蜀既定,为犍为属国都尉,因易郡名,为朱提太守,迁为安远将军、庲降都督,住南昌县。章武二年卒。失其行事,故不为传。 +824 KVcLO 323481834 扬威才干,欷歔文武,当官理任,衎衎辩举,图殖财施,有义有叙。 +825 rKRoS 220712032 尚书清尚,敕行整身,抗志存义;味览典文,倚其高风,好侔古人。 +826 kVuWd 836552960 安汉雍容,或婚或宾,见礼当时,是谓循臣。 +827 coGxU 307824806 少府修慎,鸿胪明真,谏义隐行,儒林天文,宣班大化,或首或林。 +828 WoIFA 384192936 赞王元泰、何彦英、杜辅国、周仲直 +829 Wtuio 504250377 车骑高劲,惟其泛爱,以弱制强,不陷危坠。 +830 XeDfg 318919458 辅汉惟聪,既机且惠,因言远思,切问近对,赞时休美,和我业世。 +831 xZnyf 218708705 镇北敏思,筹画有方,导师禳秽,遂事成章。偏任东隅,末命不祥,哀悲本志,放流殊疆。 +832 MeKab 026634246 越骑惟忠,历志自祗,职于内外,念公忘私。 +833 NvraL 753640587 征南厚重,征西忠克,统时选士,猛将之烈。 +834 gzaGe 528661413 赞赵子龙、陈叔至 +835 cLINF 061061424 叔至名到,汝南人也。自豫州随先主,名位常亚赵云,惧以忠勇称。建兴初,官至永安都督、征西将军,封亭侯。镇南粗强,监军尚笃,并豫戎任。任自封裔。 +836 ajQqT 028725743 赞辅元弼、刘南和 +837 krKWI 089174603 辅元弼名匡,襄阳人也。随先主入蜀。益州既定,为巴郡太守。建兴中,徙镇南,为右将军,封中乡侯。 +838 nWHdL 292190428 刘南和名邕,义阳人也。随先主入蜀。益州既定,为江阳太守。建兴中,稍迁至监军、后将军,赐爵关内侯,卒。子式嗣。少子武,有文,与樊建齐名,官亦至尚书。司农性才,敷述允章,藻丽辞理,斐斐有光。 +839 YlOTV 044562897 威公狷狭,取异众人;闲则及理,逼则伤侵,舍顺入凶,《大易》之云。 +840 QEaYe 093462389 季常良实,文经勤类,士元言规,处仁闻计。孔休、文祥,或才或臧,播播述志,楚之兰芳。 +841 CabDa 407818657 赞马季常、卫文经、韩士远、张处仁、殷孔休、习文祥 +842 ptClx 264408971 孔休名观。为荆州主簿、别驾从事,见《先主传》。失其郡县。文祥名祯,襄阳人也。随先主入蜀,历雒、郫令,南广汉太守。失其行事。子忠,官至尚书郎。 +843 qBxHV 313715506 国山休风,永南耽思;盛衡、承伯,言藏言时;孙德果锐,伟南笃常。德绪,义强,志壮气刚。济济修志,蜀之芬香。 +844 JpSgp 221609173 赞王国山,李永南,马盛衡,马承伯,李孙德,李伟南,龚德绪,王义强 +845 pTCEH 775185854 孙德,名福,梓潼涪人也。先主定益州后,为书佐、西充国长、成都令。建兴元年,徙巴西太守,为江州督、扬威将军,入为尚书仆射,封平阳候。延熙初,大将军蒋琬出征汉中,福以前监军领司马,卒。 +846 YVkST 952534082 伟南名朝,永南兄。郡功曹,举孝廉,临邛令,入为别驾从事,随先主东征吴。章武二年卒于永安。 +847 rBOBl 619122695 休元轻寇,损时致害,文进奋身,同此颠沛。患生一人,至于弘大。 +848 oxzRu 317916333 赞冯休元、张文进 +849 HfRIX 679945632 休元名习,南郡人。随先主入蜀。先主东征吴,习为领军,统诸军,大败于猇亭。 +850 VFtvJ 315709534 公弘后生,卓尔奇精,天命二十,悼恨未呈。 +851 nQCHK 476564904 公弘,名祁,季然之子也。古之奔臣,礼有来逼,怨兴司官,不顾大德。靡自匡救,倍成奔北,自绝于人,作笑二国。 +852 jOiGx 811751712 赞糜芳、士仁、郝普、潘浚 +853 HgOFJ 583369364 评曰:"邓芝坚贞简亮,临官忘家,张翼亢姜维之锐,宗预御孙权之严,咸有可称。杨戏商略,意在不群,然智度有短,殆罹世难云。 +854 JPcJE 742603341 孙坚字文台,吴郡富春人,盖孙武之后也。 +855 pHCQi 538513214 初平三年,术使坚征荆州,击刘表。表遣黄祖逆于樊、邓之间。坚击破之,追渡汉水,遂围襄阳,单马行岘山,为祖军士所射杀。兄子贲,帅将士众就术。术复表贲为豫州刺史。 +856 qFJLj 085326197 坚四子:策、权、翊、匡。权既称尊号,谥坚曰武烈皇帝。 +857 lqgrY 348049906 策字伯符。坚初兴义兵,策将母徙居舒。与周瑜相友,收合士大夫,江、淮间人咸向之。坚薨,还葬曲阿。已乃渡江居江都。 +858 JmkWu 534761243 权称尊号,追谥策曰长沙桓王,封子绍为吴侯,后改封上虞侯。绍卒,子奉嗣。孙皓时,讹言谓奉当立,诛死。 +859 jayjo 386734718 评曰:"孙坚勇挚刚毅,孤微发迹,导温戮卓,山陵杜塞,有忠壮之烈。策英气杰济,猛锐冠世,览奇取异,志陵中夏。然皆轻佻果躁,陨身致败。且割据江东,策之基兆也。而权尊祟未至,子止侯爵,于义俭矣。 +860 XUvUN 100419184 七年,权母吴氏薨。 +861 pduJo 036483204 八年,权西伐黄祖,破其舟军,惟城未克,而山寇复动。还过豫章,使吕范平鄱阳,(会稽)程普讨乐安。太史慈领海昏,韩当、周泰、吕蒙等为剧县令长。 +862 VdChA 277318754 九年,权弟丹杨太守翊为左右所害,以从兄瑜代翊。 +863 ZIfzF 131098708 十年,权使贺齐讨上饶,分为建平县。 +864 wVIwI 392737108 十二年,西征黄祖。虏其人民而还。 +865 fnUyH 893792955 十四年,瑜、仁相守岁余,所杀伤甚众。仁委城走。权以瑜为南郡太守。刘备表权行车骑将军,领徐州牧。备领荆州牧,屯公安。 +866 EvogZ 665312310 十五年,分豫章为鄱阳郡;分长沙为汉昌郡。以鲁肃为太守,屯陆口。 +867 dWVwo 440844968 十六年,权徙治秣陵。明年,城石头,改秣陵为建业。闻曹公将来侵,作濡须坞。 +868 gaiKE 188260388 十八年正月,曹公攻濡须,权与相拒月余。曹公望权军,叹其齐肃,乃退。初,曹公恐江滨郡县为权所略,征令内移。民转相惊,自庐江、九江、蕲春、广陵户十余万皆东渡江。江西遂虚,合肥以南惟有皖城。 +869 GmXiq 461558783 二十一年冬,曹公次于居巢,遂攻濡须。 +870 HkYay 923699671 二十二年春,权令都尉徐详诣曹公请降,公报使修好,誓重结婚。 +871 ESsIG 585763763 二十三年十月,权将如吴,亲乘马射虎于庱亭。马为虎所伤,权投以双戟,虎却废。常从张世击以戈,获之。 +872 YRPiO 234084414 二十五年春正月,曹公薨。太子丕代为丞相魏王,改年为延康。秋,魏将梅敷使张俭求见抚纳。南阳阴、酂筑阳、山都、中庐五县民五千家来附。冬,魏嗣王称尊号,改元为黄初。 +873 sxjVv 040341777 黄武元年春正月,陆逊部将军宋谦等攻蜀五屯,皆破之,斩其将。三月,鄱阳言黄龙见。蜀军分据险地,前后五十余营。逊随轻重以兵应拒,自正月至闰月,大破之。临陈所斩及投兵降首数万人。刘备奔走,仅以身免。 +874 rjvuo 264058081 三年夏,遣辅义中郎将张温聘于蜀。秋八月,赦死罪。九月,魏文帝出广陵,望大江,曰"彼有人焉,未可图也",乃还。 +875 VxszZ 846529189 四年夏五月,丞相孙邵卒。六月,以太常顾雍为丞相。皖口言木连理。冬十二月,鄱阳贼彭绮自称将军,攻没诸县,众数万人。是岁地连震。 +876 rsIRI 948479647 六年春正月,诸将,获彭绮。闰月,韩当子综以其众降魏。 +877 JWdWa 961023037 七年春三月,封子虑为建昌侯,罢东安郡。夏五月,鄱阳太守周鲂伪叛,诱魏将曹休。秋八月,权至皖口,使将军陆逊督诸将大破休于石亭。大司马吕范卒。是岁,改合浦为珠官郡。 +878 kszAg 004409028 嘉禾元年春正月,建昌侯虑卒。三月,遣将军周贺、校尉裴潜乘海之辽东。秋九月,魏将田豫要击,斩贺于成山。冬十月,魏辽东太守公孙渊遣校尉宿舒、阆中令孙综称藩于权,并献貂马。权大悦,加渊爵位。 +879 IDiWR 784689059 四年夏,遣吕岱讨桓等。秋七月,有雹。魏使以马求易珠玑、翡翠、瑇瑁,权曰:"此皆孤所不用,而可得马。何苦而不听其交易?" +880 JcwZt 943393954 六年春正月,新都言白虎见。诸葛恪征六安,破魏将谢顺营,收其民人。冬十一月,丞相顾雍卒。十二月,扶南王范旃遣使献乐人及方物。是岁,司马宣王率军入舒,诸葛亮恪自皖迁于柴桑。 +881 zhQIR 068097846 九年春二月,车骑将军朱然征魏柤中,斩获千余。夏四月,武昌言甘露降。秋九月,以骠骑步骘为丞相,车骑朱然为左大司马,卫将军全琮为右大司马,镇南吕岱为上大将军,威北将军诺葛恪为大将军。 +882 okTUd 911480490 十年春正月,右大司马全琮卒。二月,权适南宫。三月,改作太初宫,诸将及州郡皆义作。夏五月,丞相步骘卒。冬十月,赦死罪。 +883 mzxIg 260093101 十二年春三月,左大司马朱然卒。四月,有两乌衔鹊堕东馆。丙寅,骠骑将军朱据领丞相,燎鹊以祭。 +884 IjFOk 684531486 孙亮,字子明,权少子也。权春秋高,而亮最少,故尤留意。姊全公主常谮太子和子母,心自不安。因倚权意,欲豫自结,数称述全尚女,劝为亮纳。赤乌十三年,和废,权遂立亮为太子,以全氏为妃。 +885 zxGAI 074903162 太元元年夏,亮母潘氏立为皇后。冬,权寝疾,征大将军诸葛恪为太子太傅,会稽太守滕胤为太常,并受诏辅太子。明年四月,权薨,太子即尊号。大赦,改元。是岁,于魏嘉平四年也。 +886 LFLAl 614176813 五凤元年夏,大水。秋,吴侯英谋杀峻,觉,英自杀。冬十一月,星茀于斗牛。 +887 DPJKD 541430640 三年春三月,西陵言赤乌见。秋,用都尉严密议,作浦里塘。会稽郡谣言王亮当还为天子,而亮宫人告亮使巫祷祠,有恶言。有司以闻,黜为候官侯,遣之国。道自杀,卫送者伏罪。以会稽南部为建安郡,分宜都置建平郡。 +888 rjdEL 397933764 四年春五月,大雨,水泉涌溢。秋八月,遣光禄大夫周奕、石伟巡行风俗,察将吏清浊,民所疾苦,为黜陟之诏。九月,布山言白龙见。是岁,安吴民陈焦死,埋之,六日更生,穿土中出。 +889 PURXb 424460356 二年春,大赦。右丞相万彧上镇巴丘。夏六月,起显明宫,冬十二月,皓移居之。是岁,分豫章、庐陵、长沙为安成郡。 +890 lJoop 849968687 三年春二月,以左右御史大夫丁固、孟仁为司徒、司空。秋九月,皓出东关,丁奉至合肥。是岁,遣交州刺史刘俊、前部督脩则等人击交阯。为晋将毛炅等所破,皆死。兵散还合浦。 +891 IDHTh 469819913 建衡元年春正月,立子瑾为太子,及淮阳、东平王。冬十月,改年,大赦。十一月,左丞相陆凯卒。遣监军虞汜、威南将军薛珝、苍梧太守陶璜由荆州,监军李勖、督军徐存从建安海道,皆就合浦击交阯。 +892 YeSWO 230244541 天册元年,吴郡言掘地得银,长一尺,广三分,刻上有年月字。于是大赦,改年。 +893 QIysT 568806221 天纪元年夏,夏口督孙慎出江夏、汝南,烧略居民。初,驺子张俶多所谮白,累迁为司直中郎将,封侯,甚见宠爱。是岁,奸情发闻,伏诛。 +894 deLsg 679652947 二年秋七月,立成纪、宣威等十一王,王给三千兵,大赦。 +895 WYcQX 722051930 四年春,立中山、代等十一王,大赦。浚、彬所至,则土崩瓦解,靡有御者。预又斩江陵督伍延,浑复斩丞相张悌、丹杨太守沈莹等,所在战克。 +896 BCwky 394633352 刘繇太史慈士燮传 +897 ktSkL 148713013 刘繇,字正礼,东莱牟平人也。齐孝王少子封牟平侯,子孙家焉。繇伯父宠,为汉太尉。繇兄岱,字公山,历位侍中,兖州刺史。 +898 OJzRH 992359498 刘表从子磐。骁勇,数为寇于艾、西安诸县。策于是分海昬、建昌左右六县,以慈为建昌都尉,治海昬,并督诸将拒磐。磐绝迹,不复为寇。 +899 wFFTm 608500974 燮兄弟并为列郡,雄长一州,偏在万里,威尊无上。出入鸣钟磐,备具威仪,笳箫鼓吹,车骑满道。胡人夹毂焚烧香者常有数十。妻妾乘辎軿,子弟从兵骑,当时贵重,震服百蛮,尉他不足逾也。武先病没。 +900 BkdSs 576922138 评曰:刘繇藻厉名行,好尚臧否。至于扰攘之时,据万里之士,非其长也。太史慈信义笃烈,有古人之分。士燮作守南越,优游终世,至子不慎,自贻凶咎。盖庸才玩富贵而恃阻险,使之然也。 +901 XozWJ 371550028 孙破虏吴夫人,吴主权母也。本吴人,徙钱唐,早失父母。与弟景居。孙坚闻其才貌,欲娶之。吴氏亲戚嫌坚轻狡,将拒焉,坚甚以惭恨。夫人谓亲戚曰:"何爱一女以取祸乎?如有不遇,命也。"于是遂许为婚,生四男一女。 +902 hpOer 212713230 及权少年统业,夫人助治军国,甚有补益。建安七年,临薨,引见张昭等,属以后事,合葬高陵。 +903 wuDHQ 141341156 八年,景卒宫,子奋授兵为将,封新亭侯,卒。子安嗣,安坐党鲁王霸死。奋弟祺嗣,封都亭侯,卒。子纂嗣。纂妻即滕胤女也,胤被诛,并遇害。 +904 BBvSm 277783643 吴主权王夫人,南阳人也。以选人宫,嘉禾中得幸,生(孙)休。及和为太子,和母贵重,诸姬有宠者,皆出居外。夫人出公安,卒,因葬焉。休即位,遣使追尊曰敬怀皇后,改葬敬陵。王氏无后,封同母弟文雍为亭侯。 +905 MCXRp 482818569 孙翊字叔弼,权弟也,骁悍果烈,有兄策风。太守朱治举孝廉,司空辟。建安八年,以偏将军领丹杨太守,时年二十。后卒为左右边鸿所杀,鸿亦即诛。 +906 xUvZp 620090633 子松为射声校尉、都乡侯。黄龙三年卒。蜀丞相诸葛亮与兄瑾书曰:"既受东朝厚遇,依依于子弟。又子乔良器,为之恻怆。见其所与亮器物,感用流涕。"其悼松如此,由亮养子乔咨述故云。 +907 WfjaY 608965119 孙韶字公礼。伯父河,字伯海,本姓俞氏,亦吴人也。孙策爱之,赐姓为孙,列之属籍,后为将军,屯京城。 +908 sxVQf 083102114 评曰:夫亲亲恩义,古今之常。宗子维城,诗人所称。况此诸孙,或赞兴初基,或镇据边陲,克堪厥任,不忝其荣者乎!故详著云。 +909 FSaJb 192044784 初,权当置丞相,众议归昭。权曰:"方今多事,职统者责重,非所以优之也。"后孙邵卒,百寮复举昭,权曰:"孤岂为子布有爱乎?领丞相事烦,而此公性刚,所言不从,怨咎将兴,非所以益之也。"乃用顾雍。 +910 UaNPX 195424420 昭容貌矜严,有威风,权常曰:"孤与张公言,不敢妄也。"举邦惮之。年八十一,嘉禾五年卒。遗令幅巾素棺,敛以时服。权素服临吊,谥曰文侯。长子承已自封侯,少子休袭爵。 +911 xbsxf 252931686 昭弟子奋年二十,造作攻城大攻车,为步骘所荐。昭不愿曰:"妆年尚少,何为自委于军旅乎?"奋对曰:"昔童汪死难,子奇治阿,奋实不才耳,于年不为少也。"遂领兵为将军,连有功效,至(平州)都督,封乐乡亭侯。 +912 MVbNM 836379546 诸葛瑾字子瑜,琅邪阳都人也。汉末避乱江东。值孙策卒,孙权姊婿曲阿弘咨见而异之,荐之于权,与鲁肃等并见宾待。后为权长史,转中司马。建安二十年,权遣瑾使蜀通好刘备,与其弟亮俱公会相见,退无私面。 +913 FJInF 941384815 虞翻以狂直流徙,惟瑾屡为之说。翻与所亲书曰:"诸葛敦仁,则天活物,比蒙清论,有以保分。恶积罪深,见忌殷重,虽有祁老之救,德无羊舌,解释难冀也。" +914 usTKO 376991900 步骘字子山,临淮淮阴人也。世乱,避难江东,单身穷困。与广陵卫旌同年相善,俱以种瓜自给,昼勤四体,夜诵经传。 +915 QEKIk 976480500 赤乌九年,代陆逊为丞相,犹诲育门生,手不释书。被服居处有如儒生。然门内妻妾服饰奢绮,颇以此见讥。在西陵二十年,邻敌敬其威信。性宽弘得众,喜怒不形于声色,而外内肃然。 +916 jTVzd 839229362 薛综字敬文,沛郡竹邑人也。少依族人避地交州,从刘熙学。士燮既附孙权,召综为五官中郎(将),除合浦、交阯太守。 +917 anthn 067203823 天纪四年,督军征皓,皓奉书司马伷、王浑、王浚请降,其文,莹所造也。莹既至洛阳,特先见叙,为散骑常侍,答问处当,皆有条理。太康三年卒。著书八篇,名曰《新议》。 +918 KupQp 119196644 评曰:张纮文理意正,为世令器,孙策待之亚于张昭,诚有以也,严、程、阚生,一时儒林也。至畯辞荣济旧,不亦长者乎!薛综学识规纳,为吴良臣。及莹纂蹈,允有先风,然于暴酷之朝,屡登显列,君子殆诸。 +919 NMXzG 632281981 瑜少精意于音乐。虽三爵之后,其有阙误。瑜必知之,知之必顾,故时人谣曰:"曲有误,周郎顾。" +920 kCfQc 147380296 瑜兄子峻,亦以瑜元功为偏将军,领吏士千人。峻卒,全琮表峻子护为将。权曰:"昔走曹操,拓有荆州,皆是公瑾,常不忘之。初闻峻亡,仍欲用护,闻护性行危险,用之适为作祸,故便止之。孤念公瑾,岂有已乎?" +921 ruWjq 320686007 师还,遂征合肥,既撤兵,为张辽等所袭,蒙与淩统以死扦卫。后曹公又大出濡须,权以蒙为督,据前所立坞,置强弩万张于其上,以拒曹公。曹公前锋屯未就,蒙攻破之,曹公引退。拜蒙左护军、虎威将军。 +922 BwUAh 657265450 程黄韩蒋周陈董甘淩徐潘丁传 +923 pugwn 957646762 初,钦屯宣城,尝讨豫章贼。芜湖令徐盛收钦屯吏,表斩之,权以钦在远不许,盛由是自嫌于钦。曹公出濡须,钦与吕蒙持诸军节度。盛常畏钦因事害己,而钦每称其善。盛既服德,论者美焉。 +924 XhYoW 114475315 权讨关羽,钦督水军入沔。还,道病卒。权素服举哀,以芜湖民二百户、田二百顷,给钦妻子。子壹封宣城候,领兵拒刘备有功,还赴南郡,与魏交战,临陈卒。壹无子,弟休领兵,后有罪失业。 +925 xAPkd 153834071 曹公出濡须,袭从权赴之,使袭督五楼船住濡须口。夜卒暴风,五搂船倾覆,左右散走舸,乞使袭出。袭怒曰:"受将军任,在此备贼,何等委去也,敢复言此者斩!"于是莫敢干。其夜船败,袭死。权改服临殡,供给甚厚。 +926 bkvBb 562883111 丁奉字承渊,庐江安丰人也。少以骁勇为小将,属甘宁、陆逊、潘璋等。数随征伐,战斗常冠军。每斩将搴旗,身被创夷。稍迁偏将军。孙亮即位,为冠军将军,封都亭侯。 +927 nWmnH 005881422 评曰:"凡此诸将,皆江表之虎臣,孙氏之所厚待也。以潘璋之不修,权能忘过记功,其保据东南,宜哉!陈表将家支庶,而与胄子名人比翼齐衡,拔萃出类,不亦美乎!" +928 eHxWw 867471668 朱治朱然吕范朱桓传 +929 VlOjZ 980783027 建安七年,权表治为(九真)太守,行扶义将军,割娄、由拳、无锡。毗陵为奉邑,置长吏。征讨夷越,佐定东南,禽截黄巾余类陈败、万秉等。黄武元年,封毗陵侯,领郡如故。 +930 OGDLX 694178698 二年,拜安国将军,金印紫绶,徙封故鄣。权历位上将,及为吴王,治每进见,权常亲迎。执版交拜,飨宴赠赐,恩敬特隆,至从行吏,皆得奉贽私觌,其见异如此。 +931 yKmGV 872626282 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +932 hVDme 414466479 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +933 XQdmP 585685304 虞陆张骆陆吾朱传 +934 YrkTp 702759009 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +935 AgIjK 847844416 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +936 bcBhc 043645422 虞陆张骆陆吾朱传 +937 TCznt 924313349 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +938 gmdgA 570167523 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +939 ssRdw 647897924 绩容貌雄壮,博学多识,星历算数无不该览。虞翻旧齿名盛,庞统荆州令士,年亦差长,皆与绩友善。孙权统事,辟为奏曹掾,以直道见惮,出为郁林太守 +940 dwIrR 820257129 虞陆张骆陆吾朱传 +941 kDjNG 694406021 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +942 lwUsR 115281508 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +943 BUrdL 986472921 初,瑁同郡闻人敏见待国邑,优于宗脩,惟瑁以为不然,后果如其言。赤乌二年,瑁卒。子喜亦涉文籍,好人伦,孙皓时为选曹尚书。 +944 lNErQ 156301898 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +945 akEAD 960503420 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +946 mbWxh 752594186 虞陆张骆陆吾朱传 +947 TLJJX 800169667 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +948 udKLC 288770909 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +949 nHwqJ 641981698 虞陆张骆陆吾朱传 +950 NJbdC 508086966 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +951 qpVOX 763025021 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +952 iwoIn 002695325 绩容貌雄壮,博学多识,星历算数无不该览。虞翻旧齿名盛,庞统荆州令士,年亦差长,皆与绩友善。孙权统事,辟为奏曹掾,以直道见惮,出为郁林太守 +953 ZhCxx 523838924 虞陆张骆陆吾朱传 +954 JjGkg 464782955 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +955 KZjIx 034932665 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +956 kSAzw 017475898 初,瑁同郡闻人敏见待国邑,优于宗脩,惟瑁以为不然,后果如其言。赤乌二年,瑁卒。子喜亦涉文籍,好人伦,孙皓时为选曹尚书。 +957 GqAFj 478158796 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +958 RThKr 646886368 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +959 AOLOW 604250289 虞陆张骆陆吾朱传 +960 dlkCh 332835527 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +961 oFoil 685279612 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +962 cHpcW 815711881 虞陆张骆陆吾朱传 +963 lBUUK 153406869 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +964 lIvsg 719561309 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +965 nYuoT 016618472 绩容貌雄壮,博学多识,星历算数无不该览。虞翻旧齿名盛,庞统荆州令士,年亦差长,皆与绩友善。孙权统事,辟为奏曹掾,以直道见惮,出为郁林太守 +966 AEMzU 265346496 虞陆张骆陆吾朱传 +967 vevXE 885728258 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +968 JpFVd 894574484 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +969 HIhrR 359940807 初,瑁同郡闻人敏见待国邑,优于宗脩,惟瑁以为不然,后果如其言。赤乌二年,瑁卒。子喜亦涉文籍,好人伦,孙皓时为选曹尚书。 +970 Ycsbz 775479693 黄武元年,与吕范、贺齐等俱以舟师拒魏将曹休于洞口。值天大风,诸船绠绁断绝,漂没 +971 qVfgf 849050557 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +972 BWCus 439085791 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +973 IEqhJ 663871030 虞陆张骆陆吾朱传 +974 LPBEl 222758821 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +975 QFkTB 926626408 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +976 QhKOk 761782171 虞陆张骆陆吾朱传 +977 TdgfH 232472189 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +978 urOmg 424503067 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +979 sOTJa 682633050 绩容貌雄壮,博学多识,星历算数无不该览。虞翻旧齿名盛,庞统荆州令士,年亦差长,皆与绩友善。孙权统事,辟为奏曹掾,以直道见惮,出为郁林太守 +980 xVObh 187063217 虞陆张骆陆吾朱传 +981 bXXtf 499665897 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +982 dRslD 903358711 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +983 mqBiH 224931803 初,瑁同郡闻人敏见待国邑,优于宗脩,惟瑁以为不然,后果如其言。赤乌二年,瑁卒。子喜亦涉文籍,好人伦,孙皓时为选曹尚书。 +984 LSeem 124325282 黄武元年,与吕范、贺齐等俱以舟师拒魏将曹休于洞口。值天大风,诸船绠绁断绝,漂没 +985 toHRA 029649354 虞陆张骆陆吾朱传 +986 KhitP 700929996 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +987 KmvMT 576070878 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +988 KBAsL 078793745 虞陆张骆陆吾朱传 +989 enSZd 125376453 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +990 vwIdT 711658601 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +991 ztcKb 992974239 虞陆张骆陆吾朱传 +992 hkDFL 816260253 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +993 hwNWp 671465237 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +994 QrwIg 891133628 绩容貌雄壮,博学多识,星历算数无不该览。虞翻旧齿名盛,庞统荆州令士,年亦差长,皆与绩友善。孙权统事,辟为奏曹掾,以直道见惮,出为郁林太守 +995 goohA 970110411 虞陆张骆陆吾朱传 +996 SRaqY 510661470 初,山阴丁览,太末徐陵,或在县吏之中,或众所未识,翻一见之,便与友善,终咸显名。在南十余年,年七十卒。归葬旧墓,妻子得还。 +997 yGyjp 770846528 翻有十一子。第四子汜最知名,永安初,从选曹朗为散骑中常侍,后为监军使者,讨扶严,病卒,汜弟忠,宜都太守。耸,越骑校尉。累迁廷尉,湘东、河间太守昺,廷尉尚书,济阴太守。 +998 QmQPP 246955798 初,瑁同郡闻人敏见待国邑,优于宗脩,惟瑁以为不然,后果如其言。赤乌二年,瑁卒。子喜亦涉文籍,好人伦,孙皓时为选曹尚书。 +999 KKzLe 037972747 陆逊字伯言,吴郡吴人也。本名仪,世江东大族。逊少孤,随从祖庐江太守康在官。袁术与康有隙,将攻康,康遣逊及亲戚还吴。逊年长于康子绩数岁,为之纲纪门户。 +1000 yYunD 089834483 二年春,就拜大司马、荆州牧。 diff --git a/src/test/regress/expected/alter_table_modify.out b/src/test/regress/expected/alter_table_modify.out index f2fdfaf615c388274c5ab8a92cdaa68a075d026f..14c2074309a4d7093b41b78572bdada2b1c5ca06 100644 --- a/src/test/regress/expected/alter_table_modify.out +++ b/src/test/regress/expected/alter_table_modify.out @@ -3556,6 +3556,27 @@ SELECT * FROM "test_modify_view_f1f2F3"; DROP VIEW "test_modify_view_f1f2F3"; DROP TABLE test_at_modify_view_column CASCADE; +-- test MODIFY after ADD COLUMN DEFAULT +CREATE TABLE test_modify_after_add ( + c1 INT, + value_column INT +); +insert into test_modify_after_add values (1,2); +ALTER TABLE test_modify_after_add ADD COLUMN c2 TIMESTAMP(5) default '2025-11-11 11:11:11'; +select * from test_modify_after_add; + c1 | value_column | c2 +----+--------------+-------------------------- + 1 | 2 | Tue Nov 11 11:11:11 2025 +(1 row) + +ALTER TABLE test_modify_after_add MODIFY column c2 TIMESTAMP(5); +select * from test_modify_after_add; + c1 | value_column | c2 +----+--------------+-------------------------- + 1 | 2 | Tue Nov 11 11:11:11 2025 +(1 row) + +DROP TABLE test_modify_after_add; -- END RESET CURRENT_SCHEMA; DROP SCHEMA atbdb_schema CASCADE; diff --git a/src/test/regress/expected/autonomous_cursor.out b/src/test/regress/expected/autonomous_cursor.out index b00ad33b169f16cdcdabe6f4e31ddeef916c8aed..0263573f571a0381273566018ed56115036936a1 100644 --- a/src/test/regress/expected/autonomous_cursor.out +++ b/src/test/regress/expected/autonomous_cursor.out @@ -1912,6 +1912,91 @@ begin END; $$; drop function f1(); +create table source(c1 int,c2 varchar2(100)); +insert into source values(1,'aa'); +insert into source values(2,'bb'); +create table target(c1 int,c2 varchar2(100)); +declare + cursor cur is + select c1,c2 from source; +begin + for data in cur loop + INSERT INTO target values(data.c1,data.c2); + end loop; +end; +/ +declare + cursor cur is + select c1,c2 from source; +begin + for data in cur loop + INSERT INTO target values data; + end loop; +end; +/ +ERROR: unsupported insert into table from record type without desc, may need set behavior_compat_options to allow_procedure_compile_check. at or near "data" +LINE 5: INSERT INTO target values data; + ^ +QUERY: DECLARE cursor cur is + select c1,c2 from source; +begin + for data in cur loop + INSERT INTO target values data; + end loop; +end +declare +begin + for cur in (select c1,c2 from source) loop + insert into target values cur; + commit; + end loop; +end; +/ +ERROR: unsupported insert into table from record type without desc, may need set behavior_compat_options to allow_procedure_compile_check. at or near "cur" +LINE 3: insert into target values cur; + ^ +QUERY: DECLARE begin + for cur in (select c1,c2 from source) loop + insert into target values cur; + commit; + end loop; +end +set behavior_compat_options = 'allow_procedure_compile_check'; +delete from target; +declare + cursor cur is + select c1,c2 from source; +begin + for data in cur loop + INSERT INTO target values data; + end loop; +end; +/ +select * from target order by c1; + c1 | c2 +----+---- + 1 | aa + 2 | bb +(2 rows) + +delete from target; +declare +begin + for cur in (select c1,c2 from source) loop + insert into target values cur; + end loop; +end; +/ +select * from target order by c1; + c1 | c2 +----+---- + 1 | aa + 2 | bb +(2 rows) + +drop table source; +drop table target; +reset behavior_compat_options; -- clean drop schema pl_auto_ref cascade; NOTICE: drop cascades to 2 other objects diff --git a/src/test/regress/expected/create_seg_table.out b/src/test/regress/expected/create_seg_table.out index efdee56ea56f0e875b9531a704726dca6c9ef032..a805970f3d0ac77fd3832c24fe5db071098d421d 100644 --- a/src/test/regress/expected/create_seg_table.out +++ b/src/test/regress/expected/create_seg_table.out @@ -28,6 +28,8 @@ create table tab_segment(a int); create table tab_segment_off(a int) with(segment=off); ERROR: Only support segment storage type while parameter enable_segment is ON. create table tab_segment_on(a int) with(segment=on); +create table tab_segment_compress(a int) with(compresstype=2,compress_chunk_size=512,compress_level=1); +ERROR: compresstype can not be used in segment table. \d+ tab_segment; Table "public.tab_segment" Column | Type | Modifiers | Storage | Stats target | Description @@ -49,6 +51,8 @@ drop table tab_segment; drop table if exists tab_segment_off; NOTICE: table "tab_segment_off" does not exist, skipping drop table if exists tab_segment_on; +drop table if exists tab_segment_compress; +NOTICE: table "tab_segment_compress" does not exist, skipping select pg_sleep(1); pg_sleep ---------- diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out index 67e2838487bceca805af809007659ab3b91d0254..6b946f51a1c1d431efeb78cc32661f9619be8859 100644 --- a/src/test/regress/expected/event_trigger.out +++ b/src/test/regress/expected/event_trigger.out @@ -770,6 +770,9 @@ NOTICE: triggered revoke all on function ddl_command_test() from event_trigger_us; NOTICE: command: REVOKE NOTICE: triggered +alter table event_trigger_tt alter column a type bigint; +NOTICE: command: ALTER TABLE +NOTICE: triggered -- clean drop sequence event_trigger_ss; drop domain event_trigger_dm; diff --git a/src/test/regress/expected/gpi_alter_partition.out b/src/test/regress/expected/gpi_alter_partition.out index b79ce5e8d2c22336504f69dd58e3b65ba575a8be..ed44643b87e561ee09604fd376902b809a01f533 100644 --- a/src/test/regress/expected/gpi_alter_partition.out +++ b/src/test/regress/expected/gpi_alter_partition.out @@ -356,6 +356,7 @@ order by 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; (30 rows) ALTER TABLE alter_table drop partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select part.relname, part.indextblid, part.parttype, part.rangenum, part.intervalnum, part.partstrategy, part.relallvisible, part.reltoastrelid, part.partkey, part.interval, part.boundaries, part.reltuples from pg_class class, pg_partition part, pg_index ind where class.relname = 'alter_table' and ind.indrelid = class.oid and part.parentid = ind.indrelid @@ -535,6 +536,7 @@ order by 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; (27 rows) ALTER TABLE alter_table TRUNCATE partition p2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select part.relname, part.indextblid, part.parttype, part.rangenum, part.intervalnum, part.partstrategy, part.relallvisible, part.reltoastrelid, part.partkey, part.interval, part.boundaries, part.reltuples from pg_class class, pg_partition part, pg_index ind where class.relname = 'alter_table' and ind.indrelid = class.oid and part.parentid = ind.indrelid @@ -714,6 +716,7 @@ order by 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; (27 rows) ALTER TABLE alter_table SPLIT PARTITION p0 AT (2500) INTO (PARTITION p10, PARTITION p11); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select part.relname, part.indextblid, part.parttype, part.rangenum, part.intervalnum, part.partstrategy, part.relallvisible, part.reltoastrelid, part.partkey, part.interval, part.boundaries, part.reltuples from pg_class class, pg_partition part, pg_index ind where class.relname = 'alter_table' and ind.indrelid = class.oid and part.parentid = ind.indrelid @@ -899,6 +902,7 @@ order by 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; (30 rows) ALTER TABLE alter_table MERGE PARTITIONS p10, p11 INTO PARTITION p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select part.relname, part.indextblid, part.parttype, part.rangenum, part.intervalnum, part.partstrategy, part.relallvisible, part.reltoastrelid, part.partkey, part.interval, part.boundaries, part.reltuples from pg_class class, pg_partition part, pg_index ind where class.relname = 'alter_table' and ind.indrelid = class.oid and part.parentid = ind.indrelid @@ -1089,6 +1093,7 @@ order by 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; (27 rows) ALTER TABLE alter_table EXCHANGE PARTITION FOR(2500) WITH TABLE exchange_table; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select part.relname, part.indextblid, part.parttype, part.rangenum, part.intervalnum, part.partstrategy, part.relallvisible, part.reltoastrelid, part.partkey, part.interval, part.boundaries, part.reltuples from pg_class class, pg_partition part, pg_index ind where class.relname = 'alter_table' and ind.indrelid = class.oid and part.parentid = ind.indrelid diff --git a/src/test/regress/expected/gpi_clean_wait.out b/src/test/regress/expected/gpi_clean_wait.out index 238996624bed0995c5828c29155773f47ab3d9ce..8a4fd8ad19cb0ae6b372e316fc4ddcc810b3ea88 100644 --- a/src/test/regress/expected/gpi_clean_wait.out +++ b/src/test/regress/expected/gpi_clean_wait.out @@ -426,6 +426,7 @@ start transaction; alter table test_gpi_more_invalid add partition p5 values less than (4001); update test_gpi_more_invalid set a = a + 1000 where a > 1000 or a < 500; alter table test_gpi_more_invalid drop partition p5; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index commit; -- all global index unusuable select c.relname, i.indisusable from pg_index i join pg_class c on i.indexrelid = c.oid where i.indrelid = 'test_gpi_more_invalid'::regclass ORDER BY c.relname; @@ -530,6 +531,7 @@ select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a (2 rows) alter table interval_normal_date drop partition sys_p2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index commit; select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions diff --git a/src/test/regress/expected/gpi_invalid_part.out b/src/test/regress/expected/gpi_invalid_part.out index 90758221e4682d0561499f95eab4e85125434bfc..7c2e6297b2b9218ecdfcb0900f368a7c017e7b02 100644 --- a/src/test/regress/expected/gpi_invalid_part.out +++ b/src/test/regress/expected/gpi_invalid_part.out @@ -178,6 +178,7 @@ select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where (1 row) alter table gpi_test_invalid_part drop partition p9; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --p9 not exists select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parttype = 'p' and a.relname = 'p9' and a.reloptions[3] like '%wait_clean_gpi=y%' and b.relname = 'gpi_test_invalid_part' order by 1,2,3; relname | parttype | reloptions @@ -268,6 +269,7 @@ select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a (1 row) alter table gpi_test_invalid_part drop partition p9; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --p9 not exists select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parttype = 'p' and a.relname = 'p9' and a.reloptions[3] like '%wait_clean_gpi=y%' and b.relname = 'gpi_test_invalid_part' order by 1,2,3; relname | parttype | reloptions diff --git a/src/test/regress/expected/gpi_set_index_unusable.out b/src/test/regress/expected/gpi_set_index_unusable.out index 421cb1a8a893584349d68902ed8a61760d3a36fe..87e13b171ee5e33ea3c306f92bf1aa98032c67dd 100644 --- a/src/test/regress/expected/gpi_set_index_unusable.out +++ b/src/test/regress/expected/gpi_set_index_unusable.out @@ -509,4 +509,131 @@ select * from test_drop_llt where a=40; set enable_bitmapscan=on; set enable_seqscan=on; drop table if exists test_drop_llt; --- End. Clean up +--astore +CREATE TABLE web_returns_p_a +( + sk_date INTEGER, + cm_num INTEGER, + nv_num INTEGER, + cn_name INTEGER +) +with (STORAGE_TYPE=ASTORE) +PARTITION BY RANGE(sk_date) +( + PARTITION P1 VALUES LESS THAN(1), + PARTITION P2 VALUES LESS THAN(2), + PARTITION P3 VALUES LESS THAN(3), + PARTITION P4 VALUES LESS THAN(4), + PARTITION P5 VALUES LESS THAN(5), + PARTITION P6 VALUES LESS THAN(6), + PARTITION P7 VALUES LESS THAN(7), + PARTITION P8 VALUES LESS THAN(8), + PARTITION P9 VALUES LESS THAN(9), + PARTITION Pmax VALUES LESS THAN(MAXVALUE) +); +insert into web_returns_p_a values (1,1,1,1); +insert into web_returns_p_a values (2,2,2,2); +insert into web_returns_p_a values (3,3,3,3); +insert into web_returns_p_a values (4,4,4,4); +insert into web_returns_p_a values (5,5,5,5); +insert into web_returns_p_a values (6,6,6,6); +insert into web_returns_p_a values (7,7,7,7); +insert into web_returns_p_a values (8,8,8,8); +insert into web_returns_p_a values (9,9,9,9); +create index idx_cm_num_a on web_returns_p_a(cm_num) global; +create index idx_nv_num_a on web_returns_p_a(nv_num) local; +create unique index idx_uq_a on web_returns_p_a(sk_date) global; +set behavior_compat_options = 'update_unusable_unique_index_on_iud'; +alter table web_returns_p_a drop partition p2; +insert into web_returns_p_a values (1,1,1,1); +insert into web_returns_p_a values (1,1,1,1); +ERROR: duplicate key value violates unique constraint "idx_uq_a" +DETAIL: Key (sk_date)=(1) already exists. +update web_returns_p_a set sk_date = 1 where true; +ERROR: duplicate key value violates unique constraint "idx_uq_a" +DETAIL: Key (sk_date)=(1) already exists. +set enable_opfusion = off; +insert into web_returns_p_a values (1,1,1,1); +ERROR: duplicate key value violates unique constraint "idx_uq_a" +DETAIL: Key (sk_date)=(1) already exists. +insert into web_returns_p_a values (1,1,1,1); +ERROR: duplicate key value violates unique constraint "idx_uq_a" +DETAIL: Key (sk_date)=(1) already exists. +update web_returns_p_a set sk_date = 1 where true; +ERROR: duplicate key value violates unique constraint "idx_uq_a" +DETAIL: Key (sk_date)=(1) already exists. +set enable_opfusion = on; +alter index idx_uq_a rebuild; +alter table web_returns_p_a drop partition p3; +reset behavior_compat_options; +insert into web_returns_p_a values (2,2,2,2); +insert into web_returns_p_a values (2,2,2,2); +reset behavior_compat_options; +-- ustore +CREATE TABLE web_returns_p_u +( + sk_date INTEGER, + cm_num INTEGER, + nv_num INTEGER, + cn_name INTEGER +) +with (STORAGE_TYPE=ASTORE) +PARTITION BY RANGE(sk_date) +( + PARTITION P1 VALUES LESS THAN(1), + PARTITION P2 VALUES LESS THAN(2), + PARTITION P3 VALUES LESS THAN(3), + PARTITION P4 VALUES LESS THAN(4), + PARTITION P5 VALUES LESS THAN(5), + PARTITION P6 VALUES LESS THAN(6), + PARTITION P7 VALUES LESS THAN(7), + PARTITION P8 VALUES LESS THAN(8), + PARTITION P9 VALUES LESS THAN(9), + PARTITION Pmax VALUES LESS THAN(MAXVALUE) +); +insert into web_returns_p_u values (1,1,1,1); +insert into web_returns_p_u values (2,2,2,2); +insert into web_returns_p_u values (3,3,3,3); +insert into web_returns_p_u values (4,4,4,4); +insert into web_returns_p_u values (5,5,5,5); +insert into web_returns_p_u values (6,6,6,6); +insert into web_returns_p_u values (7,7,7,7); +insert into web_returns_p_u values (8,8,8,8); +insert into web_returns_p_u values (9,9,9,9); +create index idx_cm_num_u on web_returns_p_u(cm_num) global; +create index idx_nv_num_u on web_returns_p_u(nv_num) local; +create unique index idx_uq_u on web_returns_p_u(sk_date) global; +set behavior_compat_options = 'update_unusable_unique_index_on_iud'; +alter table web_returns_p_u drop partition p2; +insert into web_returns_p_u values (1,1,1,1); +insert into web_returns_p_u values (1,1,1,1); +ERROR: duplicate key value violates unique constraint "idx_uq_u" +DETAIL: Key (sk_date)=(1) already exists. +update web_returns_p_u set sk_date = 1 where true; +ERROR: duplicate key value violates unique constraint "idx_uq_u" +DETAIL: Key (sk_date)=(1) already exists. +set enable_opfusion = off; +insert into web_returns_p_u values (1,1,1,1); +ERROR: duplicate key value violates unique constraint "idx_uq_u" +DETAIL: Key (sk_date)=(1) already exists. +insert into web_returns_p_u values (1,1,1,1); +ERROR: duplicate key value violates unique constraint "idx_uq_u" +DETAIL: Key (sk_date)=(1) already exists. +update web_returns_p_u set sk_date = 1 where true; +ERROR: duplicate key value violates unique constraint "idx_uq_u" +DETAIL: Key (sk_date)=(1) already exists. +set enable_opfusion = on; +alter index idx_uq_u rebuild; +alter table web_returns_p_u drop partition p3; +reset behavior_compat_options; +insert into web_returns_p_u values (2,2,2,2); +insert into web_returns_p_u values (2,2,2,2); +drop index idx_cm_num_a; +drop index idx_nv_num_a; +drop index idx_uq_a; +drop table web_returns_p_a; +drop index idx_cm_num_u; +drop index idx_nv_num_u; +drop index idx_uq_u; +drop table web_returns_p_u; +-- End. Clean u diff --git a/src/test/regress/expected/hw_cstore_truncate.out b/src/test/regress/expected/hw_cstore_truncate.out index 9007d6be11a662866cfe2c71230b6c3ad0f0ef16..0ea4a1243485de8ae9f6d9bb0708b010812692a3 100644 --- a/src/test/regress/expected/hw_cstore_truncate.out +++ b/src/test/regress/expected/hw_cstore_truncate.out @@ -7,8 +7,10 @@ partition create_columnar_table_partition_p5 values less than(4121), partition create_columnar_table_partition_p6 values less than(maxvalue)) ; create index create_columnar_index_1_106 on create_columnar_table_106(c_integer,c_numeric,c_text,c_timestamp_with_timezone) local; alter table create_columnar_table_106 truncate partition create_columnar_table_partition_p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index insert into create_columnar_table_106 values(32431); alter table create_columnar_table_106 truncate partition create_columnar_table_partition_p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index insert into create_columnar_table_106 values(32431); select * from create_columnar_table_106; c_smallint | c_double_precision | c_time_without_time_zone | c_time_with_time_zone | c_integer | c_bigint | c_decimal | c_real | c_numeric | c_varchar | c_char | c_timestamp_with_timezone | c_char2 | c_text | c_varchar2 | c_timestamp_without_timezone | c_date | c_varchar22 | c_numeric2 diff --git a/src/test/regress/expected/hw_cursor_part4.out b/src/test/regress/expected/hw_cursor_part4.out index 3b7dd429265276b512f4d5355e7dae0dc487a71d..daab45b25c4c25498f3f702d7c2c79cd612511fc 100644 --- a/src/test/regress/expected/hw_cursor_part4.out +++ b/src/test/regress/expected/hw_cursor_part4.out @@ -370,9 +370,101 @@ NOTICE: SQL%ROWCOUNT :NULL (1 row) +--test strong cursor +create table tb1(a int); +create table tb2(a int, b text); +insert into tb1 values(1); +insert into tb2 values(1,'one'),(2,'two'); +declare + type cur1 is ref cursor return record; + var cur1; +begin + open var for select * from tb1; +end; +/ +declare + type cur1 is ref cursor return; +begin + null; +end; +/ +ERROR: missing data type declaration +LINE 1: DECLARE type cur1 is ref cursor return; + ^ +QUERY: DECLARE type cur1 is ref cursor return; +begin + null; +end +declare + type cur1 is ref cursor return int[]; +begin + null; +end; +/ +ERROR: invalid cursor return type; _int4 must be a record type +CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 1 +create type typ1_rec as (a int, b text); +declare + type cur1 is ref cursor return typ1_rec; +begin + null; +end; +/ +drop type typ1_rec; +--use in function +create or replace function func1() return int as +declare + type cur1 is ref cursor return tb1%rowtype; + var cur1; + res int; +begin + open var for select * from tb1; + fetch var into res; + return res; +end; +/ +call func1(); + func1 +------- + 1 +(1 row) + +drop function func1; +--use in package +create or replace package pkg1 as + type typ1 is record(a int, b text); + type cur1 is ref cursor return typ1; + procedure proc1(a inout cur1); +end pkg1; +/ +create or replace package body pkg1 as + procedure proc1(a inout cur1) is + declare + var cur1; + res record; + begin + open var for select * from tb2; + fetch var into res; + raise info 'res = %',res; + end; +end pkg1; +/ +declare + var pkg1.cur1; +begin + pkg1.proc1(var); +end; +/ +INFO: res = (1,one) +CONTEXT: SQL statement "CALL pkg1.proc1(var)" +PL/pgSQL function inline_code_block line 3 at SQL statement +drop package pkg1; +NOTICE: drop cascades to function hw_cursor_part4.proc1(refcursor) DROP schema hw_cursor_part4 CASCADE; -NOTICE: drop cascades to 4 other objects +NOTICE: drop cascades to 6 other objects DETAIL: drop cascades to table tbl_rcwscfg drop cascades to table tbl_temp_module_312 drop cascades to function test_temp() drop cascades to function test_crs_rpt_emptysor(integer) +drop cascades to table tb1 +drop cascades to table tb2 diff --git a/src/test/regress/expected/hw_grant_package.out b/src/test/regress/expected/hw_grant_package.out index 8e9b3f19ca1cf2a5efde0bbd7aa33af1df4d371a..300bb832b1080a0a3771da050ff973222b83a7c6 100644 --- a/src/test/regress/expected/hw_grant_package.out +++ b/src/test/regress/expected/hw_grant_package.out @@ -95,7 +95,7 @@ NOTICE: drop cascades to function test_grant1.a() drop package pck3; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to function test_grant1.p1() -drop cascades to function test_grant1.p2(integer,_s_type[],integer,_s_type[]) +--?.* drop type s_type; reset session AUTHORIZATION; drop user test_grant1; diff --git a/src/test/regress/expected/hw_package.out b/src/test/regress/expected/hw_package.out index 9315c63cca9e27084b824d2ff09c2a45d97f5686..4f8fdf738e47848b9da56b24d4dc7415478f9b02 100644 --- a/src/test/regress/expected/hw_package.out +++ b/src/test/regress/expected/hw_package.out @@ -2745,6 +2745,56 @@ end pck3; / create user package_user password 'gauss@123'; alter package pck3 owner to package_user; +-- test methods schema not consistent with object +create schema multi_schema_001; +-- failed +create or replace package public.multi_shema_package is +var1 int:=1; --公有变量 +var2 int:=2; +procedure multi_schema_001.testpro1(var3 int); --公有存储过程,可以被外部调用 +end multi_shema_package; +/ +ERROR: The namespace of functions or procedures within a package needs to be consistent with the package it belongs. +-- failed +create or replace package multi_schema_001.multi_shema_package is +var1 int:=1; --公有变量 +var2 int:=2; +procedure public.testpro1(var3 int); --公有存储过程,可以被外部调用 +end multi_shema_package; +/ +ERROR: The namespace of functions or procedures within a package needs to be consistent with the package it belongs. +-- succeed +create or replace package multi_schema_001.multi_shema_package is +var1 int:=1; --公有变量 +var2 int:=2; +procedure multi_schema_001.testpro1(var3 int); --公有存储过程,可以被外部调用 +end multi_shema_package; +/ +-- failed +create or replace package body multi_schema_001.multi_shema_package is +var3 int:=3; +var4 int:=4; +procedure public.testpro1(var3 int) +is +begin +end; +end multi_shema_package; +/ +ERROR: The namespace of functions or procedures within a package needs to be consistent with the package it belongs. +-- succeed +create or replace package body multi_schema_001.multi_shema_package is +var3 int:=3; +var4 int:=4; +procedure multi_schema_001.testpro1(var3 int) +is +begin +end; +end multi_shema_package; +/ +-- clean +drop package multi_schema_001.multi_shema_package; +NOTICE: drop cascades to function multi_schema_001.testpro1(integer) +drop schema multi_schema_001; drop package pck1; NOTICE: drop cascades to function pkgsch059.f1(integer,test_tb) drop package pck2; diff --git a/src/test/regress/expected/hw_package_function.out b/src/test/regress/expected/hw_package_function.out index de2079b5c74ef50ff5dea05226e83e41f305c588..6c20ddcef635d4aca9d4c268cca26a0c960345c2 100644 --- a/src/test/regress/expected/hw_package_function.out +++ b/src/test/regress/expected/hw_package_function.out @@ -828,8 +828,8 @@ end pkg112; set behavior_compat_options='proc_outparam_override'; drop package if exists pkg112; NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to function public.p1(_int4[],_int4[],integer) -drop cascades to function public.p1(_int4[],integer) +--?.* +--?.* drop cascades to function public.p4() create or replace package pkg112 as @@ -842,8 +842,8 @@ end pkg112; / drop package if exists pkg112; NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to function public.p1(_int4[],_int4[],integer) -drop cascades to function public.p1(_int4[],integer) +--?.* +--?.* drop cascades to function public.p4() set behavior_compat_options=''; --fix package synonym diff --git a/src/test/regress/expected/hw_partition_add_drop_partition.out b/src/test/regress/expected/hw_partition_add_drop_partition.out index 286212120db9b1c5a9d4f053e5b495517aadf629..9c875d40ede4364b79f37f84963bc27aa18e5620 100644 --- a/src/test/regress/expected/hw_partition_add_drop_partition.out +++ b/src/test/regress/expected/hw_partition_add_drop_partition.out @@ -114,8 +114,10 @@ Options: orientation=row, compression=no --check for drop partition (for) --success, drop partition time_2009 ALTER TABLE range_sales DROP PARTITION time_2009; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop partition time_2011 ALTER TABLE range_sales DROP PARTITION FOR ('2011-06-01'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, invalid type ALTER TABLE range_sales DROP PARTITION FOR (1); ERROR: partition key value must be const or const-evaluable expression @@ -128,6 +130,7 @@ ERROR: Un-support feature DETAIL: Can not drop subpartition against NON-SUBPARTITIONED table --success, drop partition time_2012 ALTER TABLE range_sales DROP PARTITION FOR ('2011-06-01'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --check for ok after drop SELECT count(*) FROM range_sales; count @@ -295,8 +298,10 @@ Options: orientation=row, compression=no --check for drop partition (for) --success, drop partition time_2009 ALTER TABLE range2_sales DROP PARTITION time_2009; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop partition time_2011 ALTER TABLE range2_sales DROP PARTITION FOR ('2011-06-01', 600); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, invalid type ALTER TABLE range2_sales DROP PARTITION FOR (1, 100); ERROR: partition key value must be const or const-evaluable expression @@ -309,6 +314,7 @@ ERROR: Un-support feature DETAIL: Can not drop subpartition against NON-SUBPARTITIONED table --success, drop partition time_2012 ALTER TABLE range2_sales DROP PARTITION FOR ('2011-06-01', 100); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --check for ok after drop SELECT count(*) FROM range2_sales; count @@ -460,8 +466,10 @@ Options: orientation=row, compression=no --check for drop partition (for) --success, drop partition time_2009 ALTER TABLE interval_sales DROP PARTITION time_2009; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop partition sys_p1 ALTER TABLE interval_sales DROP PARTITION FOR ('2011-06-01'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, invalid type ALTER TABLE interval_sales DROP PARTITION FOR (1); ERROR: partition key value must be const or const-evaluable expression @@ -634,8 +642,10 @@ Options: orientation=row, compression=no --check for drop partition (for) --success, drop partition channel2 ALTER TABLE list_sales DROP PARTITION channel2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop partition channel3 ALTER TABLE list_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, invalid type ALTER TABLE list_sales DROP PARTITION FOR (10); ERROR: value too long for type character(1) @@ -648,6 +658,7 @@ ERROR: Un-support feature DETAIL: Can not drop subpartition against NON-SUBPARTITIONED table --success, drop partition channel_default ALTER TABLE list_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --check for ok after drop SELECT count(*) FROM list_sales; count diff --git a/src/test/regress/expected/hw_partition_b_db.out b/src/test/regress/expected/hw_partition_b_db.out index 4f4be34e20611ffba5223994f959dfa0e9718f48..cc817a573b5624cce8b1ca0f536a3818d3c80254 100644 --- a/src/test/regress/expected/hw_partition_b_db.out +++ b/src/test/regress/expected/hw_partition_b_db.out @@ -1588,6 +1588,7 @@ DROP TABLE IF EXISTS t_alter_partition_temp; ALTER TABLE t_multi_keys_list_default ADD PARTITION p5 VALUES ((2,1)); ERROR: list boundary of adding partition MUST NOT overlap with existing partition ALTER TABLE t_multi_keys_list_default DROP PARTITION FOR (1,'5'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ALTER TABLE t_multi_keys_list_default DROP PARTITION FOR (2,'1') UPDATE GLOBAL INDEX; SELECT * FROM t_multi_keys_list_default PARTITION FOR (1,'5') ORDER BY a,b; ERROR: Cannot find partition by the value diff --git a/src/test/regress/expected/hw_partition_create_view.out b/src/test/regress/expected/hw_partition_create_view.out index 7c043bc4b8f669cce8b2ca90da59a7427059287b..cdff18015dee6dfedd00a60741419440e531bf74 100644 --- a/src/test/regress/expected/hw_partition_create_view.out +++ b/src/test/regress/expected/hw_partition_create_view.out @@ -39,12 +39,14 @@ SELECT COUNT(*) FROM range_test1_v3; -- do DDL on destination partition ALTER TABLE range_test1 DROP PARTITION p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- the partition is missing, error SELECT COUNT(*) FROM range_test1_v1; --?ERROR: fail to find partition with oid .* for partitioned table .* DETAIL: this partition may have already been dropped by DDL operation HINT: Check if this query contains a view that refrences the target partition. If so, REBUILD this view. ALTER TABLE range_test1 TRUNCATE PARTITION p2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- the partition is reserved, success SELECT COUNT(*) FROM range_test1_v2; count @@ -120,12 +122,14 @@ SELECT COUNT(*) FROM range_range_test1_v4; -- do DDL on destination partition ALTER TABLE range_range_test1 DROP SUBPARTITION p1_1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- the subpartition p1_1 is missing SELECT COUNT(*) FROM range_range_test1_v2; --?ERROR: fail to find subpartition with oid .* for partitioned table .* DETAIL: this subpartition may have already been dropped by DDL operation HINT: Check if this query contains a view that refrences the target subpartition. If so, REBUILD this view. ALTER TABLE range_range_test1 DROP PARTITION p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- the partition p1 is missing SELECT COUNT(*) FROM range_range_test1_v1; --?ERROR: fail to find partition with oid .* for partitioned table .* diff --git a/src/test/regress/expected/hw_partition_hash_truncate.out b/src/test/regress/expected/hw_partition_hash_truncate.out index 17989d9c7aaaf40833494025362973ae44e49e6b..77011ee09e64ab12052bf90f571499cf4cd62b58 100644 --- a/src/test/regress/expected/hw_partition_hash_truncate.out +++ b/src/test/regress/expected/hw_partition_hash_truncate.out @@ -19,6 +19,7 @@ select count(*) from hash_partition_truncate_table; --4 rows alter table hash_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -27,7 +28,9 @@ select count(*) from hash_partition_truncate_table; --2 rows alter table hash_partition_truncate_table truncate partition for (1); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table hash_partition_truncate_table truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -57,6 +60,7 @@ partition by hash (c1) ); insert into hash_partition_truncate_table values(1),(2),(3),(4); alter table hash_partition_truncate_table truncate partition for (1), truncate partition p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ERROR: partition "p6" does not exist select count(*) from hash_partition_truncate_table; count @@ -66,6 +70,8 @@ select count(*) from hash_partition_truncate_table; -- 4 rows alter table hash_partition_truncate_table truncate partition for (1), truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -117,6 +123,7 @@ select count(*) from hash_partition_truncate_table; --4 rows alter table hash_partition_truncate_table truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -125,6 +132,7 @@ select count(*) from hash_partition_truncate_table; --2 rows alter table hash_partition_truncate_table truncate partition for (2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -154,6 +162,7 @@ select count(*) from hash_partition_truncate_table; --5 rows alter table hash_partition_truncate_table truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -162,6 +171,7 @@ select count(*) from hash_partition_truncate_table; --3 rows alter table hash_partition_truncate_table truncate partition for (2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -193,6 +203,7 @@ select count(*) from hash_partition_truncate_table; --5 rows alter table hash_partition_truncate_table truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -227,6 +238,7 @@ select count(*) from hash_partition_truncate_table; --5 rows alter table hash_partition_truncate_table truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -263,6 +275,8 @@ select count(*) from hash_partition_truncate_table; --5 rows alter table hash_partition_truncate_table truncate partition for (4), truncate partition for(3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -605,6 +619,7 @@ select count(*) from hash_partition_truncate_table; --4 rows alter table hash_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -613,7 +628,9 @@ select count(*) from hash_partition_truncate_table; --2 rows alter table hash_partition_truncate_table truncate partition for (1); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table hash_partition_truncate_table truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- @@ -643,6 +660,7 @@ partition by hash (c1) ); insert into hash_partition_truncate_table values(1),(2),(3),(4); alter table hash_partition_truncate_table truncate partition for (1), truncate partition p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ERROR: partition "p6" does not exist select count(*) from hash_partition_truncate_table; count @@ -652,6 +670,8 @@ select count(*) from hash_partition_truncate_table; -- 4 rows alter table hash_partition_truncate_table truncate partition for (1), truncate partition for (3); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from hash_partition_truncate_table; count ------- diff --git a/src/test/regress/expected/hw_partition_interval_compatibility.out b/src/test/regress/expected/hw_partition_interval_compatibility.out index 06e37cdb3e1cfc21097843be6b40c16385af20dc..57af91a43f9579889d32ebd1191a7f5755e7a145 100644 --- a/src/test/regress/expected/hw_partition_interval_compatibility.out +++ b/src/test/regress/expected/hw_partition_interval_compatibility.out @@ -66,6 +66,7 @@ explain (costs off, verbose on) select * from interval_tab1 where logdate >= '20 (7 rows) alter table interval_tab1 drop partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select relname, parttype, partstrategy, boundaries from pg_partition; relname | parttype | partstrategy | boundaries ---------------+----------+--------------+-------------- @@ -80,6 +81,7 @@ select relname, parttype, partstrategy, boundaries from pg_partition; (8 rows) alter table interval_tab1 merge partitions sys_p5, sys_p6 into partition sys_p5_p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select relname, parttype, partstrategy, boundaries from pg_partition; relname | parttype | partstrategy | boundaries ---------------+----------+--------------+-------------- @@ -127,6 +129,7 @@ select * from interval_tab1 partition(sys_p1); (3 rows) alter table interval_tab1 split partition sys_p1 at (to_date('2020-03-02', 'YYYY-MM-DD')) into (partition sys_p1_1, partition sys_p1_2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select relname, parttype, partstrategy, boundaries from pg_partition; relname | parttype | partstrategy | boundaries ---------------+----------+--------------+-------------- diff --git a/src/test/regress/expected/hw_partition_interval_exchange.out b/src/test/regress/expected/hw_partition_interval_exchange.out index ecfa36185d625a353f4a38590b63616af877c3ce..e999ac21d6fe7d0d0688c21ddd113b0dd50ff4b8 100644 --- a/src/test/regress/expected/hw_partition_interval_exchange.out +++ b/src/test/regress/expected/hw_partition_interval_exchange.out @@ -55,6 +55,7 @@ insert into interval_exchange_test values ('2020-02-26'); -- The data they have belongs to the same range. ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1) WITH TABLE interval_exchange_test; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate; logdate -------------------------- @@ -74,6 +75,7 @@ select * from interval_exchange_test order by logdate; -- exchange back ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1) WITH TABLE interval_exchange_test; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate; logdate -------------------------- @@ -99,6 +101,7 @@ ERROR: some rows in table do not qualify for specified partition -- WITHOUT VALIDATION and the exchange will be success, but some date will in the wrong range; ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1) WITH TABLE interval_exchange_test WITHOUT VALIDATION; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate; logdate -------------------------- @@ -135,6 +138,7 @@ insert into interval_exchange_test values ('2020-5-06'); -- exchange table ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (sys_p1) WITH TABLE interval_exchange_test; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_exchange partition (sys_p1)order by logdate; logdate -------------------------- @@ -154,6 +158,7 @@ select * from interval_exchange_test order by logdate; -- exchange back ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (sys_p1) WITH TABLE interval_exchange_test; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_exchange partition (sys_p1)order by logdate; logdate -------------------------- @@ -178,6 +183,7 @@ ERROR: some rows in table do not qualify for specified partition -- WITHOUT VALIDATION and the exchange will be success, but some date will in the wrong range; ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1) WITH TABLE interval_exchange_test WITHOUT VALIDATION; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate; logdate -------------------------- @@ -251,6 +257,7 @@ insert into partition_table_001 values (4,'ddd',4,'2020-05-23',false,'ddd',4.4); insert into partition_table_001 values (5,'eee',5,'2020-06-23',true,'eee',5.5); insert into partition_table_001 values (6,'fff',6,'2020-07-23',false,'fff',6.6); ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from table_001 order by 1; col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7 -------+-------+-------+--------------------------+-------+-------+------- @@ -282,6 +289,7 @@ select relname, parttype, partstrategy, boundaries from pg_partition (7 rows) ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from table_001 order by 1; col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7 -------+-------+-------+-------+-------+-------+------- @@ -300,6 +308,7 @@ select * from partition_table_001 order by 1; insert into table_001 values (7,'eee',7,'2020-08-23',true,'eee',7.7); ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001 with validation verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from table_001 order by 1; col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7 -------+-------+-------+--------------------------+-------+-------+------- diff --git a/src/test/regress/expected/hw_partition_interval_merge.out b/src/test/regress/expected/hw_partition_interval_merge.out index c1941eb44b2ac16baba74c63fb7205cd5d62d308..d2740426cec49dbeeea1453d5e3017575166d1e7 100644 --- a/src/test/regress/expected/hw_partition_interval_merge.out +++ b/src/test/regress/expected/hw_partition_interval_merge.out @@ -31,6 +31,7 @@ prepare pg_partition_sql(char) as PARTITION p1 VALUES LESS THAN (TO_DATE('6-5-2008', 'DD-MM-YYYY')) ); alter table interval_sales split partition p0 at (to_date('2007-02-10', 'YYYY-MM-DD')) into (partition p0_1, partition p0_2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index execute pg_partition_sql('interval_sales'); relname | parttype | rangenum | intervalnum | partstrategy | interval | boundary ----------------+----------+----------+-------------+--------------+-------------+------------ @@ -124,6 +125,7 @@ ERROR: source partitions must be continuous and in ascending order of boundary (16 rows) alter table interval_sales merge partitions p0_1, p0_2, p1 into partition p01; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index execute pg_partition_sql('interval_sales'); relname | parttype | rangenum | intervalnum | partstrategy | interval | boundary ----------------+----------+----------+-------------+--------------+-------------+------------ @@ -223,6 +225,7 @@ ERROR: source partitions must be continuous and in ascending order of boundary (14 rows) alter table interval_sales merge partitions sys_p6, sys_p7, sys_p8 into partition sys_p6_p7_p8; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition (sys_p6); ERROR: partition "sys_p6" of relation "interval_sales" does not exist @@ -261,6 +264,7 @@ ERROR: partition "sys_p8" of relation "interval_sales" does not exist -- 2.3 merge interval partition and range partition -- FIRST, build a range partition which is continuous with a interval partition alter table interval_sales merge partitions sys_p2, sys_p1 into partition sys_p2_p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- 2.3.1 merge sys_p2_p1 with sys_p3 in wrong order alter table interval_sales merge partitions sys_p3, sys_p2_p1 into partition sys_p2_p1_p3; ERROR: source partitions must be continuous and in ascending order of boundary @@ -282,6 +286,7 @@ ERROR: source partitions must be continuous and in ascending order of boundary (1 row) alter table interval_sales merge partitions sys_p2_p1, sys_p3 into partition sys_p2_p1_p3; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition (sys_p2_p1_p3); prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold @@ -312,6 +317,7 @@ ERROR: source partitions must be continuous and in ascending order of boundary ERROR: source partitions must be continuous and in ascending order of boundary -- 2.4.1 merge interval partition and range partition into one in right order alter table interval_sales merge partitions sys_p2_p1_p3, sys_p9 into partition sys_p9_p2_p1_p3; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition (sys_p9_p2_p1_p3); prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold diff --git a/src/test/regress/expected/hw_partition_interval_split.out b/src/test/regress/expected/hw_partition_interval_split.out index 8bf593f9743af488bbc6ba4288ea8cd7a5865c4a..32153920937916085c88ad7ad8f400021e57f432 100644 --- a/src/test/regress/expected/hw_partition_interval_split.out +++ b/src/test/regress/expected/hw_partition_interval_split.out @@ -14,6 +14,7 @@ INTERVAL('1 MONTH') PARTITION p1 VALUES LESS THAN (TO_DATE('6-5-2008', 'DD-MM-YYYY')) ); alter table interval_sales split partition p0 at (to_date('2007-02-10', 'YYYY-MM-DD')) into (partition p0_1, partition p0_2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales order by time_id; prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold ---------+---------+---------+------------+----------+---------------+------------- @@ -67,6 +68,7 @@ select * from interval_sales partition(sys_p1) order by time_id; (2 rows) alter table interval_sales split partition sys_p1 at (to_date('2009-02-10', 'YYYY-MM-DD')) into (partition sys_p1_1, partition sys_p1_2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition(sys_p1_1) order by time_id; prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold ---------+---------+--------------------------+------------+----------+---------------+------------- @@ -106,6 +108,7 @@ select * from interval_sales partition(sys_p2) order by time_id; (1 row) alter table interval_sales split partition sys_p2 at (to_date('2009-01-10', 'YYYY-MM-DD')) into (partition sys_p2_1, partition sys_p2_2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition(sys_p2_1) order by time_id; prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold ---------+---------+---------+------------+----------+---------------+------------- @@ -145,6 +148,7 @@ select * from interval_sales partition(sys_p3) order by time_id; (1 row) alter table interval_sales split partition sys_p3 at (to_date('2009-04-5', 'YYYY-MM-DD')) into (partition sys_p3_1, partition sys_p3_2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition(sys_p3_1) order by time_id; prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold ---------+---------+---------+------------+----------+---------------+------------- @@ -262,6 +266,7 @@ select * from interval_sales partition(sys_p4) order by time_id; (2 rows) alter table interval_sales split partition sys_p4 at (to_date('2009-07-10', 'YYYY-MM-DD')) into (partition sys_p4_1, partition sys_p4_2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition(sys_p4_1) order by time_id; prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold ---------+---------+---------+------------+----------+---------------+------------- @@ -316,6 +321,7 @@ alter table interval_sales split partition p1 into partition p1_2 values less than (to_date('2008-03-06', 'YYYY-MM-DD')), partition p1_3 values less than (to_date('2008-04-06', 'YYYY-MM-DD')), partition p1_4 values less than (to_date('2008-05-06', 'YYYY-MM-DD'))); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition(p1_1)order by time_id; prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold ---------+---------+---------+------------+----------+---------------+------------- @@ -356,6 +362,7 @@ alter table interval_sales split partition sys_p6 into partition sys_p6_2 values less than (to_date('2018-10-29', 'YYYY-MM-DD')), partition sys_p6_3 values less than (to_date('2018-11-01', 'YYYY-MM-DD')), partition sys_p6_4 values less than (to_date('2018-11-06', 'YYYY-MM-DD'))); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_sales partition(sys_p6_1)order by time_id; prod_id | cust_id | time_id | channel_id | promo_id | quantity_sold | amount_sold ---------+---------+---------+------------+----------+---------------+------------- diff --git a/src/test/regress/expected/hw_partition_interval_unusable_index.out b/src/test/regress/expected/hw_partition_interval_unusable_index.out index c2ab1ad030ad8fbcd0ceaabf3e97370d9bbe2b7f..8bef04a7e6454dfb05312ce9e83515510cc9a848 100644 --- a/src/test/regress/expected/hw_partition_interval_unusable_index.out +++ b/src/test/regress/expected/hw_partition_interval_unusable_index.out @@ -366,6 +366,7 @@ ERROR: index mismatch for tables in ALTER TABLE EXCHANGE PARTITION ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1; ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0) WITH TABLE table_unusable_index_exchange; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- clean table_unusable_index_exchange DROP TABLE table_unusable_index_exchange; DROP TABLE partition_unsable_index_1; diff --git a/src/test/regress/expected/hw_partition_list_dql.out b/src/test/regress/expected/hw_partition_list_dql.out index 09f241eefbaa8da6dc93baf2d62eaee7a8865515..c1353b7c2be45ba11f9a249e9a62d3ba003afa4f 100644 --- a/src/test/regress/expected/hw_partition_list_dql.out +++ b/src/test/regress/expected/hw_partition_list_dql.out @@ -59,6 +59,7 @@ alter table test_partition_for_null_list drop partition for (null); ERROR: The partition number is invalid or out-of-range -- success alter table test_partition_for_null_list drop partition for (0); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- failed select * from test_partition_for_null_list partition (test_partition_for_null_list_part1) order by 1, 2, 3, 4; ERROR: partition "test_partition_for_null_list_part1" of relation "test_partition_for_null_list" does not exist diff --git a/src/test/regress/expected/hw_partition_list_truncate.out b/src/test/regress/expected/hw_partition_list_truncate.out index 139ab5166f1dfad375e7512bae5559208476f6f5..ea90489014a03da14817a429d729144b22094a8f 100644 --- a/src/test/regress/expected/hw_partition_list_truncate.out +++ b/src/test/regress/expected/hw_partition_list_truncate.out @@ -22,6 +22,7 @@ select count(*) from list_partition_truncate_table; --5 rows alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -30,6 +31,7 @@ select count(*) from list_partition_truncate_table; --4 rows alter table list_partition_truncate_table truncate partition for (2000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -65,6 +67,7 @@ alter table list_partition_truncate_table truncate partition for (6000); ERROR: The partition number is invalid or out-of-range --error alter table list_partition_truncate_table truncate partition for (5000), truncate partition for (6000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ERROR: The partition number is invalid or out-of-range select count(*) from list_partition_truncate_table; count @@ -74,6 +77,7 @@ select count(*) from list_partition_truncate_table; -- 5 rows alter table list_partition_truncate_table truncate partition for (5000), truncate partition p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ERROR: partition "p6" does not exist select count(*) from list_partition_truncate_table; count @@ -83,6 +87,8 @@ select count(*) from list_partition_truncate_table; -- 5 rows alter table list_partition_truncate_table truncate partition for (5000), truncate partition p2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -140,6 +146,7 @@ select count(*) from list_partition_truncate_table; --5 rows alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -148,6 +155,7 @@ select count(*) from list_partition_truncate_table; --4 rows alter table list_partition_truncate_table truncate partition for (2000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -180,6 +188,7 @@ select count(*) from list_partition_truncate_table; --5 rows alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -188,6 +197,7 @@ select count(*) from list_partition_truncate_table; --4 rows alter table list_partition_truncate_table truncate partition for (2000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -222,6 +232,7 @@ select count(*) from list_partition_truncate_table; --5 rows alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -259,6 +270,7 @@ select count(*) from list_partition_truncate_table; --5 rows alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -300,6 +312,7 @@ select count(*) from list_partition_truncate_table; --5 rows start transaction ; alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -308,6 +321,7 @@ select count(*) from list_partition_truncate_table; --4 rows alter table list_partition_truncate_table drop partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index rollback; select count(*) from list_partition_truncate_table; count @@ -318,6 +332,7 @@ select count(*) from list_partition_truncate_table; --5 rows start transaction ; alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -368,6 +383,7 @@ select count(*) from list_partition_truncate_table; --6 rows alter table list_partition_truncate_table truncate partition p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -417,6 +433,7 @@ select count(*) from list_partition_truncate_table; --6 rows alter table list_partition_truncate_table truncate partition p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -456,6 +473,8 @@ select count(*) from list_partition_truncate_table; --5 rows alter table list_partition_truncate_table truncate partition p1, truncate partition for(1000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -468,6 +487,8 @@ start transaction; alter table list_partition_truncate_table add partition p6 values (6000); insert into list_partition_truncate_table values(6000,'0'); alter table list_partition_truncate_table truncate partition p6, truncate partition for(6000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table partition(p6); count ------- @@ -483,6 +504,8 @@ start transaction; alter table list_partition_truncate_table add partition p6 values (6000); insert into list_partition_truncate_table values(6000,'0'); alter table list_partition_truncate_table truncate partition p6, truncate partition for(6000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table partition(p6); count ------- @@ -834,6 +857,7 @@ select count(*) from list_partition_truncate_table; --5 rows alter table list_partition_truncate_table truncate partition p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -842,6 +866,7 @@ select count(*) from list_partition_truncate_table; --4 rows alter table list_partition_truncate_table truncate partition for (2000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- @@ -877,6 +902,7 @@ alter table list_partition_truncate_table truncate partition for (6000); ERROR: The partition number is invalid or out-of-range --error alter table list_partition_truncate_table truncate partition for (5000), truncate partition for (6000); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ERROR: The partition number is invalid or out-of-range select count(*) from list_partition_truncate_table; count @@ -886,6 +912,7 @@ select count(*) from list_partition_truncate_table; -- 5 rows alter table list_partition_truncate_table truncate partition for (5000), truncate partition p6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ERROR: partition "p6" does not exist select count(*) from list_partition_truncate_table; count @@ -895,6 +922,8 @@ select count(*) from list_partition_truncate_table; -- 5 rows alter table list_partition_truncate_table truncate partition for (5000), truncate partition p2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from list_partition_truncate_table; count ------- diff --git a/src/test/regress/expected/hw_partition_llt.out b/src/test/regress/expected/hw_partition_llt.out index 4c1abeb22bf9eebd3951546add6b71c12fdb282e..86db9cf33487e79584d164c57aded4c1d196ebfc 100644 --- a/src/test/regress/expected/hw_partition_llt.out +++ b/src/test/regress/expected/hw_partition_llt.out @@ -21,6 +21,7 @@ partition by range (a) create table test_ord (a int); insert into test_ord values (11); alter table test_exchange_llt exchange partition (test_exchange_llt_p2) with table test_ord with validation; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_llt; drop table test_ord; -- get_rel_oids diff --git a/src/test/regress/expected/hw_partitionno.out b/src/test/regress/expected/hw_partitionno.out index 3570d0a5f49adb7ab70bb9d9db360626d170f4c8..6f9acbfb329b15f40a266203838017907c897b26 100644 --- a/src/test/regress/expected/hw_partitionno.out +++ b/src/test/regress/expected/hw_partitionno.out @@ -67,6 +67,7 @@ EXECUTE partition_get_partitionno('range_sales'); -- add/drop partition ALTER TABLE range_sales ADD PARTITION time_default VALUES LESS THAN (MAXVALUE); ALTER TABLE range_sales DROP PARTITION time_2008; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXECUTE partition_get_partitionno('range_sales'); relname | partitionno | subpartitionno | boundaries --------------+-------------+----------------+-------------- @@ -79,6 +80,7 @@ EXECUTE partition_get_partitionno('range_sales'); -- merge/split partition ALTER TABLE range_sales SPLIT PARTITION time_default AT ('2013-01-01') INTO (PARTITION time_2012, PARTITION time_default_temp); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ALTER TABLE range_sales RENAME PARTITION time_default_temp TO time_default; ALTER TABLE range_sales MERGE PARTITIONS time_2009, time_2010 INTO PARTITION time_2010_old UPDATE GLOBAL INDEX; EXECUTE partition_get_partitionno('range_sales'); @@ -163,6 +165,7 @@ EXECUTE partition_get_partitionno('interval_sales'); INSERT INTO interval_sales VALUES (1,1,'2013-01-01','A',1,1,1); INSERT INTO interval_sales VALUES (2,2,'2012-01-01','B',2,2,2); ALTER TABLE interval_sales DROP PARTITION time_2008; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXECUTE partition_get_partitionno('interval_sales'); relname | partitionno | subpartitionno | boundaries ----------------+-------------+----------------+------------------------------ @@ -175,6 +178,7 @@ EXECUTE partition_get_partitionno('interval_sales'); -- merge/split partition ALTER TABLE interval_sales SPLIT PARTITION time_2009 AT ('2009-01-01') INTO (PARTITION time_2008, PARTITION time_2009_temp); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ALTER TABLE interval_sales RENAME PARTITION time_2009_temp TO time_2009; ALTER TABLE interval_sales MERGE PARTITIONS time_2009, time_2010 INTO PARTITION time_2010_old UPDATE GLOBAL INDEX; EXECUTE partition_get_partitionno('interval_sales'); @@ -260,6 +264,7 @@ EXECUTE partition_get_partitionno('list_sales'); -- add/drop partition ALTER TABLE list_sales ADD PARTITION channel_default VALUES (DEFAULT); ALTER TABLE list_sales DROP PARTITION channel4; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXECUTE partition_get_partitionno('list_sales'); relname | partitionno | subpartitionno | boundaries -----------------+-------------+----------------+------------ @@ -362,6 +367,7 @@ EXECUTE subpartition_get_partitionno('list_range_sales'); -- add/drop partition ALTER TABLE list_range_sales DROP PARTITION channel3; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ALTER TABLE list_range_sales ADD PARTITION channel3 VALUES ('6', '7') ( SUBPARTITION channel3_customer1 VALUES LESS THAN (200), @@ -395,6 +401,7 @@ EXECUTE subpartition_get_partitionno('list_range_sales'); -- merge/split partition ALTER TABLE list_range_sales SPLIT SUBPARTITION channel2_customer2 AT (800) INTO (SUBPARTITION channel2_customer3, SUBPARTITION channel2_customer4); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXECUTE subpartition_get_partitionno('list_range_sales'); relname | partitionno | subpartitionno | boundaries --------------------------+-------------+----------------+------------ diff --git a/src/test/regress/expected/hw_subpartition_add_drop_partition.out b/src/test/regress/expected/hw_subpartition_add_drop_partition.out index 55430300e5374016b3eae43839ec8da9cd93d943..40a78ce6189c72e37c45de0cab41a8ce7ed9a3a3 100644 --- a/src/test/regress/expected/hw_subpartition_add_drop_partition.out +++ b/src/test/regress/expected/hw_subpartition_add_drop_partition.out @@ -187,14 +187,17 @@ Options: orientation=row, compression=no --check for drop partition/subpartition (for) --success, drop partition customer2 ALTER TABLE range_range_sales DROP PARTITION customer2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE range_range_sales DROP SUBPARTITION customer1_2008; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE range_range_sales DROP SUBPARTITION customer4_all; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition customer3 ALTER TABLE range_range_sales DROP PARTITION FOR (400); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE range_range_sales DROP PARTITION FOR (400, '2010-01-01'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -210,6 +213,7 @@ ALTER TABLE range_range_sales DROP SUBPARTITION FOR ('2010-01-01', 1400); ERROR: invalid input syntax for integer: "2010-01-01" --success, drop subpartition customer5_2010 ALTER TABLE range_range_sales DROP SUBPARTITION FOR(1400, '2010-01-01'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in customer6 ALTER TABLE range_range_sales DROP SUBPARTITION FOR(2000, '2009-01-01'); ERROR: Cannot drop the only subpartition of a partitioned table @@ -475,14 +479,17 @@ Options: orientation=row, compression=no --check for drop partition/subpartition (for) --success, drop partition customer2 ALTER TABLE range_list_sales DROP PARTITION customer2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE range_list_sales DROP SUBPARTITION customer1_channel1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE range_list_sales DROP SUBPARTITION customer4_channel1; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition customer3 ALTER TABLE range_list_sales DROP PARTITION FOR (400); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE range_list_sales DROP PARTITION FOR (400, '4'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -498,6 +505,7 @@ ALTER TABLE range_list_sales DROP SUBPARTITION FOR ('abc', 1400); ERROR: invalid input syntax for integer: "abc" --success, drop subpartition customer5_channel3 ALTER TABLE range_list_sales DROP SUBPARTITION FOR(1400, '7'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in customer6 ALTER TABLE range_list_sales DROP SUBPARTITION FOR(2000, 'X'); ERROR: Cannot drop the only subpartition of a partitioned table @@ -742,6 +750,7 @@ Options: orientation=row, compression=no --check for drop partition/subpartition (for) --success, drop partition customer2 ALTER TABLE range_hash_sales DROP PARTITION customer2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, not support drop hash ALTER TABLE range_hash_sales DROP SUBPARTITION customer1_product1; ERROR: Un-support feature @@ -752,6 +761,7 @@ ERROR: Un-support feature DETAIL: The syntax is unsupported for hash subpartition --success, drop partition customer3 ALTER TABLE range_hash_sales DROP PARTITION FOR (400); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE range_hash_sales DROP PARTITION FOR (400, '2010-01-01'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -1014,14 +1024,17 @@ Options: orientation=row, compression=no --check for drop partition/subpartition (for) --success, drop partition channel2 ALTER TABLE list_range_sales DROP PARTITION channel2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE list_range_sales DROP SUBPARTITION channel1_customer1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE list_range_sales DROP SUBPARTITION channel4_customer1; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition channel3 ALTER TABLE list_range_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE list_range_sales DROP PARTITION FOR('X', 700); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -1037,6 +1050,7 @@ ALTER TABLE list_range_sales DROP SUBPARTITION FOR(700, 'X'); ERROR: value too long for type character(1) --success, drop subpartition channel5_customer3 ALTER TABLE list_range_sales DROP SUBPARTITION FOR('X', 700); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in channel6 ALTER TABLE list_range_sales DROP SUBPARTITION FOR('K', 100); ERROR: Cannot drop the only subpartition of a partitioned table @@ -1305,14 +1319,17 @@ Options: orientation=row, compression=no --check for drop partition/subpartition (for) --success, drop partition channel2 ALTER TABLE list_list_sales DROP PARTITION channel2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE list_list_sales DROP SUBPARTITION channel1_type1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE list_list_sales DROP SUBPARTITION channel4_type1; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition channel3 ALTER TABLE list_list_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE list_list_sales DROP PARTITION FOR('X', 6); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -1328,6 +1345,7 @@ ALTER TABLE list_list_sales DROP SUBPARTITION FOR(10, 'X'); ERROR: value too long for type character(1) --success, drop subpartition channel5_type3 ALTER TABLE list_list_sales DROP SUBPARTITION FOR('X', 6); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in channel6 ALTER TABLE list_list_sales DROP SUBPARTITION FOR('K', 10); ERROR: Cannot drop the only subpartition of a partitioned table diff --git a/src/test/regress/expected/hw_subpartition_add_drop_partition_1.out b/src/test/regress/expected/hw_subpartition_add_drop_partition_1.out index 0fc715f4b6314388ce62b1272eb7ea342c5795ba..8cd2afe5fc6483f8ec51c7130b1311703450f763 100644 --- a/src/test/regress/expected/hw_subpartition_add_drop_partition_1.out +++ b/src/test/regress/expected/hw_subpartition_add_drop_partition_1.out @@ -162,6 +162,7 @@ Options: orientation=row, compression=no --check for drop partition/subpartition (for) --success, drop partition channel2 ALTER TABLE list_hash_sales DROP PARTITION channel2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, not support drop hash ALTER TABLE list_hash_sales DROP SUBPARTITION channel1_product1; ERROR: Un-support feature @@ -172,6 +173,7 @@ ERROR: Un-support feature DETAIL: The syntax is unsupported for hash subpartition --success, drop partition channel3 ALTER TABLE list_hash_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE list_hash_sales DROP PARTITION FOR ('6', '2010-01-01'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -414,8 +416,10 @@ ALTER TABLE hash_range_sales DROP PARTITION product2; ERROR: Droping hash partition is unsupported. --success, drop subpartition product1_customer1 ALTER TABLE hash_range_sales DROP SUBPARTITION product1_customer1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop subpartition product4_customer1 ALTER TABLE hash_range_sales DROP SUBPARTITION product4_customer1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in product4 ALTER TABLE hash_range_sales DROP SUBPARTITION product4_customer2; ERROR: Cannot drop the only subpartition of a partitioned table @@ -435,6 +439,7 @@ ALTER TABLE hash_range_sales DROP SUBPARTITION FOR('2010-01-01', 100); ERROR: invalid input syntax for integer: "2010-01-01" --success, drop subpartition product1_customer2, but not suggest to do this operation ALTER TABLE hash_range_sales DROP SUBPARTITION FOR(0, 100); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, no subpartition find ALTER TABLE hash_range_sales DROP SUBPARTITION FOR(0, 2300); ERROR: The subpartition number is invalid or out-of-range @@ -668,8 +673,10 @@ ALTER TABLE hash_list_sales DROP PARTITION product2; ERROR: Droping hash partition is unsupported. --success, drop subpartition product1_channel1 ALTER TABLE hash_list_sales DROP SUBPARTITION product1_channel1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop subpartition product4_channel1 ALTER TABLE hash_list_sales DROP SUBPARTITION product4_channel1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in product4 ALTER TABLE hash_list_sales DROP SUBPARTITION product4_channel2; ERROR: Cannot drop the only subpartition of a partitioned table @@ -689,6 +696,7 @@ ALTER TABLE hash_list_sales DROP SUBPARTITION FOR('2010-01-01', '4'); ERROR: invalid input syntax for integer: "2010-01-01" --success, drop subpartition product1_channel2, but not suggest to do this operation ALTER TABLE hash_list_sales DROP SUBPARTITION FOR(0, '4'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, no subpartition find ALTER TABLE hash_list_sales DROP SUBPARTITION FOR(0, 'Z'); ERROR: The subpartition number is invalid or out-of-range diff --git a/src/test/regress/expected/hw_subpartition_alter_table.out b/src/test/regress/expected/hw_subpartition_alter_table.out index 5ec6a1613a83c640f15b107fe588ef38b958fb81..9123f1a26fbbde8f844714cd2bf5c7b004773a3f 100644 --- a/src/test/regress/expected/hw_subpartition_alter_table.out +++ b/src/test/regress/expected/hw_subpartition_alter_table.out @@ -93,6 +93,7 @@ LINE 1: ALTER TABLE range_range EXCHANGE SUBPARTITION (p_201901) WIT... ^ -- drop alter table range_range drop partition p_201901; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table range_range drop partition p_201901_a; ERROR: partition "p_201901_a" does not exist alter table range_range drop subpartition p_201901_a; diff --git a/src/test/regress/expected/hw_subpartition_ddl_index.out b/src/test/regress/expected/hw_subpartition_ddl_index.out index 63fd4add4d7f6a343d0c2515d9b1427cb54349ad..51add009cb826e7b91fc6dc41f065bc21c4abc67 100644 --- a/src/test/regress/expected/hw_subpartition_ddl_index.out +++ b/src/test/regress/expected/hw_subpartition_ddl_index.out @@ -262,6 +262,7 @@ SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx4) */ COUNT(time --4. if drop partition without update global index, the gpi will be invalid, we can rebuild the index ALTER TABLE range_list_sales1 DROP PARTITION FOR (1600); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXPLAIN(costs off) SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx1) */ COUNT(product_id) FROM range_list_sales1; WARNING: Error hint: IndexOnlyScan(range_list_sales1 range_list_sales1_idx1), index "range_list_sales1_idx1" doesn't exist. QUERY PLAN @@ -350,6 +351,7 @@ SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx4) */ COUNT(time --5. if drop subpartition without update global index, the gpi will be invalid, we can rebuild the index ALTER TABLE range_list_sales1 DROP SUBPARTITION customer5_channel3; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXPLAIN(costs off) SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx1) */ COUNT(product_id) FROM range_list_sales1; WARNING: Error hint: IndexOnlyScan(range_list_sales1 range_list_sales1_idx1), index "range_list_sales1_idx1" doesn't exist. QUERY PLAN diff --git a/src/test/regress/expected/hw_subpartition_gpi.out b/src/test/regress/expected/hw_subpartition_gpi.out index 8fa5fe750b21742f9972cc3888496d506346ee15..d6b5b9b2f5c2becbd88830b60c4444258d3fca1f 100644 --- a/src/test/regress/expected/hw_subpartition_gpi.out +++ b/src/test/regress/expected/hw_subpartition_gpi.out @@ -454,6 +454,7 @@ select * from range_list where user_no = '1' order by 1, 2, 3, 4; (3 rows) alter table range_list truncate subpartition p_201901_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(costs off, verbose on) select * from range_list where month_code = '201902' order by 1, 2, 3, 4; QUERY PLAN ---------------------------------------------------------------------------------- @@ -721,6 +722,7 @@ alter table range_list split subpartition p_201902_b values ('3') into subpartition p_201902_b, subpartition p_201902_c ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(costs off, verbose on) select * from range_list where month_code = '201902' order by 1, 2, 3, 4; QUERY PLAN ---------------------------------------------------------------------------------- @@ -995,6 +997,7 @@ alter table range_range split subpartition p_201902_b at ('3') into subpartition p_201902_c, subpartition p_201903_d ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(costs off, verbose on) select * from range_range where month_code = '201902' order by 1, 2, 3, 4; QUERY PLAN ----------------------------------------------------------------------------------- diff --git a/src/test/regress/expected/hw_subpartition_split.out b/src/test/regress/expected/hw_subpartition_split.out index b52ab4cffca3051de9a000fc89cd6aeda52beb34..6edc7c4f237de2e603874ff8dd98655d45393ac1 100644 --- a/src/test/regress/expected/hw_subpartition_split.out +++ b/src/test/regress/expected/hw_subpartition_split.out @@ -74,6 +74,7 @@ alter table list_list split subpartition p_201901_b values (2) into subpartition p_201901_b, subpartition p_201901_c ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -118,6 +119,7 @@ alter table list_list split subpartition p_201902_b values (2, 3) into subpartition p_201902_b, subpartition p_201902_c ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -220,6 +222,7 @@ alter table range_range split subpartition p_201901_b at (3) into subpartition p_201901_c, subpartition p_201901_d ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from range_range subpartition (p_201901_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -258,6 +261,7 @@ alter table range_range split subpartition p_201902_b at (3) into subpartition p_201902_c, subpartition p_201902_d ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from range_range subpartition (p_201902_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- diff --git a/src/test/regress/expected/hw_subpartition_truncate.out b/src/test/regress/expected/hw_subpartition_truncate.out index f66a3f54995b4c9e0ed2a8dfa1d5090e0feefa11..5148d8744dd65cb854e64049fe5a51b58425aa62 100644 --- a/src/test/regress/expected/hw_subpartition_truncate.out +++ b/src/test/regress/expected/hw_subpartition_truncate.out @@ -50,6 +50,7 @@ select * from list_list partition (p_201901); (3 rows) alter table list_list truncate partition p_201901; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list partition (p_201901); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -64,6 +65,7 @@ select * from list_list partition (p_201902); (3 rows) alter table list_list truncate partition p_201902; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list partition (p_201902); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -88,6 +90,7 @@ select * from list_list subpartition (p_201901_a); (2 rows) alter table list_list truncate subpartition p_201901_a; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_a); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -100,6 +103,7 @@ select * from list_list subpartition (p_201901_b); (1 row) alter table list_list truncate subpartition p_201901_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_b); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -112,6 +116,7 @@ select * from list_list subpartition (p_201902_a); (1 row) alter table list_list truncate subpartition p_201902_a; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_a); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -125,6 +130,7 @@ select * from list_list subpartition (p_201902_b); (2 rows) alter table list_list truncate subpartition p_201902_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_b); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- diff --git a/src/test/regress/expected/hw_to_timestamp.out b/src/test/regress/expected/hw_to_timestamp.out index 19f79cb0e4d2630a6e6a6d58290272123a5c94d5..96e34eb84c0b349424592daa38836803153137c8 100644 --- a/src/test/regress/expected/hw_to_timestamp.out +++ b/src/test/regress/expected/hw_to_timestamp.out @@ -1086,3 +1086,9 @@ SELECT to_date('19920101123456.4999999999999'); 1992-01-01 12:34:56 (1 row) +SELECT to_date('202201 ', 'yyyymm'); + to_date +--------------------- + 2022-01-01 00:00:00 +(1 row) + diff --git a/src/test/regress/expected/ignore/ignore_unique_constraints.out b/src/test/regress/expected/ignore/ignore_unique_constraints.out index 6235354c8566fbf3edd4f84466eb1c84d716e992..27a3c7a129a00f33b18639f4dbfc6b8cb5f6be85 100644 --- a/src/test/regress/expected/ignore/ignore_unique_constraints.out +++ b/src/test/regress/expected/ignore/ignore_unique_constraints.out @@ -442,5 +442,44 @@ update /*+ ignore_error */ t_column_orien set c1 = null where c1 = 2; ERROR: IGNORE is not supported on UPDATE column orientated table. update /*+ ignore_error */ t_column_orien set c1 = 1 where c1 = 2; ERROR: IGNORE is not supported on UPDATE column orientated table. +--test under opfusion+prepare +set enable_opfusion = on; +set enable_bitmapscan to off; +set enable_seqscan to off; +create table t_ignore_0037(c1 int primary key, c2 number(5,2)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_ignore_0037_pkey" for table "t_ignore_0037" +create index i_test on t_ignore_0037(c2); +analyze t_ignore_0037; +prepare insert_ignore(int,number(5,2)) as insert /*+ ignore_error */ into t_ignore_0037 values(1,2); +explain(costs off) execute insert_ignore(0, 123.12); + QUERY PLAN +------------------------- + [Bypass] + Insert on t_ignore_0037 + -> Result +(3 rows) + +execute insert_ignore(0, 123.12); +execute insert_ignore(0, 123.12); +WARNING: duplicate key value violates unique constraint in table "t_ignore_0037" +insert into t_ignore_0037 values(3,1); +insert into t_ignore_0037 values(4,1); +prepare update_ignore(int) as update /*+ ignore_error */ t_ignore_0037 set c1=$1 where c2=1; +explain(costs off) execute update_ignore(0); + QUERY PLAN +------------------------------------------------ + [Bypass] + Update on t_ignore_0037 + -> Index Scan using i_test on t_ignore_0037 + Index Cond: (c2 = 1::numeric) +(4 rows) + +execute update_ignore(0); +WARNING: duplicate key value violates unique constraint in table "t_ignore_0037" +execute update_ignore(0); +WARNING: duplicate key value violates unique constraint in table "t_ignore_0037" +reset enable_bitmapscan; +reset enable_seqscan; +DEALLOCATE all; \c postgres drop database if exists sql_ignore_unique_test; diff --git a/src/test/regress/expected/invisible_index.out b/src/test/regress/expected/invisible_index.out index 373bcda4034c5e07b9f368521640d58835f56bb4..781cb21766f12bd49da0a6f47f515090c0018d1d 100644 --- a/src/test/regress/expected/invisible_index.out +++ b/src/test/regress/expected/invisible_index.out @@ -1,17 +1,53 @@ /* unsupported */ create schema invisible_index; set search_path to 'invisible_index'; -create table t1 (a int, b int, constraint key_a primary key(a) visible); --error -ERROR: visible is supported only in B compatible database. -create table t1 (a int, b int, constraint key_a primary key(a)); -NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "key_a" for table "t1" -alter table t1 alter index key_a invisible; --error -ERROR: invisible is supported only in B compatible database. -alter table t1 add constraint key_b unique (b) visible; --error -ERROR: visible is supported only in B compatible database. +create table t1 (a int, b int, constraint key1 primary key(a) visible); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "key1" for table "t1" +alter table t1 alter index key1 invisible; +alter table t1 add constraint key2 unique (b) visible; +NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "key2" for table "t1" +create table t2 (a int, b int, constraint key3 primary key(a) invisible); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "key3" for table "t2" +alter table t2 alter index key3 visible; +alter table t2 add constraint key4 unique (b) invisible; +NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "key4" for table "t2" +create table t3 (a int, b int); +create index key5 on t3(a) visible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | t +(1 row) + +alter index key5 invisible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | f +(1 row) + +create table t4 (a int, b int); +create index key6 on t4(a) invisible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | f +(1 row) + +alter index key6 visible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | t +(1 row) + reset search_path; drop schema invisible_index cascade; -NOTICE: drop cascades to table invisible_index.t1 +NOTICE: drop cascades to 4 other objects +DETAIL: drop cascades to table invisible_index.t1 +drop cascades to table invisible_index.t2 +drop cascades to table invisible_index.t3 +drop cascades to table invisible_index.t4 create database invisible_index_db dbcompatibility 'B'; \c invisible_index_db -- create table with index @@ -26,6 +62,36 @@ select indkey, indisvisible from pg_index where indrelid = 't1'::regclass order 2 | f (2 rows) +create table t3 (a int, b int); +create index key5 on t3(a) visible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | t +(1 row) + +alter index key5 invisible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | f +(1 row) + +create table t4 (a int, b int); +create index key6 on t4(a) invisible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | f +(1 row) + +alter index key6 visible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; + indkey | indisvisible +--------+-------------- + 1 | t +(1 row) + insert into t1 values (generate_series(1, 100), generate_series(1, 100)); analyze t1; set enable_seqscan = off; diff --git a/src/test/regress/expected/multi_update.out b/src/test/regress/expected/multi_update.out index 75ce7d83daae9d86555c43098a831fa7817f0353..cebc35b4c51d1f40299ff57227af605ae92a3be9 100644 --- a/src/test/regress/expected/multi_update.out +++ b/src/test/regress/expected/multi_update.out @@ -1565,5 +1565,33 @@ UPDATE t2 AS A NATURAL JOIN v1 B SET B.f1 = 1; drop table t1; drop view v1; drop table t2; +-- except no core +set query_dop = 6; +drop table if exists t_t_mutil_t1; +drop table if exists t_t_mutil_t2; +drop table if exists t_t_mutil_t3; +create table t_t_mutil_t1(col1 int,col2 int); +create table t_t_mutil_t2(col1 int,col2 int); +create table t_t_mutil_t3(col1 int,col2 int); +insert into t_t_mutil_t1 values(generate_series(1,1000000),generate_series(1,1000000)); +insert into t_t_mutil_t2 values(generate_series(1,1000000),generate_series(1,1000000)); +insert into t_t_mutil_t3 values(generate_series(1,1000000),generate_series(1,1000000)); +explain(costs off, verbose) update/*+nestloop(a b)*/ t_t_mutil_t1 a,t_t_mutil_t2 b set b.col1=5,a.col2=4 where a.col1=b.col1; + QUERY PLAN +--------------------------------------------------- + Update on MULTI-RELATION + -> Nested Loop + Output: a.col1, 4, a.ctid, a.ctid, b.ctid + Join Filter: (a.col1 = b.col1) + -> Seq Scan on public.t_t_mutil_t1 a + Output: a.col1, a.ctid + -> Seq Scan on public.t_t_mutil_t2 b + Output: b.col2, b.ctid, b.col1 +(8 rows) + +drop table if exists t_t_mutil_t1; +drop table if exists t_t_mutil_t2; +drop table if exists t_t_mutil_t3; +reset query_dop; \c regression drop database multiupdate; diff --git a/src/test/regress/expected/mysql_delimiter_ustore.out b/src/test/regress/expected/mysql_delimiter_ustore.out new file mode 100644 index 0000000000000000000000000000000000000000..7183fcb0ffc255a343f5407c2f146ffe531c0a35 --- /dev/null +++ b/src/test/regress/expected/mysql_delimiter_ustore.out @@ -0,0 +1,209 @@ +-- B db compatibility case +drop database if exists my_test; +NOTICE: database "my_test" does not exist, skipping +create database my_test dbcompatibility 'B'; +\c my_test +--Test default delimiter +select 1; + ?column? +---------- + 1 +(1 row) + +--Test delimiter aa +delimiter aa; +select 1aa + ?column? +---------- + 1 +(1 row) + +select 1aaselect 1;aa + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 1 +(1 row) + +select kaa +ERROR: column "k" does not exist +LINE 1: select k aa + ^ +CONTEXT: referenced column: k +delimiter ;aa +--Test delimiter // +delimiter //; +select 1// + ?column? +---------- + 1 +(1 row) + +delimiter ;// +--Test delimiter length +delimiter "" +ERROR: zero-length delimited identifier at or near """" +LINE 1: delimiter "" ";" + ^ +delimiter '' +ERROR: DELIMITER must be followed by a 'delimiter' character or string at or near "";"" +LINE 1: delimiter '' ";" + ^ +delimiter aaaaaaaaaaaaaaaa +ERROR: 'delimiter' length should less than 16 at or near "";"" +LINE 1: delimiter aaaaaaaaaaaaaaaa ";" + ^ +delimiter "aaaaaaaaaaaaaaaa" +ERROR: 'delimiter' length should less than 16 at or near "";"" +LINE 1: delimiter "aaaaaaaaaaaaaaaa" ";" + ^ +delimiter aaaaaaaaaaaaaaa +delimiter ; +--Test delimiter % +delimiter %; +select 1% + ?column? +---------- + 1 +(1 row) + +delimiter ;% +--Test delimiter 'Mysql' +delimiter 'Mysql'; +select 1Mysql + ?column? +---------- + 1 +(1 row) + +delimiter ;Mysql +--Test other +delimiter sds; +delimiter aasds +select 1aasds + ?column? +---------- + 1 +(1 row) + +delimiter ;aasds +-- +delimiter asd ss; +select 1asd + ?column? +---------- + 1 +(1 row) + +delimiter ;asd +delimiter bb +delimiter aa +select 1aa + ?column? +---------- + 1 +(1 row) + +delimiter ; +delimiter de +delimiter abcde +select 1abcde + ?column? +---------- + 1 +(1 row) + +delimiter zz sdsd aasds +delimiter kkasda "sdsd" sdsda +select 1kkasda + ?column? +---------- + 1 +(1 row) + +delimiter +ERROR: syntax error at or near ""kkasda"" +LINE 1: delimiter "kkasda" + ^ +delimiter "sdsd sd" +select 1"sdsd sd" + ?column? +---------- + 1 +(1 row) + +delimiter ; +-- test delimiter use in create procedure situation +-- report gram error in server ,not subprogram end error, success in plugin +create table test_table (dot_no int) with (storage_type = ustore); +insert into test_table values(1); +insert into test_table values(NULL); +delimiter // +create procedure test91() +begin + declare rec_curs_value int; + declare curs_dot cursor for select dot_no from test_table; + open curs_dot; + fetch curs_dot into rec_curs_value; + while rec_curs_value is not null do + fetch curs_dot into rec_curs_value; + end while; + close curs_dot; +end; +// +ERROR: syntax error at or near "begin" +LINE 2: begin + ^ +delimiter ; +delimiter // +create procedure test92() +begin + declare rec_curs_value int; + declare curs_dot cursor for select dot_no from test_table; + open curs_dot; + fetch curs_dot into rec_curs_value; + while rec_curs_value is null do + fetch curs_dot into rec_curs_value; + end while; + close curs_dot; +end; +// +ERROR: syntax error at or near "begin" +LINE 2: begin + ^ +delimiter ; +-- test deterministic error +create function fun2(age1 int)return int DETERMINISTIC +NOT SHIPPABLE NOT FENCED EXTERNAL SECURITY INVOKER +AS +declare +a1 int; +begin +return a1; +end; +/ +select fun2(1); + fun2 +------ + +(1 row) + +-- test create procedure select error +create table t1 (a int) with (storage_type = ustore); +insert into t1 values (1),(2); +-- server should has gram error,plugin pass +create procedure pro_test() select a from t1; +ERROR: syntax error at or near "select" +LINE 1: create procedure pro_test() select a from t1; + ^ +-- server should has gram error, plugin pass; +create procedure pro_test2() select a as b from t1; +ERROR: syntax error at or near "select" +LINE 1: create procedure pro_test2() select a as b from t1; + ^ +\c regression +drop database my_test; diff --git a/src/test/regress/expected/mysql_trigger.out b/src/test/regress/expected/mysql_trigger.out index 4fd4a3cdfd786d9ab1f0656987e3f9c97138a381..552ca133646701d773eff6014948a4871d72cb22 100644 --- a/src/test/regress/expected/mysql_trigger.out +++ b/src/test/regress/expected/mysql_trigger.out @@ -1001,6 +1001,57 @@ end; alter trigger testscm.animals_trigger2 on animals_scm rename to animals_trigger2_1; drop trigger testscm.animals_trigger2_1 on animals_scm; set search_path to public; +--bugfix for name long +drop table if exists T_ignore_case_in_dquotes_use_case0007; +NOTICE: table "t_ignore_case_in_dquotes_use_case0007" does not exist, skipping +drop table if exists T_ignore_case_in_dquotes_use_case0007_1; +NOTICE: table "t_ignore_case_in_dquotes_use_case0007_1" does not exist, skipping +create table T_ignore_case_in_dquotes_use_case0007(col1 int,col2 varchar(20)); +create table T_ignore_case_in_dquotes_use_case0007_1(col1 int,col2 varchar(20)); +create trigger Tri_ignore_case_in_dquotes_use_case0007 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +create trigger Tri_ignore_case_in_dquotes_use_case0008 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +create trigger Tri_ignore_case_in_dquotes_use_case0009 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +create trigger Tri_ignore_case_in_dquotes_use_case0011 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +insert into T_ignore_case_in_dquotes_use_case0007 values(11,'test'); +select * from T_ignore_case_in_dquotes_use_case0007; + col1 | col2 +------+------ + 11 | test +(1 row) + +select * from T_ignore_case_in_dquotes_use_case0007_1; + col1 | col2 +------+-------- + 1 | INSERT + 1 | INSERT + 1 | INSERT + 1 | INSERT +(4 rows) + -- 1.5 cleanup \c regression drop database testdb_m; diff --git a/src/test/regress/expected/orderby_in_subselect.out b/src/test/regress/expected/orderby_in_subselect.out new file mode 100644 index 0000000000000000000000000000000000000000..1122091cbd4a10f1ff65ec69c4fa24e27e2b8a95 --- /dev/null +++ b/src/test/regress/expected/orderby_in_subselect.out @@ -0,0 +1,138 @@ +DROP TABLE if exists zytest1; +NOTICE: table "zytest1" does not exist, skipping +DROP TABLE if exists zytest2; +NOTICE: table "zytest2" does not exist, skipping +DROP TABLE if exists zytest3; +NOTICE: table "zytest3" does not exist, skipping +CREATE TABLE zytest1 +(aid NUMERIC, +name varchar(20) +); +CREATE TABLE zytest2 +(bid NUMERIC, +des varchar(20), +zid NUMERIC --zytest1.aid +); +CREATE TABLE zytest3 +(aid NUMERIC, ----zytest1.aid +numb NUMERIC -- +); +INSERT INTO zytest1 values(1,'NAME1'); +INSERT INTO zytest1 values(2,'NAME2'); +INSERT INTO zytest1 values(3,'NAME3'); +INSERT INTO zytest1 values(4,'NAME4'); +INSERT INTO zytest1 values(5,'NAME5'); +INSERT INTO zytest1 values(6,'NAME6'); +INSERT INTO zytest2 values(1,'des1',1); +INSERT INTO zytest2 values(2,'des2',2); +INSERT INTO zytest2 values(3,'des3',3); +INSERT INTO zytest2 values(4,'des4',4); +INSERT INTO zytest2 values(5,'des5',5); +INSERT INTO zytest2 values(6,'des6',6); +INSERT INTO zytest3 values(1,1); +INSERT INTO zytest3 values(2,2); +INSERT INTO zytest3 values(3,3); +INSERT INTO zytest3 values(1,4); +INSERT INTO zytest3 values(2,5); +INSERT INTO zytest3 values(3,6); +SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +ORDER BY bid +) +WHERE nsum IS NOT NULL OR nsum>5; + bid | nsum +-----+------ + 1 | 5 + 2 | 7 + 3 | 9 + 4 | 0 + 5 | 0 + 6 | 0 +(6 rows) + +explain (analyze, costs off, timing off) SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +ORDER BY bid +) +WHERE nsum IS NOT NULL OR nsum>5; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Sort (actual rows=6 loops=1) + Sort Key: zytest2.bid + Sort Method: quicksort Memory: 25kB + -> Hash Left Join (actual rows=6 loops=1) + Hash Cond: (zytest2.zid = subquery."?column?") + Filter: ((COALESCE(subquery.sum, 0::numeric) IS NOT NULL) OR (COALESCE(subquery.sum, 0::numeric) > 5::numeric)) + -> Hash Left Join (actual rows=6 loops=1) + Hash Cond: (zytest2.zid = subquery."?column?") + -> Seq Scan on zytest2 (actual rows=6 loops=1) + -> Hash (actual rows=3 loops=1) + Buckets: 32768 Batches: 1 Memory Usage: 257kB + -> Subquery Scan on subquery (actual rows=3 loops=1) + -> HashAggregate (actual rows=3 loops=1) + Group By Key: public.zytest3.aid + -> Seq Scan on zytest3 (actual rows=6 loops=1) + -> Hash (actual rows=3 loops=1) + Buckets: 32768 Batches: 1 Memory Usage: 257kB + -> Subquery Scan on subquery (actual rows=3 loops=1) + -> HashAggregate (actual rows=3 loops=1) + Group By Key: public.zytest3.aid + -> Seq Scan on zytest3 (actual rows=6 loops=1) + SubPlan 1 + -> Aggregate (actual rows=6 loops=6) + -> Seq Scan on zytest3 (actual rows=6 loops=6) + Filter: (aid = zytest2.zid) + Rows Removed by Filter: 30 +--? Total runtime: .* ms +(27 rows) + +SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +) +WHERE nsum IS NOT NULL OR nsum>5 ORDER BY bid; + bid | nsum +-----+------ + 1 | 5 + 2 | 7 + 3 | 9 + 4 | 0 + 5 | 0 + 6 | 0 +(6 rows) + +explain (analyze, costs off, timing off) SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +) +WHERE nsum IS NOT NULL OR nsum>5 ORDER BY bid; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Sort (actual rows=6 loops=1) + Sort Key: zytest2.bid + Sort Method: quicksort Memory: 25kB + -> Seq Scan on zytest2 (actual rows=6 loops=1) + Filter: ((COALESCE((SubPlan 2), 0::numeric) IS NOT NULL) OR (COALESCE((SubPlan 3), 0::numeric) > 5::numeric)) + SubPlan 1 + -> Aggregate (actual rows=6 loops=6) + -> Seq Scan on zytest3 (actual rows=6 loops=6) + Filter: (aid = zytest2.zid) + Rows Removed by Filter: 30 + SubPlan 2 + -> Aggregate (actual rows=6 loops=6) + -> Seq Scan on zytest3 (actual rows=6 loops=6) + Filter: (aid = zytest2.zid) + Rows Removed by Filter: 30 + SubPlan 3 + -> Aggregate (Actual time: never executed) + -> Seq Scan on zytest3 (Actual time: never executed) + Filter: (aid = zytest2.zid) +--? Total runtime: .* ms +(20 rows) + diff --git a/src/test/regress/expected/out_param_func.out b/src/test/regress/expected/out_param_func.out index 282e6ace0271a73b2de323e424d52bdd1455314f..e1ad69effb0d9d377e1526fbfc424cecd3e56840 100644 --- a/src/test/regress/expected/out_param_func.out +++ b/src/test/regress/expected/out_param_func.out @@ -1201,6 +1201,24 @@ call pck1.f1(10,(1,'a',2)); 10 | (10,,) (1 row) +-- test expect no core +drop function if exists v_func1; +NOTICE: function v_func1() does not exist, skipping +create FUNCTION v_func1(c4 variadic integer[]) RETURN int is +BEGIN +raise notice 'c4 = %', c4; +return 1; +END; +/ +select v_func1(1, 2, 3); +NOTICE: c4 = {1,2,3} +CONTEXT: referenced column: v_func1 + v_func1 +--------- + 1 +(1 row) + +drop function v_func1; --clean reset behavior_compat_options; drop schema out_param_schema cascade; diff --git a/src/test/regress/expected/partition_dml_operations.out b/src/test/regress/expected/partition_dml_operations.out index 0523a627da90a5250d5ad06c8b81ed5c5a3e50a7..49a0d0a75ffc22a2e6ac0799c4071f73f697c8ff 100644 --- a/src/test/regress/expected/partition_dml_operations.out +++ b/src/test/regress/expected/partition_dml_operations.out @@ -2239,6 +2239,7 @@ explain delete from t_multi_parts_order partition(p4, p1) limit 10; (5 rows) ALTER TABLE t_multi_parts_order MERGE PARTITIONS p1,p2 INTO PARTITION p0; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index begin; delete from t_multi_parts_order partition(p3, p0, p4) limit 20; select count(*) from t_multi_parts_order partition (p0); @@ -2271,6 +2272,7 @@ explain delete from t_multi_parts_order partition(p3, p0, p4) limit 20; (5 rows) ALTER TABLE t_multi_parts_order SPLIT PARTITION p0 AT ( 10 ) INTO ( PARTITION p1 , PARTITION p2); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index begin; delete from t_multi_parts_order partition(p3, p2, p4) limit 10; select count(*) from t_multi_parts_order partition (p2); @@ -2303,6 +2305,7 @@ explain delete from t_multi_parts_order partition(p3, p2, p4) limit 10; (5 rows) ALTER TABLE t_multi_parts_order drop partition p4; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ALTER TABLE t_multi_parts_order add partition p5 values less than(50); ALTER TABLE t_multi_parts_order add partition p6 values less than(60); ALTER TABLE t_multi_parts_order add partition pmax values less than(maxvalue); diff --git a/src/test/regress/expected/plpgsql_depend/plpgsql_depend_type.out b/src/test/regress/expected/plpgsql_depend/plpgsql_depend_type.out index 480d58b5178e82328f9681e0cbe9edbfe27cc86c..c5ec9e17d42702188e9ae27db34546135c01049f 100644 --- a/src/test/regress/expected/plpgsql_depend/plpgsql_depend_type.out +++ b/src/test/regress/expected/plpgsql_depend/plpgsql_depend_type.out @@ -309,7 +309,7 @@ select a.schemaname as sn, a.packagename as pn, a.objectname as on, a.refobjpos -- remove dependency drop type sr cascade; -NOTICE: drop cascades to type _sr[] +--?.* select a.schemaname as sn, a.packagename as pn, a.objectname as on, a.refobjpos as refpos, b.schemaname as refsn, b.packagename as refpn, b.name as refon, b.type as refot, b.objnode as refast from gs_dependencies as a right join gs_dependencies_obj as b on b.oid = a.refobjoid where (a.schemaname='plpgsql_depend_type' and a.packagename='pkg') or (b.schemaname='plpgsql_depend_type' and b.packagename='pkg') order by a.schemaname, a.objectname, a.refobjpos, b.type, b.name; sn | pn | on | refpos | refsn | refpn | refon | refot | refast ----+----+----+--------+-------+-------+-------+-------+-------- @@ -1282,7 +1282,7 @@ select a.schemaname as sn, a.packagename as pn, a.objectname as on, a.refobjpos -- define ref dependency drop type sr cascade; -NOTICE: drop cascades to type _sr[] +--?.* select a.schemaname as sn, a.packagename as pn, a.objectname as on, a.refobjpos as refpos, b.schemaname as refsn, b.packagename as refpn, b.name as refon, b.type as refot, b.objnode as refast from gs_dependencies as a right join gs_dependencies_obj as b on b.oid = a.refobjoid where (a.schemaname='plpgsql_depend_type' and a.packagename='pkg') or (b.schemaname='plpgsql_depend_type' and b.packagename='pkg') order by a.schemaname, a.objectname, a.refobjpos, b.type, b.name; sn | pn | on | refpos | refsn | refpn | refon | refot | refast ----+----+----+--------+-------+-------+-------+-------+-------- @@ -1856,7 +1856,7 @@ select a.schemaname as sn, a.packagename as pn, a.objectname as on, a.refobjpos -- drop ref dependency drop type sr cascade; -NOTICE: drop cascades to type _sr[] +--?.* select valid from pg_object where object_type='S' and object_oid in (select Oid from gs_package where pkgname='pkg' and pkgnamespace = (select Oid from pg_namespace where nspname = 'plpgsql_depend_type')); valid ------- @@ -2033,7 +2033,7 @@ select a.schemaname as sn, a.packagename as pn, a.objectname as on, a.refobjpos -- drop ref dependency drop type sr cascade; NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to type _sr[] +--?.* drop cascades to type sr[] select valid from pg_object where object_type='S' and object_oid in (select Oid from gs_package where pkgname='pkg' and pkgnamespace = (select Oid from pg_namespace where nspname = 'plpgsql_depend_type')); valid @@ -2800,7 +2800,7 @@ select schemaname, packagename, objectname, refobjpos from gs_dependencies where --test 35 proc_param_type_used_undefine_pkg_type drop type if exists sr cascade; -NOTICE: drop cascades to type _sr[] +--?.* drop package if exists pkg; NOTICE: drop cascades to function plpgsql_depend_type.proc1() drop procedure if exists proc1; @@ -3068,10 +3068,10 @@ select pr.proname, po.valid, pr.proargtypes, pr.proargsrc from pg_proc as pr inn drop type ssr; ERROR: cannot drop type ssr because other objects depend on it -DETAIL: type _ssr[] depends on type ssr[] +DETAIL: type stab depends on type ssr[] HINT: Use DROP ... CASCADE to drop the dependent objects too. drop type ssr cascade; -NOTICE: drop cascades to type _ssr[] +NOTICE: drop cascades to type stab select a.schemaname as sn, a.packagename as pn, a.objectname as on, a.refobjpos as refpos, b.schemaname as refsn, b.packagename as refpn, b.name as refon, b.type as refot, b.objnode as refast from gs_dependencies as a right join gs_dependencies_obj as b on b.oid = a.refobjoid where (a.schemaname='plpgsql_depend_type' and a.objectname = 'stab') order by a.schemaname, a.objectname, a.refobjpos, b.type, b.name; sn | pn | on | refpos | refsn | refpn | refon | refot | refast ----+----+----+--------+-------+-------+-------+-------+-------- @@ -3152,7 +3152,7 @@ select pr.proname, po.valid, pr.proargtypes, pr.proargsrc from pg_proc as pr inn drop type ssr; ERROR: cannot drop type ssr because other objects depend on it -DETAIL: type _ssr[] depends on type ssr[] +DETAIL: type stab depends on type ssr[] HINT: Use DROP ... CASCADE to drop the dependent objects too. select * from gs_dependencies_obj where schemaname='plpgsql_depend_type' order by schemaname, packagename, name, type; schemaname | packagename | type | name | objnode diff --git a/src/test/regress/expected/plpgsql_depend/plpgsql_pkg_dependency.out b/src/test/regress/expected/plpgsql_depend/plpgsql_pkg_dependency.out index 3659dbac41a7219bc53a5079d891421b6b993d62..55c3b3525a6df79849b0bf560501869023c826b9 100644 --- a/src/test/regress/expected/plpgsql_depend/plpgsql_pkg_dependency.out +++ b/src/test/regress/expected/plpgsql_depend/plpgsql_pkg_dependency.out @@ -3,6 +3,7 @@ NOTICE: schema "plpgsql_pkg_dependency" does not exist, skipping create schema plpgsql_pkg_dependency; set current_schema = plpgsql_pkg_dependency; set behavior_compat_options = 'plpgsql_dependency'; +-- test 1 create or replace package test_package_depend2_pkg is type t is record (col1 int, col2 text); procedure p1(param test_package_depend3_pkg.t); @@ -30,7 +31,7 @@ type t is record (col1 int, col2 text, col3 varchar); procedure p1(param test_package_depend2_pkg.t); end test_package_depend3_pkg; / ---?WARNING: Package ?.* is invalid. +--?.* WARNING: Package created with compilation erors. create or replace package body test_package_depend3_pkg is procedure p1(param test_package_depend2_pkg.t) is @@ -39,7 +40,7 @@ procedure p1(param test_package_depend2_pkg.t) is end; end test_package_depend3_pkg; / ---?WARNING: Package ?.* is invalid. +--?.* WARNING: Package Body created with compilation erors. call test_package_depend2_pkg.p1((1,'a','2023')); INFO: call param: (1,a,2023) @@ -59,6 +60,66 @@ drop package if exists test_package_depend2_pkg; --?.* drop package if exists test_package_depend3_pkg; NOTICE: drop cascades to function plpgsql_pkg_dependency.p1(undefined) +-- test 2 +create or replace package pkg1 is +type x is record(tt int); +procedure a(zz pkg2.x); +end pkg1; +/ +WARNING: Type x does not exist. +WARNING: The header information of function a is not defined. +CONTEXT: compilation of PL/pgSQL package near line 1 +WARNING: Package created with compilation erors. +create or replace package body pkg1 is +procedure a(zz pkg2.x) is +begin +null; +end; +end pkg1; +/ +WARNING: Type x does not exist. +WARNING: The header information of function a is not defined. +CONTEXT: compilation of PL/pgSQL package near line 1 +WARNING: The header information of function a is not defined. +CONTEXT: compilation of PL/pgSQL package near line 1 +WARNING: Package Body created with compilation erors. +create or replace package pkg2 is +type x is record(tt int); +procedure a(zz pkg1.x); +end pkg2; +/ +--?.* +WARNING: Package created with compilation erors. +create or replace package body pkg2 is +procedure a( zz pkg1.x) is +begin +null; +end; +end pkg2; +/ +--?.* +WARNING: Package Body created with compilation erors. +\parallel on 2 +begin +perform pkg1.a(row(1)); +perform pg_sleep(1.5); +perform pkg2.a(row(1)); +perform pg_sleep(2.5); +end; +/ +begin +perform pg_sleep(0.5); +perform pkg2.a(row(1)); +perform pg_sleep(2.5); +perform pkg1.a(row(1)); +perform pg_sleep(2.5); +end; +/ +\parallel off +drop package if exists pkg1; +--?.* +drop package if exists pkg2; +NOTICE: drop cascades to function plpgsql_pkg_dependency.a(undefined) -- clean drop schema plpgsql_pkg_dependency cascade; reset behavior_compat_options; diff --git a/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out b/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out index db25c0bec3de875a94629ed5202377c3cdb250d3..52234c82322a3d44789fe42e019110b443957f55 100644 --- a/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out +++ b/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out @@ -466,6 +466,51 @@ INFO: call p_in: (1,"(1,zhang,M,1)") drop type r1; drop table stu; drop procedure test_proc; +-- test 7 +set behavior_compat_options = 'plpgsql_dependency'; +create or replace package pkg1 is +type tttt is record (col1 int, col2 text); +procedure p1(param pkg2.tqqq); +end pkg1; +/ +WARNING: Type tqqq does not exist. +WARNING: The header information of function p1 is not defined. +CONTEXT: compilation of PL/pgSQL package near line 1 +WARNING: Package created with compilation erors. +create or replace package pkg2 is +type tqqq is record (col1 int, col2 text, col3 varchar); +procedure p1(param pkg1.tttt); +end pkg2; +/ +--?.* +WARNING: Package created with compilation erors. +create or replace package body pkg2 is +procedure p1(param pkg1.tttt) is +begin +RAISE INFO 'call param: %', param; +end; +end pkg2; +/ +--?.* +WARNING: Package Body created with compilation erors. +call pkg2.p1((1,'a')); +INFO: call param: (1,a) + p1 +---- + +(1 row) + +set behavior_compat_options =''; +drop package pkg1; +--?.* +set behavior_compat_options = 'plpgsql_dependency'; +drop package pkg2; +NOTICE: drop cascades to function p1 +WARNING: The oid of the input parameter type of function p1 does not exist. +WARNING: function p1 does not exist +WARNING: function p1(plpgsql_recompile.pkg2.tqqq) does not exist +WARNING: function p1 does not exist +WARNING: function p1(plpgsql_recompile.pkg2.tqqq) does not exist -- clean drop schema plpgsql_recompile_new cascade; drop schema plpgsql_recompile cascade; diff --git a/src/test/regress/expected/plpgsql_inout_param.out b/src/test/regress/expected/plpgsql_inout_param.out index e8f56c696188d6ca98b1bb65d99e449143d0c7a9..9dc4bbac7d722f1e7d0a6a5027240c15f6cb9dfa 100644 --- a/src/test/regress/expected/plpgsql_inout_param.out +++ b/src/test/regress/expected/plpgsql_inout_param.out @@ -1810,7 +1810,7 @@ PL/pgSQL function inline_code_block line 5 at assignment INFO: res:10 INFO: z: drop package pck1; -NOTICE: drop cascades to function plpgsql_inout.f1(integer,_int4[]) +--?.* -- test custom type as in param create type myint; create function myintin(cstring) returns myint strict immutable language @@ -1884,10 +1884,8 @@ select test_inout_func2(); set behavior_compat_options="proc_outparam_override"; select test_inout_func2(); -ERROR: tuple is null -DETAIL: it may be because change guc behavior_compat_options in one session -CONTEXT: PL/pgSQL function test_inout_func2() line 4 at RETURN -referenced column: test_inout_func2 +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. +CONTEXT: referenced column: test_inout_func2 drop function test_inout_func2(); drop function test_inout_func(); drop type test_inout_type; @@ -1920,7 +1918,7 @@ drop cascades to function proc17() drop cascades to type t drop cascades to function proc3() drop cascades to function proc1() -drop cascades to type _int4[] +drop cascades to type t1 drop cascades to function p1(integer) drop cascades to function p2() drop cascades to function fun1() diff --git a/src/test/regress/expected/plpgsql_override_out.out b/src/test/regress/expected/plpgsql_override_out.out index 52de16a6f82e17d6b501a4ebbc8f1c922d019dd6..754b0c0a4f8299c4f9342f9549bc64b7c10ed47a 100644 --- a/src/test/regress/expected/plpgsql_override_out.out +++ b/src/test/regress/expected/plpgsql_override_out.out @@ -173,30 +173,15 @@ NOTICE: 1,2,,a, set behavior_compat_options = ''; call test_in_out_in(1,2,3,'a','b'); -NOTICE: 1,2,,a, - b | c | e ----+---+--- - 2 | | -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. begin; CURSOR temp_cursor NO SCROLL FOR SELECT test_in_out_in(1,2,'a'); FETCH FORWARD 1 FROM temp_cursor; -NOTICE: 1,2,,a, +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. CONTEXT: referenced column: test_in_out_in - test_in_out_in ----------------- - (2,,) -(1 row) - end; SELECT * from test_in_out_in(1,2,'a'); -NOTICE: 1,2,,a, - b | c | e ----+---+--- - 2 | | -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. ---- -- test in/out/inout args ---- @@ -232,22 +217,12 @@ NOTICE: 1,,2 set behavior_compat_options = 'proc_outparam_override'; call iob_proc(1,2,3); -- ok -NOTICE: 1,,3 - b | c ----+--- - | 3 -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. call iob_proc(1,2); ERROR: function iob_proc(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts. select * from iob_proc(1,2,3); -- ok -NOTICE: 1,,3 - b | c ----+--- - | 3 -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. select * from iob_proc(1,2); ERROR: function iob_proc(integer, integer) does not exist LINE 1: select * from iob_proc(1,2); @@ -284,22 +259,12 @@ NOTICE: 1,2, set behavior_compat_options = 'proc_outparam_override'; call bio_proc(1,2,3); -- ok -NOTICE: 1,2, - a | c ----+--- - 1 | -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. call bio_proc(1,2); ERROR: function bio_proc(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts. select * from bio_proc(1,2,3); -- ok -NOTICE: 1,2, - a | c ----+--- - 1 | -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. select * from bio_proc(1,2); ERROR: function bio_proc(integer, integer) does not exist LINE 1: select * from bio_proc(1,2); @@ -336,22 +301,12 @@ NOTICE: ,1,2 set behavior_compat_options = 'proc_outparam_override'; call obi_proc(1,2,3); -- ok -NOTICE: ,2,3 - a | b ----+--- - | 2 -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. call obi_proc(1,2); ERROR: function obi_proc(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts. select * from obi_proc(1,2,3); -- ok -NOTICE: ,2,3 - a | b ----+--- - | 2 -(1 row) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. select * from obi_proc(1,2); ERROR: function obi_proc(integer, integer) does not exist LINE 1: select * from obi_proc(1,2); @@ -389,20 +344,12 @@ NOTICE: 1,,2 set behavior_compat_options = 'proc_outparam_override'; call iob_func(1,2,3); -NOTICE: 1,,3 - iob_func | b | c -----------+---+--- -(0 rows) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. call iob_func(1,2); ERROR: function iob_func(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts. select * from iob_func(1,2,3); -NOTICE: 1,,3 - iob_func | b | c -----------+---+--- -(0 rows) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. select * from iob_func(1,2); -- ok ERROR: function iob_func(integer, integer) does not exist LINE 1: select * from iob_func(1,2); @@ -439,20 +386,12 @@ NOTICE: 1,2, set behavior_compat_options = 'proc_outparam_override'; call bio_func(1,2,3); -NOTICE: 1,2, - bio_func | a | c -----------+---+--- -(0 rows) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. call bio_func(1,2); ERROR: function bio_func(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts. select * from bio_func(1,2,3); -NOTICE: 1,2, - bio_func | a | c -----------+---+--- -(0 rows) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. select * from bio_func(1,2); -- ok ERROR: function bio_func(integer, integer) does not exist LINE 1: select * from bio_func(1,2); @@ -489,20 +428,12 @@ NOTICE: ,1,2 set behavior_compat_options = 'proc_outparam_override'; call obi_func(1,2,3); -NOTICE: ,2,3 - obi_func | a | b -----------+---+--- -(0 rows) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. call obi_func(1,2); ERROR: function obi_func(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts. select * from obi_func(1,2,3); -NOTICE: ,2,3 - obi_func | a | b -----------+---+--- -(0 rows) - +ERROR: Cannot change the PROC_OUTPARAM_OVERRIDE guc status while in the same session. select * from obi_func(1,2); -- ok ERROR: function obi_func(integer, integer) does not exist LINE 1: select * from obi_func(1,2); diff --git a/src/test/regress/expected/plpgsql_package_type.out b/src/test/regress/expected/plpgsql_package_type.out index 949d6d91c017ba861c36c470790da58456c4cf5c..ed631fcff82e6626fdc4fd051eed4cbec4bd4867 100644 --- a/src/test/regress/expected/plpgsql_package_type.out +++ b/src/test/regress/expected/plpgsql_package_type.out @@ -1314,17 +1314,6 @@ va pck1.r1; procedure p1; end pck1; / -ERROR: record type with table of attribute is not suppoted to be referenced by another package. -LINE 4: va pck1.r1; - ^ -DETAIL: attribute "a" of record type "r1" is table of with index by, which is not supported to be referenced by another package. -QUERY: PACKAGE DECLARE -type t1 is table of int index by int; -type r1 is record (a t1, b int); -va pck1.r1; -procedure p1; -end -CONTEXT: compilation of PL/pgSQL package near line 4 create or replace package pck1 as type t1 is table of int index by int; type r1 is record (a t1, b int); @@ -1339,14 +1328,6 @@ null; end; end pck1; / -ERROR: record type with table of attribute is not suppoted to be referenced by another package. -LINE 1: DECLARE vb pck1.r1; - ^ -DETAIL: attribute "a" of record type "r1" is table of with index by, which is not supported to be referenced by another package. -QUERY: DECLARE vb pck1.r1; -begin -null; -end drop package pck1; NOTICE: drop cascades to function plpgsql_packagetype1.p1() -- b, another ref @@ -1361,17 +1342,8 @@ begin null; end; / -ERROR: record type with table of attribute is not suppoted to be referenced by another package. -LINE 1: DECLARE va pck1.r1; - ^ -DETAIL: attribute "a" of record type "r1" is table of with index by, which is not supported to be referenced by another package. -QUERY: DECLARE va pck1.r1; -begin -null; -end drop package pck1; drop procedure p1; -ERROR: function p1 does not exist -- test pck1.va%type ref table of -- a. var ref create or replace package pck2 as @@ -1462,6 +1434,50 @@ varray1 tp_varray; procedure p1; end pak1 ; / +set behavior_compat_options='allow_procedure_compile_check'; +create table int_4(a NUMBER, b VARCHAR2(5)); +insert into int_4(a, b) values(3,'johan'); +create or replace package pck3_1 is +var1 RECORD; +procedure ppp1; +procedure ppp2(a int); +end pck3_1; +/ +create or replace package body pck3_1 is +procedure ppp1() is +query_str text; +begin +ppp2(9); +raise info '(ppp1)var1: %', var1.a; +end; + +procedure ppp2(a int) is +query_str text; +begin + query_str := 'select a,b from int_4'; + FOR var1 IN EXECUTE(query_str) LOOP + raise info '[ppp2]var1: %', var1.a; + END LOOP; + var1.a:=8+var1.a; + raise info '[ppp2]var1: %', var1.a; +end; +end pck3_1; +/ +call pck3_1.ppp1(); +INFO: [ppp2]var1: 3 +CONTEXT: SQL statement "CALL ppp2(9)" +PL/pgSQL function ppp1() line 3 at PERFORM +INFO: [ppp2]var1: 11 +CONTEXT: SQL statement "CALL ppp2(9)" +PL/pgSQL function ppp1() line 3 at PERFORM +INFO: (ppp1)var1: 11 + ppp1 +------ + +(1 row) + +drop table int_4 cascade; +set behavior_compat_options=''; -------------------------------------------------- ------------------ END OF TESTS ------------------ -------------------------------------------------- @@ -1473,6 +1489,10 @@ drop package plpgsql_packagetype1.p_test2; ERROR: package plpgsql_packagetype1.p_test2 does not exist drop package plpgsql_packagetype1.p_test1; ERROR: package plpgsql_packagetype1.p_test1 does not exist +drop package pck3_1; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to function plpgsql_packagetype1.ppp1() +drop cascades to function plpgsql_packagetype1.ppp2(integer) -- clean up -- drop schema if exists plpgsql_packagetype2 cascade; drop schema if exists plpgsql_packagetype1 cascade; diff --git a/src/test/regress/expected/plpgsql_table_opengauss.out b/src/test/regress/expected/plpgsql_table_opengauss.out index 61f9ff35cafb8aaa2d70a214e3bbca8835d19b20..2c207040f4e78099cf9cf3388a840cb4919c7354 100644 --- a/src/test/regress/expected/plpgsql_table_opengauss.out +++ b/src/test/regress/expected/plpgsql_table_opengauss.out @@ -926,15 +926,34 @@ INFO: plpgsql_table_opengauss.pck1.v2(2) is 3 0 (1 row) +-- test pg_get_function_result and pg_get_function_arguments +create type ty_test is(col1 int,col2 char(10),col3 varchar2(10)); +create type tyt_test is table of ty_test; +CREATE OR REPLACE PROCEDURE sp_tyt(i_tyt in tyt_test, o_tyt out tyt_test) +AS DECLARE +begin +o_tyt := i_tyt; +end; +/ +\df plpgsql_table_opengauss.sp_tyt + List of functions + Schema | Name | Result data type | Argument data types | Type | fencedmode | propackage | prokind +-------------------------+--------+------------------+------------------------------------+--------+------------+------------+--------- + plpgsql_table_opengauss | sp_tyt | tyt_test | i_tyt tyt_test, OUT o_tyt tyt_test | normal | f | f | p +(1 row) + +drop procedure sp_tyt; +drop type tyt_test; +drop type ty_test; drop type typeA; -ERROR: cannot drop type _s_type[] because other objects depend on it -DETAIL: function tableof_1(_s_type[]) depends on type _s_type[] +ERROR: cannot drop type typea because other objects depend on it +DETAIL: function tableof_1(typea) depends on type typea HINT: Use DROP ... CASCADE to drop the dependent objects too. drop type typeB; drop type s_type cascade; NOTICE: drop cascades to 5 other objects -DETAIL: drop cascades to type _s_type[] -drop cascades to function tableof_1(_s_type[]) +DETAIL: drop cascades to type typea +drop cascades to function tableof_1(typea) drop cascades to function tableof_4() drop cascades to function tableof_5() drop cascades to function tableof_9() @@ -943,7 +962,7 @@ drop type typeE; drop type typeG; drop type s_type_extend; ERROR: cannot drop type s_type_extend because other objects depend on it -DETAIL: type _s_type_extend[] depends on type s_type_extend[] +DETAIL: type typea_ext depends on type s_type_extend[] function tableof_8() depends on type s_type_extend[] HINT: Use DROP ... CASCADE to drop the dependent objects too. drop type typeA_ext; @@ -987,16 +1006,16 @@ drop schema if exists plpgsql_table_opengauss cascade; NOTICE: drop cascades to 19 other objects DETAIL: drop cascades to table int8_tbl drop cascades to view tt17v -drop cascades to type _varchar[] -drop cascades to type _varchar[] +drop cascades to type typed +drop cascades to type type1 drop cascades to type type2 drop cascades to type type3 -drop cascades to type _type3[] +drop cascades to type type4 drop cascades to type type5 drop cascades to table tycod01 drop cascades to type tycod02 drop cascades to table tycod03 -drop cascades to type _tycod01[] +drop cascades to type tycode23 drop cascades to function recordnes23() drop cascades to type s_type_extend drop cascades to function tableof_20() diff --git a/src/test/regress/expected/reduce_orderby.out b/src/test/regress/expected/reduce_orderby.out index 9364a7e70587b44bed2ee7e32403bde1e0b58407..d0de2a4eae903edd59d87497869a2bd0ed230fe8 100644 --- a/src/test/regress/expected/reduce_orderby.out +++ b/src/test/regress/expected/reduce_orderby.out @@ -213,6 +213,66 @@ explain (costs off) select t1.a from reduce_orderby_t1 t1 where t1.b in (select --drop table drop table reduce_orderby_t1; drop table reduce_orderby_t2; +CREATE TABLE orders (user_id int, order_id int, order_date date, quantity int, revenue float, product text); +INSERT INTO orders VALUES +(1, 1, '2021-03-05', 1, 15, 'books'), +(1, 2, '2022-03-07', 1, 3, 'music'), +(1, 3, '2022-06-15', 1, 900, 'travel'), +(1, 4, '2021-11-17', 2, 25, 'books'), +(2, 5, '2022-08-03', 2, 32, 'books'), +(2, 6, '2021-04-12', 2, 4, 'music'), +(2, 7, '2021-06-29', 3, 9, 'books'), +(2, 8, '2022-11-03', 1, 8, 'music'), +(3, 9, '2022-11-07', 1, 575, 'food'), +(3, 10, '2022-11-20', 2, 95, 'food'), +(3, 11, '2022-11-20', 1, 95, 'food'), +(4, 12, '2022-11-20', 2, 95, 'books'), +(4, 13, '2022-11-21', 1, 95, 'food'), +(4, 14, '2022-11-23', 4, 17, 'books'), +(5, 15, '2022-11-20', 1, 95, 'food'), +(5, 16, '2022-11-25', 2, 95, 'books'), +(5, 17, '2022-11-29', 1, 95, 'food'); +explain (costs off) SELECT avg(o.quantity) AS avg_quantity, +sum(o.revenue) AS total_revenue +FROM ( +SELECT DISTINCT ON (user_id) +user_id, product +FROM orders +ORDER BY user_id, order_date +) init +JOIN orders o USING (user_id, product) +WHERE init.product = 'books'; + QUERY PLAN +----------------------------------------------------------------------- + Aggregate + -> Nested Loop + Join Filter: (init.user_id = o.user_id) + -> Subquery Scan on init + Filter: (init.product = 'books'::text) + -> Unique + -> Sort + Sort Key: orders.user_id, orders.order_date + -> Seq Scan on orders + -> Seq Scan on orders o + Filter: (product = 'books'::text) +(11 rows) + +SELECT avg(o.quantity) AS avg_quantity, +sum(o.revenue) AS total_revenue +FROM ( +SELECT DISTINCT ON (user_id) +user_id, product +FROM orders +ORDER BY user_id, order_date +) init +JOIN orders o USING (user_id, product) +WHERE init.product = 'books'; + avg_quantity | total_revenue +--------------------+--------------- + 2.2500000000000000 | 152 +(1 row) + +drop table orders; --drop schema reset current_schema; drop schema reduce_orderby cascade; diff --git a/src/test/regress/expected/row_compression/normal_test.out b/src/test/regress/expected/row_compression/normal_test.out index dcdbca80c6b15180fe9b46ec82213c086a1eda05..1559c84f5ddde320e0666d894bce6d9d31a18cae 100644 --- a/src/test/regress/expected/row_compression/normal_test.out +++ b/src/test/regress/expected/row_compression/normal_test.out @@ -95,6 +95,7 @@ select relname, reloptions from pg_partition where parentid in (Select relfileno create table normal_test.exchange_table(id int) WITH(compresstype=2,compress_chunk_size=1024); ALTER TABLE normal_test.tbl_partition EXCHANGE PARTITION FOR(2500) WITH TABLE normal_test.exchange_table; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from normal_test.tbl_partition; count ------- @@ -103,6 +104,7 @@ select count(*) from normal_test.tbl_partition; -- spilit ALTER TABLE normal_test.tbl_partition SPLIT PARTITION p1 AT (7500) INTO (PARTITION p10, PARTITION p11); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select relname, reloptions from pg_partition where parentid in (Select relfilenode from pg_class where relname like 'tbl_partition') order by relname; relname | reloptions ---------------+---------------------------------------------------------------------------- diff --git a/src/test/regress/expected/segment_subpartition_add_drop_partition.out b/src/test/regress/expected/segment_subpartition_add_drop_partition.out index 9e61689254b014017d66569946afffdc76985612..a7775517412c8ad30689b7038d801caa38776d29 100644 --- a/src/test/regress/expected/segment_subpartition_add_drop_partition.out +++ b/src/test/regress/expected/segment_subpartition_add_drop_partition.out @@ -170,14 +170,17 @@ Options: orientation=row, segment=on, compression=no --check for drop partition/subpartition (for) --success, drop partition customer2 ALTER TABLE range_range_sales DROP PARTITION customer2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE range_range_sales DROP SUBPARTITION customer1_2008; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE range_range_sales DROP SUBPARTITION customer4_all; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition customer3 ALTER TABLE range_range_sales DROP PARTITION FOR (400); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE range_range_sales DROP PARTITION FOR (400, '2010-01-01'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -193,6 +196,7 @@ ALTER TABLE range_range_sales DROP SUBPARTITION FOR ('2010-01-01', 1400); ERROR: invalid input syntax for integer: "2010-01-01" --success, drop subpartition customer5_2010 ALTER TABLE range_range_sales DROP SUBPARTITION FOR(1400, '2010-01-01'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in customer6 ALTER TABLE range_range_sales DROP SUBPARTITION FOR(2000, '2009-01-01'); ERROR: Cannot drop the only subpartition of a partitioned table @@ -442,14 +446,17 @@ Options: orientation=row, segment=on, compression=no --check for drop partition/subpartition (for) --success, drop partition customer2 ALTER TABLE range_list_sales DROP PARTITION customer2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE range_list_sales DROP SUBPARTITION customer1_channel1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE range_list_sales DROP SUBPARTITION customer4_channel1; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition customer3 ALTER TABLE range_list_sales DROP PARTITION FOR (400); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE range_list_sales DROP PARTITION FOR (400, '4'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -465,6 +472,7 @@ ALTER TABLE range_list_sales DROP SUBPARTITION FOR ('abc', 1400); ERROR: invalid input syntax for integer: "abc" --success, drop subpartition customer5_channel3 ALTER TABLE range_list_sales DROP SUBPARTITION FOR(1400, '7'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in customer6 ALTER TABLE range_list_sales DROP SUBPARTITION FOR(2000, 'X'); ERROR: Cannot drop the only subpartition of a partitioned table @@ -709,6 +717,7 @@ Options: orientation=row, segment=on, compression=no --check for drop partition/subpartition (for) --success, drop partition customer2 ALTER TABLE range_hash_sales DROP PARTITION customer2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, not support drop hash ALTER TABLE range_hash_sales DROP SUBPARTITION customer1_product1; ERROR: Un-support feature @@ -719,6 +728,7 @@ ERROR: Un-support feature DETAIL: The syntax is unsupported for hash subpartition --success, drop partition customer3 ALTER TABLE range_hash_sales DROP PARTITION FOR (400); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE range_hash_sales DROP PARTITION FOR (400, '2010-01-01'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -972,14 +982,17 @@ Options: orientation=row, segment=on, compression=no --check for drop partition/subpartition (for) --success, drop partition channel2 ALTER TABLE list_range_sales DROP PARTITION channel2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE list_range_sales DROP SUBPARTITION channel1_customer1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE list_range_sales DROP SUBPARTITION channel4_customer1; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition channel3 ALTER TABLE list_range_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE list_range_sales DROP PARTITION FOR('X', 700); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -995,6 +1008,7 @@ ALTER TABLE list_range_sales DROP SUBPARTITION FOR(700, 'X'); ERROR: value too long for type character(1) --success, drop subpartition channel5_customer3 ALTER TABLE list_range_sales DROP SUBPARTITION FOR('X', 700); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in channel6 ALTER TABLE list_range_sales DROP SUBPARTITION FOR('K', 100); ERROR: Cannot drop the only subpartition of a partitioned table @@ -1244,14 +1258,17 @@ Options: orientation=row, segment=on, compression=no --check for drop partition/subpartition (for) --success, drop partition channel2 ALTER TABLE list_list_sales DROP PARTITION channel2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success ALTER TABLE list_list_sales DROP SUBPARTITION channel1_type1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition ALTER TABLE list_list_sales DROP SUBPARTITION channel4_type1; ERROR: Cannot drop the only subpartition of a partitioned table DETAIL: N/A --success, drop partition channel3 ALTER TABLE list_list_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE list_list_sales DROP PARTITION FOR('X', 6); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -1267,6 +1284,7 @@ ALTER TABLE list_list_sales DROP SUBPARTITION FOR(10, 'X'); ERROR: value too long for type character(1) --success, drop subpartition channel5_type3 ALTER TABLE list_list_sales DROP SUBPARTITION FOR('X', 6); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in channel6 ALTER TABLE list_list_sales DROP SUBPARTITION FOR('K', 10); ERROR: Cannot drop the only subpartition of a partitioned table @@ -1511,6 +1529,7 @@ Options: orientation=row, segment=on, compression=no --check for drop partition/subpartition (for) --success, drop partition channel2 ALTER TABLE list_hash_sales DROP PARTITION channel2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, not support drop hash ALTER TABLE list_hash_sales DROP SUBPARTITION channel1_product1; ERROR: Un-support feature @@ -1521,6 +1540,7 @@ ERROR: Un-support feature DETAIL: The syntax is unsupported for hash subpartition --success, drop partition channel3 ALTER TABLE list_hash_sales DROP PARTITION FOR ('6'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, number not equal to the number of partkey ALTER TABLE list_hash_sales DROP PARTITION FOR ('6', '2010-01-01'); ERROR: number of boundary items NOT EQUAL to number of partition keys @@ -1763,8 +1783,10 @@ ALTER TABLE hash_range_sales DROP PARTITION product2; ERROR: Droping hash partition is unsupported. --success, drop subpartition product1_customer1 ALTER TABLE hash_range_sales DROP SUBPARTITION product1_customer1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop subpartition product4_customer1 ALTER TABLE hash_range_sales DROP SUBPARTITION product4_customer1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in product4 ALTER TABLE hash_range_sales DROP SUBPARTITION product4_customer2; ERROR: Cannot drop the only subpartition of a partitioned table @@ -1784,6 +1806,7 @@ ALTER TABLE hash_range_sales DROP SUBPARTITION FOR('2010-01-01', 100); ERROR: invalid input syntax for integer: "2010-01-01" --success, drop subpartition product1_customer2, but not suggest to do this operation ALTER TABLE hash_range_sales DROP SUBPARTITION FOR(0, 100); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, no subpartition find ALTER TABLE hash_range_sales DROP SUBPARTITION FOR(0, 2300); ERROR: The subpartition number is invalid or out-of-range @@ -2017,8 +2040,10 @@ ALTER TABLE hash_list_sales DROP PARTITION product2; ERROR: Droping hash partition is unsupported. --success, drop subpartition product1_channel1 ALTER TABLE hash_list_sales DROP SUBPARTITION product1_channel1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --success, drop subpartition product4_channel1 ALTER TABLE hash_list_sales DROP SUBPARTITION product4_channel1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, the only subpartition in product4 ALTER TABLE hash_list_sales DROP SUBPARTITION product4_channel2; ERROR: Cannot drop the only subpartition of a partitioned table @@ -2038,6 +2063,7 @@ ALTER TABLE hash_list_sales DROP SUBPARTITION FOR('2010-01-01', '4'); ERROR: invalid input syntax for integer: "2010-01-01" --success, drop subpartition product1_channel2, but not suggest to do this operation ALTER TABLE hash_list_sales DROP SUBPARTITION FOR(0, '4'); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --fail, no subpartition find ALTER TABLE hash_list_sales DROP SUBPARTITION FOR(0, 'Z'); ERROR: The subpartition number is invalid or out-of-range diff --git a/src/test/regress/expected/segment_subpartition_alter_table.out b/src/test/regress/expected/segment_subpartition_alter_table.out index 941da92bb829ea2683d009c29ce12fad6f4b5bff..c5ea776ef789f6af1934841c8816da8e6a2e6c18 100644 --- a/src/test/regress/expected/segment_subpartition_alter_table.out +++ b/src/test/regress/expected/segment_subpartition_alter_table.out @@ -93,6 +93,7 @@ LINE 1: ALTER TABLE range_range EXCHANGE SUBPARTITION (p_201901) WIT... ^ -- drop alter table range_range drop partition p_201901; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table range_range drop partition p_201901_a; ERROR: partition "p_201901_a" does not exist alter table range_range drop subpartition p_201901_a; diff --git a/src/test/regress/expected/segment_subpartition_ddl_index.out b/src/test/regress/expected/segment_subpartition_ddl_index.out index 9220498516c490104476593b94e1761e823a5ee6..ee28e16a004714cc7a47c07145354ce047a56b73 100644 --- a/src/test/regress/expected/segment_subpartition_ddl_index.out +++ b/src/test/regress/expected/segment_subpartition_ddl_index.out @@ -256,6 +256,7 @@ SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx4) */ COUNT(time --4. if drop partition without update global index, the gpi will be invalid, we can rebuild the index ALTER TABLE range_list_sales1 DROP PARTITION FOR (1600); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXPLAIN(costs off) SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx1) */ COUNT(product_id) FROM range_list_sales1; WARNING: Error hint: IndexOnlyScan(range_list_sales1 range_list_sales1_idx1), index "range_list_sales1_idx1" doesn't exist. QUERY PLAN @@ -344,6 +345,7 @@ SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx4) */ COUNT(time --5. if drop subpartition without update global index, the gpi will be invalid, we can rebuild the index ALTER TABLE range_list_sales1 DROP SUBPARTITION customer5_channel3; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index EXPLAIN(costs off) SELECT /*+ indexonlyscan(range_list_sales1 range_list_sales1_idx1) */ COUNT(product_id) FROM range_list_sales1; WARNING: Error hint: IndexOnlyScan(range_list_sales1 range_list_sales1_idx1), index "range_list_sales1_idx1" doesn't exist. QUERY PLAN diff --git a/src/test/regress/expected/segment_subpartition_gpi.out b/src/test/regress/expected/segment_subpartition_gpi.out index ae6abc570a95951fe2299698a06aa8486aecbfd5..585afef3c34502240c115f7cd77a083bd1d5984a 100644 --- a/src/test/regress/expected/segment_subpartition_gpi.out +++ b/src/test/regress/expected/segment_subpartition_gpi.out @@ -454,6 +454,7 @@ select * from range_list where user_no = '1' order by 1, 2, 3, 4; (3 rows) alter table range_list truncate subpartition p_201901_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(costs off, verbose on) select * from range_list where month_code = '201902' order by 1, 2, 3, 4; QUERY PLAN ---------------------------------------------------------------------------------- @@ -721,6 +722,7 @@ alter table range_list split subpartition p_201902_b values ('3') into subpartition p_201902_b, subpartition p_201902_c ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(costs off, verbose on) select * from range_list where month_code = '201902' order by 1, 2, 3, 4; QUERY PLAN ---------------------------------------------------------------------------------- @@ -995,6 +997,7 @@ alter table range_range split subpartition p_201902_b at ('3') into subpartition p_201902_c, subpartition p_201903_d ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(costs off, verbose on) select * from range_range where month_code = '201902' order by 1, 2, 3, 4; QUERY PLAN ----------------------------------------------------------------------------------- diff --git a/src/test/regress/expected/segment_subpartition_split.out b/src/test/regress/expected/segment_subpartition_split.out index dc6706674d9fb967bbb476c311ed0bf98e715989..9684e8c81d3dfb01cc68896245ee14fb5d92aba3 100644 --- a/src/test/regress/expected/segment_subpartition_split.out +++ b/src/test/regress/expected/segment_subpartition_split.out @@ -60,6 +60,7 @@ alter table list_list split subpartition p_201901_b values (2) into subpartition p_201901_b, subpartition p_201901_c ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -104,6 +105,7 @@ alter table list_list split subpartition p_201902_b values (2, 3) into subpartition p_201902_b, subpartition p_201902_c ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -186,6 +188,7 @@ alter table range_range split subpartition p_201901_b at (3) into subpartition p_201901_c, subpartition p_201901_d ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from range_range subpartition (p_201901_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -224,6 +227,7 @@ alter table range_range split subpartition p_201902_b at (3) into subpartition p_201902_c, subpartition p_201902_d ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from range_range subpartition (p_201902_a) order by 1,2,3,4; month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- diff --git a/src/test/regress/expected/segment_subpartition_truncate.out b/src/test/regress/expected/segment_subpartition_truncate.out index a7bc54f23a7d5e07dfeaffab30af1f744e6bad01..adaf15d2f7dd22cbe824b9c95c6b61e6f21d789e 100644 --- a/src/test/regress/expected/segment_subpartition_truncate.out +++ b/src/test/regress/expected/segment_subpartition_truncate.out @@ -50,6 +50,7 @@ select * from list_list partition (p_201901); (3 rows) alter table list_list truncate partition p_201901; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list partition (p_201901); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -64,6 +65,7 @@ select * from list_list partition (p_201902); (3 rows) alter table list_list truncate partition p_201902; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list partition (p_201902); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -88,6 +90,7 @@ select * from list_list subpartition (p_201901_a); (2 rows) alter table list_list truncate subpartition p_201901_a; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_a); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -100,6 +103,7 @@ select * from list_list subpartition (p_201901_b); (1 row) alter table list_list truncate subpartition p_201901_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_b); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -112,6 +116,7 @@ select * from list_list subpartition (p_201902_a); (1 row) alter table list_list truncate subpartition p_201902_a; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_a); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -125,6 +130,7 @@ select * from list_list subpartition (p_201902_b); (2 rows) alter table list_list truncate subpartition p_201902_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_b); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- diff --git a/src/test/regress/expected/single_node_triggers.out b/src/test/regress/expected/single_node_triggers.out index 46686e79130470fd0be38af61556d7288ff429bd..a05e2ed5532efa91d7a902686a08952d638bf0c7 100644 --- a/src/test/regress/expected/single_node_triggers.out +++ b/src/test/regress/expected/single_node_triggers.out @@ -1756,3 +1756,49 @@ drop table t1; drop table t2; drop function t1_tri_func; drop schema part_bri_warnning; +create schema test_schema_for_trigger; +set current_schema to test_schema_for_trigger; +--触发器测试 +--测试时用到的package +CREATE OR REPLACE PACKAGE func_test_pkg1 AS + -- integer 类型的变量 + int_val INTEGER := 0; + + -- record 类型的定义 + TYPE rec_type IS RECORD ( + msg VARCHAR2(100) + ); + + PROCEDURE proc1; +END func_test_pkg1; +/ +CREATE OR REPLACE PACKAGE BODY func_test_pkg1 AS + PROCEDURE proc1 AS + BEGIN + RAISE NOTICE 'In func_test_pkg1.proc1()'; + END proc1; +END func_test_pkg1; +/ +CREATE TABLE trg_test(id int, name text); +create or replace function global_cache_trigger_test() + return TRIGGER as + begin + func_test_pkg1.int_val = func_test_pkg1.int_val + 1; + raise notice 'func_test_pkg1.int_val=%',func_test_pkg1.int_val; + return new; +end; +/ +CREATE TRIGGER trigger_global_cache_trigger_test +AFTER INSERT ON trg_test +FOR EACH ROW +EXECUTE PROCEDURE global_cache_trigger_test(); +insert into trg_test values(1,'引用package中的变量'); +NOTICE: func_test_pkg1.int_val=1 +insert into trg_test values(1,'引用package中的变量'); +NOTICE: func_test_pkg1.int_val=2 +drop package func_test_pkg1; +NOTICE: drop cascades to function test_schema_for_trigger.proc1() +drop schema test_schema_for_trigger cascade; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table trg_test +drop cascades to function global_cache_trigger_test() diff --git a/src/test/regress/expected/ss_wr/segment_subpartition_truncate.out b/src/test/regress/expected/ss_wr/segment_subpartition_truncate.out index 970a03f1a88b1fd38971bebfa703c6b2eb791c80..2be30d900c973742d42294801ff707e2ee0b2849 100644 --- a/src/test/regress/expected/ss_wr/segment_subpartition_truncate.out +++ b/src/test/regress/expected/ss_wr/segment_subpartition_truncate.out @@ -50,6 +50,7 @@ select * from list_list partition (p_201901); (3 rows) alter table list_list truncate partition p_201901; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list partition (p_201901); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -64,6 +65,7 @@ select * from list_list partition (p_201902); (3 rows) alter table list_list truncate partition p_201902; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list partition (p_201902); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -88,6 +90,7 @@ select * from list_list subpartition (p_201901_a); (2 rows) alter table list_list truncate subpartition p_201901_a; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_a); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -100,6 +103,7 @@ select * from list_list subpartition (p_201901_b); (1 row) alter table list_list truncate subpartition p_201901_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201901_b); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -112,6 +116,7 @@ select * from list_list subpartition (p_201902_a); (1 row) alter table list_list truncate subpartition p_201902_a; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_a); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- @@ -125,6 +130,7 @@ select * from list_list subpartition (p_201902_b); (2 rows) alter table list_list truncate subpartition p_201902_b; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from list_list subpartition (p_201902_b); month_code | dept_code | user_no | sales_amt ------------+-----------+---------+----------- diff --git a/src/test/regress/expected/sw_bugfix-1.out b/src/test/regress/expected/sw_bugfix-1.out index 7e753871a0532b06f0c9072cc9054701757a42ec..805991a58ff3e91bb2826f64a153e70f5ae117ed 100644 --- a/src/test/regress/expected/sw_bugfix-1.out +++ b/src/test/regress/expected/sw_bugfix-1.out @@ -452,7 +452,6 @@ explain (costs off) select t1.ID,t1.VCH,pid,NAME,PTEX from TEST_HCB_FQB t1,TEST_ QUERY PLAN ---------------------------------------------------------------------------- CTE Scan on tmp_reuslt - Filter: ("t1@id" = "t2@id") CTE tmp_reuslt -> StartWith Operator Start With pseudo atts: RUITR, array_key_1 @@ -471,7 +470,7 @@ explain (costs off) select t1.ID,t1.VCH,pid,NAME,PTEX from TEST_HCB_FQB t1,TEST_ -> WorkTable Scan on tmp_reuslt -> Hash -> Seq Scan on test_hcb_fqb t1 -(20 rows) +(19 rows) CREATE OR REPLACE FUNCTION test_hcb_pro1(i_id in int) return int AS @@ -1840,3 +1839,29 @@ select max(name) from test3 connect by parentid = prior id group by sys_connect_ drop table test3; drop table test2; drop table test1; +drop table if exists left_table; +drop table if exists right_table; +create table left_table(id int); +create table right_table(id int); +declare +i int:=0; +begin +for i in 1..5 loop +insert into left_table values(i); +insert into right_table values(i+1); +end loop; +commit; +end; +/ +select left_table.id as id1,right_table.id as id2 from left_table,right_table where left_table.id+1=right_table.id start with left_table.id=1 connect by prior right_table.id=left_table.id; + id1 | id2 +-----+----- + 1 | 2 + 2 | 3 + 3 | 4 + 4 | 5 + 5 | 6 +(5 rows) + +drop table left_table; +drop table right_table; diff --git a/src/test/regress/expected/sw_bugfix-2.out b/src/test/regress/expected/sw_bugfix-2.out index 4091859880067a68ed6ee7f3edc0a2dd769331ca..99cd9f242bc2934a54c1f667010bb4a6d8d0959e 100755 --- a/src/test/regress/expected/sw_bugfix-2.out +++ b/src/test/regress/expected/sw_bugfix-2.out @@ -1404,11 +1404,11 @@ select id,pid,prior(level) from test_hcb_ptb where prior(id)>10 start with id=141 connect by prior pid=id; id | pid | prior -----+-----+------- - 141 | 131 | 3 131 | 121 | 6 121 | 111 | 9 111 | 11 | 12 11 | 1 | 15 + 1 | 0 | 18 (5 rows) select prior(1+1); @@ -1799,7 +1799,12 @@ create table dts_t1(c1 int,c2 int,c3 int); insert into dts_t1 values(1,1,1); insert into dts_t1 values(2,2,2); select c1,prior c2,c2 from dts_t1 start with c1=1 connect by prior c2+1=c2 ; -ERROR: Not Support prior column in TargetList in case swcb. + c1 | c2 | c2 +----+----+---- + 1 | | 1 + 2 | 1 | 2 +(2 rows) + select c1,c2 from dts_t1 start with c1=1 connect by prior c2+1=c2 ; c1 | c2 ----+---- @@ -1892,6 +1897,130 @@ DETAIL: Unsupported node type: 900. SELECT * FROM RLTEST CONNECT BY PRIOR B=A OR (MOD(ROWNUM+1,2) = 0); ERROR: column specified by prior cannot concide with ROWNUM/LEVEL. DETAIL: Unsupported node type: 900. +-- test for multi table join used with pseudo col in where clause +delete from rltest; +INSERT INTO RLTEST VALUES('1','2'),('2','3'),('3','1'); +explain select * from rltest r1,rltest r2 where r1.a<=connect_by_isleaf+level+connect_by_iscycle+connect_by_root(r1.a) start with r1.a=1 connect by nocycle prior r2.b=r1.a; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + CTE Scan on tmp_reuslt (cost=788273757.40..1796601238.36 rows=8402729008 width=32) + Filter: (("r1@a")::bigint <= (((connect_by_isleaf + level) + connect_by_iscycle) + (connect_by_root(("r1@a")::text))::bigint)) + CTE tmp_reuslt + -> StartWith Operator (cost=0.00..788273757.40 rows=25208187024 width=32) + Start With pseudo atts: RUITR, array_key_4, array_col_1 + -> Recursive Union (cost=0.00..788273757.40 rows=25208187024 width=32) + -> Nested Loop (cost=0.00..264.22 rows=15984 width=32) + -> Seq Scan on rltest r2 (cost=0.00..27.76 rows=1776 width=16) + -> Materialize (cost=0.00..36.69 rows=9 width=16) + -> Seq Scan on rltest r1 (cost=0.00..36.64 rows=9 width=16) + Filter: ((a)::bigint = 1) + -> Hash Join (cost=5194.80..28410975.27 rows=2520817104 width=32) + Hash Cond: (r1.a = tmp_reuslt."r2@b") + -> Nested Loop (cost=0.00..39487.16 rows=3154176 width=32) + -> Seq Scan on rltest r2 (cost=0.00..27.76 rows=1776 width=16) + -> Materialize (cost=0.00..36.64 rows=1776 width=16) + -> Seq Scan on rltest r1 (cost=0.00..27.76 rows=1776 width=16) + -> Hash (cost=3196.80..3196.80 rows=159840 width=8) + -> WorkTable Scan on tmp_reuslt (cost=0.00..3196.80 rows=159840 width=8) +(19 rows) + +select * from rltest r1,rltest r2 where r1.a<=connect_by_isleaf+level+connect_by_iscycle+connect_by_root(r1.a) start with r1.a=1 connect by nocycle prior r2.b=r1.a; + a | b | a | b +---+---+---+--- + 1 | 2 | 1 | 2 + 2 | 3 | 2 | 3 + 3 | 1 | 3 | 1 + 2 | 3 | 3 | 1 + 1 | 2 | 2 | 3 + 1 | 2 | 2 | 3 + 3 | 1 | 1 | 2 + 2 | 3 | 3 | 1 + 3 | 1 | 3 | 1 + 1 | 2 | 1 | 2 + 1 | 2 | 3 | 1 + 1 | 2 | 1 | 2 + 2 | 3 | 2 | 3 + 1 | 2 | 2 | 3 + 3 | 1 | 1 | 2 +(15 rows) + +-- test cross reference in start with nested query +create table test_t1(a1 int,b1 int); +create table test_t2(a2 int,b2 int); +create table test_t3(a3 int,b3 int); +insert into test_t1 values(1,2),(2,3),(3,1); +insert into test_t2 values(1,2),(2,3),(3,1); +insert into test_t3 values(1,2),(2,3),(3,1); +explain select * from test_t1 left join test_t2 on a1=a2 where exists (select 1 from test_t3 where a1+a2 is not null connect by level<2) connect by level<2; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + CTE Scan on tmp_reuslt (cost=1732932777.76..800532784124548096.00 rows=26659731370 width=16) + Filter: (SubPlan 3) + CTE tmp_reuslt + -> StartWith Operator (cost=58.35..1732932777.76 rows=53319462741 width=16) + Start With pseudo atts: RUITR + -> Recursive Union (cost=58.35..1732932777.76 rows=53319462741 width=16) + -> Hash Left Join (cost=58.35..355.67 rows=23091 width=16) + Hash Cond: (swtest.test_t1.a1 = swtest.test_t2.a2) + -> Seq Scan on test_t1 (cost=0.00..31.49 rows=2149 width=8) + -> Hash (cost=31.49..31.49 rows=2149 width=8) + -> Seq Scan on test_t2 (cost=0.00..31.49 rows=2149 width=8) + -> Nested Loop (cost=58.35..66654316.73 rows=5331943965 width=16) + -> WorkTable Scan on tmp_reuslt (cost=0.00..4618.20 rows=230910 width=0) + -> Materialize (cost=58.35..471.13 rows=23091 width=16) + -> Hash Left Join (cost=58.35..355.67 rows=23091 width=16) + Hash Cond: (swtest.test_t1.a1 = swtest.test_t2.a2) + -> Seq Scan on test_t1 (cost=0.00..31.49 rows=2149 width=8) + -> Hash (cost=31.49..31.49 rows=2149 width=8) + -> Seq Scan on test_t2 (cost=0.00..31.49 rows=2149 width=8) + SubPlan 3 + -> Result (cost=15013894.35..24250339.33 rows=461822249 width=0) + One-Time Filter: ((tmp_reuslt."test_t1@a1" + tmp_reuslt."test_t2@a2") IS NOT NULL) + CTE tmp_reuslt + -> StartWith Operator (cost=0.00..15013894.35 rows=461822249 width=8) + Start With pseudo atts: RUITR + -> Recursive Union (cost=0.00..15013894.35 rows=461822249 width=8) + -> Seq Scan on test_t3 (cost=0.00..31.49 rows=2149 width=8) + -> Nested Loop (cost=0.00..577741.79 rows=46182010 width=8) + -> WorkTable Scan on tmp_reuslt (cost=0.00..429.80 rows=21490 width=0) + -> Materialize (cost=0.00..42.23 rows=2149 width=8) + -> Seq Scan on test_t3 (cost=0.00..31.49 rows=2149 width=8) + -> CTE Scan on tmp_reuslt (cost=0.00..9236444.98 rows=461822249 width=0) +(32 rows) + +drop table test_t1; +drop table test_t2; +drop table test_t3; +-- test sys funcs in multi table join +select sys_connect_by_path(r1.a,'->') from rltest r1, rltest r2 where r1.a=r2.a connect by level<2; + sys_connect_by_path +--------------------- + ->1 + ->2 + ->3 +(3 rows) + +select connect_by_root(r1.a) from rltest r1, rltest r2 where r1.a=r2.a connect by level<2; + connect_by_root +----------------- + 1 + 2 + 3 +(3 rows) + +-- test for where push down +create table sin_col_tbl(a int); +SELECT 1 +FROM sin_col_tbl, + rltest +WHERE (sin_col_tbl.a+rltest.b) IS NOT NULL +START WITH 1=1 +CONNECT BY level<2 and prior rltest.b=rltest.a; + ?column? +---------- +(0 rows) + +drop table sin_col_tbl; DROP TABLE RLTEST; create table nocycle_tbl(id int, lid int, name text); insert into nocycle_tbl values (1,3,'A'),(2,1,'B'),(3,2,'C'),(4,2,'D'),(5,3,'E'); @@ -2119,3 +2248,97 @@ connect by drop synonym sy_pf; drop table pf_org_rela_test; +drop table if exists sw_test; + +-- test join clause in where split and push down into start with/connect by clause +drop table if exists sw_tb_1; +create table sw_tb_1(a int,b int,c int,d int); +create table sw_tb_2(a int,b int,c int,d int); +create table sw_tb_3(a int, b int, c int, d int); +insert into sw_tb_1 values(1,1,1,1); +insert into sw_tb_1 values(2,2,2,2); +insert into sw_tb_1 values(3,3,3,3); +insert into sw_tb_1 values(4,4,4,4); +insert into sw_tb_2 values(1,1,1,1); +insert into sw_tb_2 values(2,2,2,2); +insert into sw_tb_2 values(3,3,3,3); +insert into sw_tb_2 values(4,4,4,4); +select * from sw_tb_1,sw_tb_2 where sw_tb_1.c=sw_tb_2.d start with sw_tb_1.a>2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; + a | b | c | d | a | b | c | d +---+---+---+---+---+---+---+--- + 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 + 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 +(2 rows) + +select * from sw_tb_1,sw_tb_2 where (sw_tb_1.a=sw_tb_2.b or sw_tb_1.a not in (select 3)) and sw_tb_1.c=sw_tb_2.d start with sw_tb_1.a>2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; + a | b | c | d | a | b | c | d +---+---+---+---+---+---+---+--- + 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 +(1 row) + +select * from sw_tb_1,sw_tb_2 where sw_tb_1.a !=3 or sw_tb_1.c=sw_tb_2.d start with sw_tb_1.a>2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; + a | b | c | d | a | b | c | d +---+---+---+---+---+---+---+--- + 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 +(1 row) + +select * from sw_tb_1,sw_tb_2 where (sw_tb_1.a+sw_tb_1.b=sw_tb_2.b or sw_tb_1.a=sw_tb_2.c) and (sw_tb_1.b=sw_tb_2.a or (substr(sw_tb_1.b,2)=substr(sw_tb_2.b,2) and sw_tb_1.b is null)) or (sw_tb_1.c=sw_tb_2.d or sw_tb_1.b!=2) start with sw_tb_1.a=2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; + a | b | c | d | a | b | c | d +---+---+---+---+---+---+---+--- +(0 rows) + +explain select * from sw_tb_1,sw_tb_2 where (sw_tb_1.a+sw_tb_1.b=sw_tb_2.b or sw_tb_1.a=sw_tb_2.c) and (sw_tb_1.b=sw_tb_2.a or (substr(sw_tb_1.b,2)=substr(sw_tb_2.b,2) and sw_tb_1.b is null)) or (sw_tb_1.c=sw_tb_2.d or sw_tb_1.b!=2) start with sw_tb_1.a=2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + CTE Scan on tmp_reuslt (cost=1205332.35..1220171.82 rows=652970 width=32) + Filter: (("sw_tb_1@b" IS NULL) OR ("sw_tb_1@b" <> 2)) + CTE tmp_reuslt + -> StartWith Operator (cost=0.00..1205332.35 rows=659532 width=32) + Start With pseudo atts: RUITR, array_key_4 + -> Recursive Union (cost=0.00..1205332.35 rows=659532 width=32) + -> Nested Loop (cost=0.00..659.38 rows=82 width=32) + Join Filter: (((((swtest.sw_tb_1.a + swtest.sw_tb_1.b) = swtest.sw_tb_2.b) OR (swtest.sw_tb_1.a = swtest.sw_tb_2.c)) AND ((swtest.sw_tb_1.b = swtest.sw_tb_2.a) OR (substr((swtest.sw_tb_1.b)::text, 2) = substr((swtest.sw_tb_2.b)::text, 2)))) OR (swtest.sw_tb_1.c = swtest.sw_tb_2.d)) + -> Seq Scan on sw_tb_2 (cost=0.00..27.76 rows=1776 width=16) + -> Materialize (cost=0.00..32.25 rows=9 width=16) + -> Seq Scan on sw_tb_1 (cost=0.00..32.20 rows=9 width=16) + Filter: (a = 2) + -> Hash Join (cost=26.65..119148.23 rows=65945 width=32) + Hash Cond: (swtest.sw_tb_2.c = tmp_reuslt."sw_tb_1@d") + -> Materialize (cost=0.00..118341.56 rows=16083 width=32) + -> Nested Loop (cost=0.00..118341.56 rows=16083 width=32) + Join Filter: (((((swtest.sw_tb_1.a + swtest.sw_tb_1.b) = swtest.sw_tb_2.b) OR (swtest.sw_tb_1.a = swtest.sw_tb_2.c)) AND ((swtest.sw_tb_1.b = swtest.sw_tb_2.a) OR (substr((swtest.sw_tb_1.b)::text, 2) = substr((swtest.sw_tb_2.b)::text, 2)))) OR (swtest.sw_tb_1.c = swtest.sw_tb_2.d)) + -> Seq Scan on sw_tb_1 (cost=0.00..27.76 rows=1776 width=16) + -> Materialize (cost=0.00..36.64 rows=1776 width=16) + -> Seq Scan on sw_tb_2 (cost=0.00..27.76 rows=1776 width=16) + -> Hash (cost=16.40..16.40 rows=820 width=4) + -> WorkTable Scan on tmp_reuslt (cost=0.00..16.40 rows=820 width=4) +(22 rows) + +explain select * from sw_tb_3 where exists (select * from sw_tb_1, sw_tb_2 where sw_tb_1.a + sw_tb_2.a = sw_tb_3.a connect by level < 2); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Seq Scan on sw_tb_3 (cost=0.00..57437072471119520.00 rows=888 width=16) + Filter: (SubPlan 2) + SubPlan 2 + -> CTE Scan on tmp_reuslt (cost=32340693958958.68..57212759635253.08 rows=4974413135259 width=0) + Filter: (("sw_tb_1@a" + "sw_tb_2@a") = sw_tb_3.a) + CTE tmp_reuslt + -> StartWith Operator (cost=0.00..32340693958958.68 rows=994882627051776 width=32) + Start With pseudo atts: RUITR + -> Recursive Union (cost=0.00..32340693958958.68 rows=994882627051776 width=32) + -> Nested Loop (cost=0.00..39487.16 rows=3154176 width=32) + -> Seq Scan on sw_tb_1 (cost=0.00..27.76 rows=1776 width=16) + -> Materialize (cost=0.00..36.64 rows=1776 width=16) + -> Seq Scan on sw_tb_2 (cost=0.00..27.76 rows=1776 width=16) + -> Nested Loop (cost=0.00..1244304137843.60 rows=99488262389760 width=32) + -> Nested Loop (cost=0.00..700857939.40 rows=56018165760 width=16) + -> WorkTable Scan on tmp_reuslt (cost=0.00..630835.20 rows=31541760 width=0) + -> Materialize (cost=0.00..36.64 rows=1776 width=16) + -> Seq Scan on sw_tb_1 (cost=0.00..27.76 rows=1776 width=16) + -> Materialize (cost=0.00..36.64 rows=1776 width=16) + -> Seq Scan on sw_tb_2 (cost=0.00..27.76 rows=1776 width=16) +(20 rows) + +drop table sw_tb_1; +drop table sw_tb_2; +drop table sw_tb_3; diff --git a/src/test/regress/expected/sw_icbc.out b/src/test/regress/expected/sw_icbc.out index 99513488d8d06143ed5876f5d25440fa187510a6..3c07167aa793df5e8000bccef52651d54aee74df 100644 --- a/src/test/regress/expected/sw_icbc.out +++ b/src/test/regress/expected/sw_icbc.out @@ -512,7 +512,6 @@ explain (costs off) select * from t1, t2 where t1.id = t2.id start with t1.id = QUERY PLAN ----------------------------------------------------------------------------- CTE Scan on tmp_reuslt - Filter: ("t1@id" = "t2@id") CTE tmp_reuslt -> StartWith Operator Start With pseudo atts: RUITR, array_key_1 @@ -531,7 +530,7 @@ explain (costs off) select * from t1, t2 where t1.id = t2.id start with t1.id = -> WorkTable Scan on tmp_reuslt -> Hash -> Seq Scan on t2 -(20 rows) +(19 rows) explain (costs off) select * from t1 join t2 on t1.id = t2.id start with t1.id = t2.id and t1.id = 1 connect by prior t1.id = t1.pid; QUERY PLAN @@ -561,7 +560,6 @@ explain (costs off) select * from t1, (select * from t2) as test where t1.id = t QUERY PLAN ----------------------------------------------------------------------------- CTE Scan on tmp_reuslt - Filter: ("t1@id" = "test@id") CTE tmp_reuslt -> StartWith Operator Start With pseudo atts: RUITR, array_key_1 @@ -580,7 +578,7 @@ explain (costs off) select * from t1, (select * from t2) as test where t1.id = t -> WorkTable Scan on tmp_reuslt -> Hash -> Seq Scan on t2 -(20 rows) +(19 rows) explain (costs off) select id, (select id from t2 start with t2.id = t1.id connect by t2.id = t1.id limit 1) from t1 where id = 1; ERROR: START WITH CONNECT BY clauses must have at least one prior key. @@ -595,7 +593,17 @@ explain (costs off) select *, sys_connect_by_path(name, '/') from t1 start with ERROR: SYS_CONNECT_BY_PATH function is not allowed here --unsupport case select prior id cc from t1 start with id = 1 connect by prior id = pid; -ERROR: Not Support prior column in TargetList in case swcb. + cc +---- + + 1 + 2 + 1 + 4 + 7 + 4 +(7 rows) + create INCREMENTAL MATERIALIZED view mv as select * from t1 start with id=141 connect by prior id=pid; ERROR: Feature not supported DETAIL: with or start with clause diff --git a/src/test/regress/expected/sw_prior.out b/src/test/regress/expected/sw_prior.out new file mode 100644 index 0000000000000000000000000000000000000000..f77aad3599fdea68958e3cf2849447f1994d39bc --- /dev/null +++ b/src/test/regress/expected/sw_prior.out @@ -0,0 +1,1143 @@ +-- base test +DROP TABLE IF EXISTS table_name; +NOTICE: table "table_name" does not exist, skipping +CREATE TABLE table_name(node1, node2) AS +SELECT 'A1', 'B1' UNION ALL +SELECT 'A1', 'B2' UNION ALL +SELECT 'A2', 'B1' UNION ALL +SELECT 'A2', 'B3' UNION ALL +SELECT 'B1', 'K5' UNION ALL +SELECT 'B1', 'I2' UNION ALL +SELECT 'A3', 'G7' UNION ALL +SELECT 'A3', 'H9' UNION ALL +SELECT 'B2', 'J1' UNION ALL +SELECT 'B2', 'K5' UNION ALL +SELECT 'H9', 'L7' ; +SELECT +CASE LEVEL WHEN 2 THEN PRIOR node1 ELSE node1 END AS node0, +CASE LEVEL WHEN 2 THEN node1 ELSE node2 END AS node1, +CASE LEVEL WHEN 2 THEN node2 END AS node2 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + node0 | node1 | node2 +-------+-------+------- + A1 | B1 | K5 + A1 | B1 | I2 + A1 | B2 | J1 + A1 | B2 | K5 + A2 | B1 | K5 + A2 | B1 | I2 + A2 | B3 | + A3 | G7 | + A3 | H9 | L7 +(9 rows) + +SELECT +CASE LEVEL WHEN 2 THEN PRIOR PRIOR node1 ELSE node1 END AS node0, +CASE LEVEL WHEN 2 THEN node1 ELSE node2 END AS node1, +CASE LEVEL WHEN 2 THEN node2 END AS node2 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; +ERROR: syntax error at or near "node1" +LINE 2: CASE LEVEL WHEN 2 THEN PRIOR PRIOR node1 ELSE node1 END AS n... + ^ +SELECT +CASE LEVEL WHEN 2 THEN PRIOR(PRIOR node1) ELSE node1 END AS node0, +CASE LEVEL WHEN 2 THEN node1 ELSE node2 END AS node1, +CASE LEVEL WHEN 2 THEN node2 END AS node2 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; +ERROR: function prior(text) does not exist +LINE 1: SELECT + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: node0 +SELECT +PRIOR 1 +FROM table_name; +ERROR: syntax error at or near "1" +LINE 2: PRIOR 1 + ^ +SELECT +PRIOR 1 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; +ERROR: syntax error at or near "1" +LINE 2: PRIOR 1 + ^ +SELECT +PRIOR 'test' +FROM table_name; +ERROR: type "prior" does not exist +LINE 2: PRIOR 'test' + ^ +CONTEXT: referenced column: prior +SELECT +PRIOR 'test' +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; +ERROR: type "prior" does not exist +LINE 2: PRIOR 'test' + ^ +CONTEXT: referenced column: prior +SELECT +PRIOR repeat('test') +FROM table_name; +ERROR: syntax error at or near "(" +LINE 2: PRIOR repeat('test') + ^ +SELECT +PRIOR repeat('test') +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; +ERROR: syntax error at or near "(" +LINE 2: PRIOR repeat('test') + ^ +SELECT +PRIOR NULL +FROM table_name; +ERROR: syntax error at or near "NULL" +LINE 2: PRIOR NULL + ^ +SELECT +PRIOR NULL +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; +ERROR: syntax error at or near "NULL" +LINE 2: PRIOR NULL + ^ +-- test about data type +DROP TABLE IF EXISTS test_type_table; +NOTICE: table "test_type_table" does not exist, skipping +CREATE TABLE test_type_table +( + pid int, + id int, + name text, + "int1" tinyint, + "int2" smallint, + "int4" integer, + "int8" bigint, + "float4" float4, + "float8" float8, + "numeric" decimal(20, 6), + "bit5" bit(5), + "boolean" boolean, + "date" date, + "time" time, + "timetz" timetz, + "timestamp" timestamp, + "timestamptz" timestamptz, + "char" char(20), + "varchar" varchar(100), + "blob" blob, + "text" text +); +INSERT INTO test_type_table VALUES +(0, 1, 'top_father', 1, 1, 1, 1, 1.1, 1.1, 1.1, b'00001', true, '2024-01-01', '00:00:01', '00:00:01', '2024-01-01 00:00:01', '2024-01-01 00:00:01', 'top_father', 'top_father', '0A', 'top_father'), +(1, 2, 'second_father1', 2, 2, 2, 2, 1.2, 1.2, 1.2, b'00010', false, '2024-01-02', '00:00:02', '00:00:02', '2024-01-02 00:00:02', '2024-01-02 00:00:02', 'second_father1', 'second_father1', '0B', 'second_father1'), +(1, 3, 'second_father2', 3, 3, 3, 3, 1.3, 1.3, 1.3, b'00100', true, '2024-01-03', '00:00:03', '00:00:03', '2024-01-03 00:00:03', '2024-01-03 00:00:03', 'second_father2', 'second_father2', '0C', 'second_father2'), +(2, 4, 'third_father1', 4, 4, 4, 4, 1.4, 1.4, 1.4, b'01000', false, '2024-01-04', '00:00:04', '00:00:04', '2024-01-04 00:00:04', '2024-01-04 00:00:04', 'third_father1', 'third_father1', '0D', 'third_father1'), +(3, 5, 'third_father2', 5, 5, 5, 5, 1.5, 1.5, 1.5, b'10000', true, '2024-01-05', '00:00:05', '00:00:05', '2024-01-05 00:00:05', '2024-01-05 00:00:05', 'third_father2', 'third_father2', '0E', 'third_father2'); +SELECT +PRIOR name AS father_name, +PRIOR "int1" AS father_int1, +name AS current_name, +"int1" AS current_int1 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int1 | current_name | current_int1 +----------------+-------------+----------------+-------------- + | | top_father | 1 + top_father | 1 | second_father1 | 2 + second_father1 | 2 | third_father1 | 4 + top_father | 1 | second_father2 | 3 + second_father2 | 3 | third_father2 | 5 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "int2" AS father_int2, +name AS current_name, +"int2" AS current_int2 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int2 | current_name | current_int2 +----------------+-------------+----------------+-------------- + | | top_father | 1 + top_father | 1 | second_father1 | 2 + second_father1 | 2 | third_father1 | 4 + top_father | 1 | second_father2 | 3 + second_father2 | 3 | third_father2 | 5 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "int4" AS father_int4, +name AS current_name, +"int4" AS current_int4 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int4 | current_name | current_int4 +----------------+-------------+----------------+-------------- + | | top_father | 1 + top_father | 1 | second_father1 | 2 + second_father1 | 2 | third_father1 | 4 + top_father | 1 | second_father2 | 3 + second_father2 | 3 | third_father2 | 5 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "int8" AS father_int8, +name AS current_name, +"int8" AS current_int8 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int8 | current_name | current_int8 +----------------+-------------+----------------+-------------- + | | top_father | 1 + top_father | 1 | second_father1 | 2 + second_father1 | 2 | third_father1 | 4 + top_father | 1 | second_father2 | 3 + second_father2 | 3 | third_father2 | 5 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "float4" AS father_float4, +name AS current_name, +"float4" AS current_float4 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_float4 | current_name | current_float4 +----------------+---------------+----------------+---------------- + | | top_father | 1.1 + top_father | 1.1 | second_father1 | 1.2 + second_father1 | 1.2 | third_father1 | 1.4 + top_father | 1.1 | second_father2 | 1.3 + second_father2 | 1.3 | third_father2 | 1.5 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "float8" AS father_float8, +name AS current_name, +"float8" AS current_float8 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_float8 | current_name | current_float8 +----------------+---------------+----------------+---------------- + | | top_father | 1.1 + top_father | 1.1 | second_father1 | 1.2 + second_father1 | 1.2 | third_father1 | 1.4 + top_father | 1.1 | second_father2 | 1.3 + second_father2 | 1.3 | third_father2 | 1.5 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "numeric" AS father_numeric, +name AS current_name, +"numeric" AS current_numeric +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_numeric | current_name | current_numeric +----------------+----------------+----------------+----------------- + | | top_father | 1.100000 + top_father | 1.100000 | second_father1 | 1.200000 + second_father1 | 1.200000 | third_father1 | 1.400000 + top_father | 1.100000 | second_father2 | 1.300000 + second_father2 | 1.300000 | third_father2 | 1.500000 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "bit5" AS father_bit5, +name AS current_name, +"bit5" AS current_bit5 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; +ERROR: unspported type for attname:bit5 (typid:1560 typname:bit) +SELECT +PRIOR name AS father_name, +PRIOR "boolean" AS father_boolean, +name AS current_name, +"boolean" AS current_boolean +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_boolean | current_name | current_boolean +----------------+----------------+----------------+----------------- + | | top_father | t + top_father | t | second_father1 | f + second_father1 | f | third_father1 | f + top_father | t | second_father2 | t + second_father2 | t | third_father2 | t +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "date" AS father_date, +name AS current_name, +"date" AS current_date +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_date | current_name | current_date +----------------+--------------------------+----------------+-------------------------- + | | top_father | Mon Jan 01 00:00:00 2024 + top_father | Mon Jan 01 00:00:00 2024 | second_father1 | Tue Jan 02 00:00:00 2024 + second_father1 | Tue Jan 02 00:00:00 2024 | third_father1 | Thu Jan 04 00:00:00 2024 + top_father | Mon Jan 01 00:00:00 2024 | second_father2 | Wed Jan 03 00:00:00 2024 + second_father2 | Wed Jan 03 00:00:00 2024 | third_father2 | Fri Jan 05 00:00:00 2024 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "time" AS father_time, +name AS current_name, +"time" AS current_time +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_time | current_name | current_time +----------------+-------------+----------------+-------------- + | | top_father | 00:00:01 + top_father | 00:00:01 | second_father1 | 00:00:02 + second_father1 | 00:00:02 | third_father1 | 00:00:04 + top_father | 00:00:01 | second_father2 | 00:00:03 + second_father2 | 00:00:03 | third_father2 | 00:00:05 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "timetz" AS father_timetz, +name AS current_name, +"timetz" AS current_timetz +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_timetz | current_name | current_timetz +----------------+---------------+----------------+---------------- + | | top_father | 00:00:01-07 + top_father | 00:00:01-07 | second_father1 | 00:00:02-07 + second_father1 | 00:00:02-07 | third_father1 | 00:00:04-07 + top_father | 00:00:01-07 | second_father2 | 00:00:03-07 + second_father2 | 00:00:03-07 | third_father2 | 00:00:05-07 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "timestamp" AS father_timestamp, +name AS current_name, +"timestamp" AS current_timestamp +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_timestamp | current_name | current_timestamp +----------------+--------------------------+----------------+-------------------------- + | | top_father | Mon Jan 01 00:00:01 2024 + top_father | Mon Jan 01 00:00:01 2024 | second_father1 | Tue Jan 02 00:00:02 2024 + second_father1 | Tue Jan 02 00:00:02 2024 | third_father1 | Thu Jan 04 00:00:04 2024 + top_father | Mon Jan 01 00:00:01 2024 | second_father2 | Wed Jan 03 00:00:03 2024 + second_father2 | Wed Jan 03 00:00:03 2024 | third_father2 | Fri Jan 05 00:00:05 2024 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "timestamptz" AS father_timestamptz, +name AS current_name, +"timestamptz" AS current_timestamptz +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_timestamptz | current_name | current_timestamptz +----------------+------------------------------+----------------+------------------------------ + | | top_father | Mon Jan 01 00:00:01 2024 PST + top_father | Mon Jan 01 00:00:01 2024 PST | second_father1 | Tue Jan 02 00:00:02 2024 PST + second_father1 | Tue Jan 02 00:00:02 2024 PST | third_father1 | Thu Jan 04 00:00:04 2024 PST + top_father | Mon Jan 01 00:00:01 2024 PST | second_father2 | Wed Jan 03 00:00:03 2024 PST + second_father2 | Wed Jan 03 00:00:03 2024 PST | third_father2 | Fri Jan 05 00:00:05 2024 PST +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "char" AS father_char, +name AS current_name, +"char" AS current_char +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_char | current_name | current_char +----------------+----------------------+----------------+---------------------- + | | top_father | top_father + top_father | top_father | second_father1 | second_father1 + second_father1 | second_father1 | third_father1 | third_father1 + top_father | top_father | second_father2 | second_father2 + second_father2 | second_father2 | third_father2 | third_father2 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "varchar" AS father_varchar, +name AS current_name, +"varchar" AS current_varchar +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_varchar | current_name | current_varchar +----------------+----------------+----------------+----------------- + | | top_father | top_father + top_father | top_father | second_father1 | second_father1 + second_father1 | second_father1 | third_father1 | third_father1 + top_father | top_father | second_father2 | second_father2 + second_father2 | second_father2 | third_father2 | third_father2 +(5 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "blob" AS father_blob, +name AS current_name, +"blob" AS current_blob +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; +ERROR: unspported type for attname:blob (typid:88 typname:blob) +SELECT +PRIOR name AS father_name, +PRIOR "text" AS father_text, +name AS current_name, +"text" AS current_text +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_text | current_name | current_text +----------------+----------------+----------------+---------------- + | | top_father | top_father + top_father | top_father | second_father1 | second_father1 + second_father1 | second_father1 | third_father1 | third_father1 + top_father | top_father | second_father2 | second_father2 + second_father2 | second_father2 | third_father2 | third_father2 +(5 rows) + +-- test about WHERE clause +SELECT +PRIOR name AS father_name, +PRIOR "int1" AS father_int1, +name AS current_name, +"int1" AS current_int1 +FROM test_type_table WHERE PRIOR "int1" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int1 | current_name | current_int1 +----------------+-------------+---------------+-------------- + second_father1 | 2 | third_father1 | 4 + second_father2 | 3 | third_father2 | 5 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "int2" AS father_int2, +name AS current_name, +"int2" AS current_int2 +FROM test_type_table WHERE PRIOR "int2" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int2 | current_name | current_int2 +----------------+-------------+---------------+-------------- + second_father1 | 2 | third_father1 | 4 + second_father2 | 3 | third_father2 | 5 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "int4" AS father_int4, +name AS current_name, +"int4" AS current_int4 +FROM test_type_table WHERE PRIOR "int4" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int4 | current_name | current_int4 +----------------+-------------+---------------+-------------- + second_father1 | 2 | third_father1 | 4 + second_father2 | 3 | third_father2 | 5 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "int8" AS father_int8, +name AS current_name, +"int8" AS current_int8 +FROM test_type_table WHERE PRIOR "int8" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_int8 | current_name | current_int8 +----------------+-------------+---------------+-------------- + second_father1 | 2 | third_father1 | 4 + second_father2 | 3 | third_father2 | 5 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "float4" AS father_float4, +name AS current_name, +"float4" AS current_float4 +FROM test_type_table WHERE PRIOR "float4" > 1.1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_float4 | current_name | current_float4 +----------------+---------------+----------------+---------------- + top_father | 1.1 | second_father1 | 1.2 + second_father1 | 1.2 | third_father1 | 1.4 + top_father | 1.1 | second_father2 | 1.3 + second_father2 | 1.3 | third_father2 | 1.5 +(4 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "float8" AS father_float8, +name AS current_name, +"float8" AS current_float8 +FROM test_type_table WHERE PRIOR "float8" > 1.1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_float8 | current_name | current_float8 +----------------+---------------+---------------+---------------- + second_father1 | 1.2 | third_father1 | 1.4 + second_father2 | 1.3 | third_father2 | 1.5 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "numeric" AS father_numeric, +name AS current_name, +"numeric" AS current_numeric +FROM test_type_table WHERE PRIOR "numeric" > 1.1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_numeric | current_name | current_numeric +----------------+----------------+---------------+----------------- + second_father1 | 1.200000 | third_father1 | 1.400000 + second_father2 | 1.300000 | third_father2 | 1.500000 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "bit5" AS father_bit5, +name AS current_name, +"bit5" AS current_bit5 +FROM test_type_table WHERE "bit5" > b'00001' +START WITH id = 1 +CONNECT BY PRIOR id = pid; +ERROR: unspported type for attname:bit5 (typid:1560 typname:bit) +SELECT +PRIOR name AS father_name, +PRIOR "boolean" AS father_boolean, +name AS current_name, +"boolean" AS current_boolean +FROM test_type_table WHERE PRIOR "boolean" +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_boolean | current_name | current_boolean +----------------+----------------+----------------+----------------- + top_father | t | second_father1 | f + top_father | t | second_father2 | t + second_father2 | t | third_father2 | t +(3 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "date" AS father_date, +name AS current_name, +"date" AS current_date +FROM test_type_table WHERE PRIOR "date" > '2024-01-01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_date | current_name | current_date +----------------+--------------------------+---------------+-------------------------- + second_father1 | Tue Jan 02 00:00:00 2024 | third_father1 | Thu Jan 04 00:00:00 2024 + second_father2 | Wed Jan 03 00:00:00 2024 | third_father2 | Fri Jan 05 00:00:00 2024 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "time" AS father_time, +name AS current_name, +"time" AS current_time +FROM test_type_table WHERE PRIOR "time" > '00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_time | current_name | current_time +----------------+-------------+---------------+-------------- + second_father1 | 00:00:02 | third_father1 | 00:00:04 + second_father2 | 00:00:03 | third_father2 | 00:00:05 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "timetz" AS father_timetz, +name AS current_name, +"timetz" AS current_timetz +FROM test_type_table WHERE PRIOR "timetz" > '00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_timetz | current_name | current_timetz +----------------+---------------+---------------+---------------- + second_father1 | 00:00:02-07 | third_father1 | 00:00:04-07 + second_father2 | 00:00:03-07 | third_father2 | 00:00:05-07 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "timestamp" AS father_timestamp, +name AS current_name, +"timestamp" AS current_timestamp +FROM test_type_table WHERE PRIOR "timestamp" > '2024-01-01 00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_timestamp | current_name | current_timestamp +----------------+--------------------------+---------------+-------------------------- + second_father1 | Tue Jan 02 00:00:02 2024 | third_father1 | Thu Jan 04 00:00:04 2024 + second_father2 | Wed Jan 03 00:00:03 2024 | third_father2 | Fri Jan 05 00:00:05 2024 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "timestamptz" AS father_timestamptz, +name AS current_name, +"timestamptz" AS current_timestamptz +FROM test_type_table WHERE PRIOR "timestamptz" > '2024-01-01 00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_timestamptz | current_name | current_timestamptz +----------------+------------------------------+---------------+------------------------------ + second_father1 | Tue Jan 02 00:00:02 2024 PST | third_father1 | Thu Jan 04 00:00:04 2024 PST + second_father2 | Wed Jan 03 00:00:03 2024 PST | third_father2 | Fri Jan 05 00:00:05 2024 PST +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "char" AS father_char, +name AS current_name, +"char" AS current_char +FROM test_type_table WHERE PRIOR "char" LIKE '%second%' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_char | current_name | current_char +----------------+----------------------+---------------+---------------------- + second_father1 | second_father1 | third_father1 | third_father1 + second_father2 | second_father2 | third_father2 | third_father2 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "varchar" AS father_varchar, +name AS current_name, +"varchar" AS current_varchar +FROM test_type_table WHERE PRIOR "varchar" LIKE '%second%' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_varchar | current_name | current_varchar +----------------+----------------+---------------+----------------- + second_father1 | second_father1 | third_father1 | third_father1 + second_father2 | second_father2 | third_father2 | third_father2 +(2 rows) + +SELECT +PRIOR name AS father_name, +PRIOR "blob" AS father_blob, +name AS current_name, +"blob" AS current_blob +FROM test_type_table WHERE PRIOR "blob" > '0A' +START WITH id = 1 +CONNECT BY PRIOR id = pid; +ERROR: unspported type for attname:blob (typid:88 typname:blob) +SELECT +PRIOR name AS father_name, +PRIOR "text" AS father_text, +name AS current_name, +"text" AS current_text +FROM test_type_table WHERE PRIOR "text" LIKE '%second%' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + father_name | father_text | current_name | current_text +----------------+----------------+---------------+--------------- + second_father1 | second_father1 | third_father1 | third_father1 + second_father2 | second_father2 | third_father2 | third_father2 +(2 rows) + +-- test about GROUP BY clause +SELECT +PRIOR "int1", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int1"; + int1 | count +------+------- + 1 | 2 + 3 | 1 + | 1 + 2 | 1 +(4 rows) + +SELECT +PRIOR "int2", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int2"; + int2 | count +------+------- + 1 | 2 + 3 | 1 + | 1 + 2 | 1 +(4 rows) + +SELECT +PRIOR "int4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int4"; + int4 | count +------+------- + 1 | 2 + 3 | 1 + | 1 + 2 | 1 +(4 rows) + +SELECT +PRIOR "int8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int8"; + int8 | count +------+------- + 1 | 2 + 3 | 1 + | 1 + 2 | 1 +(4 rows) + +SELECT +PRIOR "float4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float4"; + float4 | count +--------+------- + | 1 + 1.1 | 2 + 1.2 | 1 + 1.3 | 1 +(4 rows) + +SELECT +PRIOR "float8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float8"; + float8 | count +--------+------- + 1.1 | 2 + | 1 + 1.3 | 1 + 1.2 | 1 +(4 rows) + +SELECT +PRIOR "numeric", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "numeric"; + numeric | count +----------+------- + 1.200000 | 1 + | 1 + 1.100000 | 2 + 1.300000 | 1 +(4 rows) + +SELECT +PRIOR "bit5", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "bit5"; +ERROR: unspported type for attname:bit5 (typid:1560 typname:bit) +SELECT +PRIOR "boolean", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "boolean"; + boolean | count +---------+------- + t | 3 + f | 1 + | 1 +(3 rows) + +SELECT +PRIOR "date", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "date"; + date | count +--------------------------+------- + Wed Jan 03 00:00:00 2024 | 1 + | 1 + Tue Jan 02 00:00:00 2024 | 1 + Mon Jan 01 00:00:00 2024 | 2 +(4 rows) + +SELECT +PRIOR "time", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "time"; + time | count +----------+------- + 00:00:03 | 1 + 00:00:02 | 1 + | 1 + 00:00:01 | 2 +(4 rows) + +SELECT +PRIOR "timetz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timetz"; + timetz | count +-------------+------- + 00:00:01-07 | 2 + | 1 + 00:00:02-07 | 1 + 00:00:03-07 | 1 +(4 rows) + +SELECT +PRIOR "timestamp", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamp"; + timestamp | count +--------------------------+------- + | 1 + Tue Jan 02 00:00:02 2024 | 1 + Wed Jan 03 00:00:03 2024 | 1 + Mon Jan 01 00:00:01 2024 | 2 +(4 rows) + +SELECT +PRIOR "timestamptz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamptz"; + timestamptz | count +------------------------------+------- + Tue Jan 02 00:00:02 2024 PST | 1 + Mon Jan 01 00:00:01 2024 PST | 2 + | 1 + Wed Jan 03 00:00:03 2024 PST | 1 +(4 rows) + +SELECT +PRIOR "char", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "char"; + char | count +----------------------+------- + second_father2 | 1 + | 1 + top_father | 2 + second_father1 | 1 +(4 rows) + +SELECT +PRIOR "varchar", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "varchar"; + varchar | count +----------------+------- + second_father2 | 1 + | 1 + top_father | 2 + second_father1 | 1 +(4 rows) + +SELECT +PRIOR "blob", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "blob"; +ERROR: unspported type for attname:blob (typid:88 typname:blob) +SELECT +PRIOR "text", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "text"; + text | count +----------------+------- + second_father2 | 1 + | 1 + top_father | 2 + second_father1 | 1 +(4 rows) + +-- test about HAVING clause +SELECT +PRIOR "int1", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int1" HAVING PRIOR "int1" > 1; + int1 | count +------+------- + 3 | 1 + 2 | 1 +(2 rows) + +SELECT +PRIOR "int2", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int2" HAVING PRIOR "int2" > 1; + int2 | count +------+------- + 3 | 1 + 2 | 1 +(2 rows) + +SELECT +PRIOR "int4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int4" HAVING PRIOR "int4" > 1; + int4 | count +------+------- + 3 | 1 + 2 | 1 +(2 rows) + +SELECT +PRIOR "int8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int8" HAVING PRIOR "int8" > 1; + int8 | count +------+------- + 3 | 1 + 2 | 1 +(2 rows) + +SELECT +PRIOR "float4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float4" HAVING PRIOR "float4" > 1.1; + float4 | count +--------+------- + 1.2 | 1 + 1.1 | 2 + 1.3 | 1 +(3 rows) + +SELECT +PRIOR "float8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float8" HAVING PRIOR "float8" > 1.1; + float8 | count +--------+------- + 1.3 | 1 + 1.2 | 1 +(2 rows) + +SELECT +PRIOR "numeric", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "numeric" HAVING PRIOR "numeric" > 1.1; + numeric | count +----------+------- + 1.300000 | 1 + 1.200000 | 1 +(2 rows) + +SELECT +PRIOR "bit5", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "bit5" HAVING PRIOR "bit5" > b'00001'; +ERROR: unspported type for attname:bit5 (typid:1560 typname:bit) +SELECT +PRIOR "boolean", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "boolean" HAVING PRIOR "boolean"; + boolean | count +---------+------- + t | 3 +(1 row) + +SELECT +PRIOR "date", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "date" HAVING PRIOR "date" > '2024-01-01'; + date | count +--------------------------+------- + Wed Jan 03 00:00:00 2024 | 1 + Tue Jan 02 00:00:00 2024 | 1 +(2 rows) + +SELECT +PRIOR "time", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "time" HAVING PRIOR "time" > '00:00:01'; + time | count +----------+------- + 00:00:03 | 1 + 00:00:02 | 1 +(2 rows) + +SELECT +PRIOR "timetz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timetz" HAVING PRIOR "timetz" > '00:00:01'; + timetz | count +-------------+------- + 00:00:02-07 | 1 + 00:00:03-07 | 1 +(2 rows) + +SELECT +PRIOR "timestamp", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamp" HAVING PRIOR "timestamp" > '2024-01-01 00:00:01'; + timestamp | count +--------------------------+------- + Wed Jan 03 00:00:03 2024 | 1 + Tue Jan 02 00:00:02 2024 | 1 +(2 rows) + +SELECT +PRIOR "timestamptz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamptz" HAVING PRIOR "timestamptz" > '2024-01-01 00:00:01'; + timestamptz | count +------------------------------+------- + Wed Jan 03 00:00:03 2024 PST | 1 + Tue Jan 02 00:00:02 2024 PST | 1 +(2 rows) + +SELECT +PRIOR "char", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "char" HAVING PRIOR "char" LIKE '%second%'; + char | count +----------------------+------- + second_father1 | 1 + second_father2 | 1 +(2 rows) + +SELECT +PRIOR "varchar", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "varchar" HAVING PRIOR "varchar" LIKE '%second%'; + varchar | count +----------------+------- + second_father1 | 1 + second_father2 | 1 +(2 rows) + +SELECT +PRIOR "blob", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "blob" HAVING PRIOR "blob" > '0A'; +ERROR: unspported type for attname:blob (typid:88 typname:blob) +SELECT +PRIOR "text", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "text" HAVING PRIOR "text" LIKE '%second%'; + text | count +----------------+------- + second_father1 | 1 + second_father2 | 1 +(2 rows) + diff --git a/src/test/regress/expected/tablesample_3.out b/src/test/regress/expected/tablesample_3.out index fa6cff64ce7277a3eba6d63f315f3f893fd90675..a592ef2b04ecdacddc5ee4f023d2cf8a8f43afca 100755 --- a/src/test/regress/expected/tablesample_3.out +++ b/src/test/regress/expected/tablesample_3.out @@ -20,16 +20,15 @@ select count(*) from ((select * from test_tablesample tablesample SYSTEM(20) REP (1 row) explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------------- - Hash Anti Join - Hash Cond: (test_tablesample.id = test_tablesample2.id) + QUERY PLAN +--------------------------------------------------------------------------------------- + Nested Loop Anti Join + Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) - -> Hash - -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) -(7 rows) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) + -> Sample Scan on test_tablesample2 + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) +(6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; id | name | salary | id | name | salary @@ -38,19 +37,15 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_hashjoin to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------------- - Merge Anti Join - Merge Cond: (test_tablesample.id = test_tablesample2.id) - -> Sort - Sort Key: test_tablesample.id - -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) - -> Sort - Sort Key: test_tablesample2.id - -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) -(10 rows) + QUERY PLAN +--------------------------------------------------------------------------------------- + Nested Loop Anti Join + Join Filter: (test_tablesample.id = test_tablesample2.id) + -> Sample Scan on test_tablesample + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) + -> Sample Scan on test_tablesample2 + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) +(6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; id | name | salary | id | name | salary @@ -59,16 +54,15 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_mergejoin to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------- Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) - -> Materialize - -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) -(7 rows) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) + -> Sample Scan on test_tablesample2 + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) +(6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; id | name | salary | id | name | salary @@ -77,14 +71,14 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_material to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------- Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -93,14 +87,14 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j (0 rows) explain (costs off) select * from test_tablesample tablesample SYSTEM(50) REPEATABLE (200) left join test_tablesample2 tablesample SYSTEM(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------ Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: system (50::real) REPEATABLE (200::double precision) + Sampling: system (50::double precision) REPEATABLE (200::double precision) -> Sample Scan on test_tablesample2 - Sampling: system (50::real) REPEATABLE (200::double precision) + Sampling: system (50::double precision) REPEATABLE (200::double precision) (6 rows) select * from test_tablesample tablesample SYSTEM(50) REPEATABLE (200) left join test_tablesample2 tablesample SYSTEM(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -130,15 +124,15 @@ select count(*) from ((select * from test_tablesample tablesample SYSTEM(30) REP (1 row) explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------- Row Adapter -> Vector Nest Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> VecSample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> VecSample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (7 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -148,15 +142,15 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_hashjoin to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------- Row Adapter -> Vector Nest Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> VecSample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> VecSample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (7 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -166,15 +160,15 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_mergejoin to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------- Row Adapter -> Vector Nest Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> VecSample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> VecSample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (7 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -184,15 +178,15 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_material to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------- Row Adapter -> Vector Nest Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> VecSample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> VecSample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (7 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -201,15 +195,15 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j (0 rows) explain (costs off) select * from test_tablesample tablesample SYSTEM(50) REPEATABLE (200) left join test_tablesample2 tablesample SYSTEM(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------ Row Adapter -> Vector Nest Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> VecSample Scan on test_tablesample - Sampling: system (50::real) REPEATABLE (200::double precision) + Sampling: system (50::double precision) REPEATABLE (200::double precision) -> VecSample Scan on test_tablesample2 - Sampling: system (50::real) REPEATABLE (200::double precision) + Sampling: system (50::double precision) REPEATABLE (200::double precision) (7 rows) select * from test_tablesample tablesample SYSTEM(50) REPEATABLE (200) left join test_tablesample2 tablesample SYSTEM(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -239,14 +233,14 @@ select count(*) from ((select * from test_tablesample tablesample SYSTEM(70) REP (1 row) explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------- Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -256,14 +250,14 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_hashjoin to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------- Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -273,14 +267,14 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_mergejoin to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------- Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -290,14 +284,14 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j set enable_material to off; explain (costs off) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------- Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) -> Sample Scan on test_tablesample2 - Sampling: bernoulli (50::real) REPEATABLE (200::double precision) + Sampling: bernoulli (50::double precision) REPEATABLE (200::double precision) (6 rows) select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left join test_tablesample2 tablesample BERNOULLI(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; @@ -306,14 +300,14 @@ select * from test_tablesample tablesample BERNOULLI(50) REPEATABLE (200) left j (0 rows) explain (costs off) select * from test_tablesample tablesample SYSTEM(50) REPEATABLE (200) left join test_tablesample2 tablesample SYSTEM(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; - QUERY PLAN ------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------ Nested Loop Anti Join Join Filter: (test_tablesample.id = test_tablesample2.id) -> Sample Scan on test_tablesample - Sampling: system (50::real) REPEATABLE (200::double precision) + Sampling: system (50::double precision) REPEATABLE (200::double precision) -> Sample Scan on test_tablesample2 - Sampling: system (50::real) REPEATABLE (200::double precision) + Sampling: system (50::double precision) REPEATABLE (200::double precision) (6 rows) select * from test_tablesample tablesample SYSTEM(50) REPEATABLE (200) left join test_tablesample2 tablesample SYSTEM(50) REPEATABLE (200) on test_tablesample.id=test_tablesample2.id where test_tablesample2.id is NULL; diff --git a/src/test/regress/expected/tablesample_4.out b/src/test/regress/expected/tablesample_4.out new file mode 100644 index 0000000000000000000000000000000000000000..54b330d6c3fe018dd5dc1105acb2d5383e741810 --- /dev/null +++ b/src/test/regress/expected/tablesample_4.out @@ -0,0 +1,458 @@ +create schema tablesample_schema5; +set current_schema = tablesample_schema5; +-- 创建普通表 +CREATE TABLE test ( + id int PRIMARY KEY, + some_timestamp timestamptz, + some_text text +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test" +-- 插入数据 +INSERT INTO test (id, some_timestamp, some_text) + SELECT + i, + now() - random() * '1 year'::INTERVAL, + 'depesz #' || i + FROM + generate_series(1,100) i; +-- 分析表的块(页)数 +analyze test; +-- 测试SAMPLE子句 +SELECT count(*) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 100 +(1 row) + +SELECT avg(id) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (1); + avg +--------------------- + 50.5000000000000000 +(1 row) + +SELECT sum(id) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (1); + sum +------ + 5050 +(1 row) + +-- 测试SAMPLE BLOCK子句 +SELECT count(*) FROM test tablesample system (99.9) REPEATABLE(1); + count +------- + 100 +(1 row) + +SELECT avg(id) FROM test tablesample system (99.9) REPEATABLE (1); + avg +--------------------- + 50.5000000000000000 +(1 row) + +SELECT sum(id) FROM test tablesample system (99.9) REPEATABLE (1); + sum +------ + 5050 +(1 row) + +-- 添加其他过滤条件 +SELECT count(*) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (105) limit 5; + count +------- + 100 +(1 row) + +SELECT count(*) FROM test tablesample system ( 99.9 ) REPEATABLE (105) where id < 5; + count +------- + 4 +(1 row) + +SELECT count(*) FROM test tablesample system ( 99.9 ) REPEATABLE (105) limit 5; + count +------- + 100 +(1 row) + + +-- 分区表 +--- 一级分区表 +create table part_list_t1( +id number, +name varchar2(20), +age int) +partition by list(age)( +partition age_10 values(10) , +partition age_20 values(20), +partition age_default values(default)); + +insert into part_list_t1 values (1,'aa',10); +insert into part_list_t1 values (2,'bb',10); +insert into part_list_t1 values (3,'cc',20); +insert into part_list_t1 values (4,'dd',20); +insert into part_list_t1 values (5,'ee',20); +insert into part_list_t1 values (6,'ff',30); +insert into part_list_t1 values (7,'gg',100); +insert into part_list_t1 values (8,'hh',110); + +analyze part_list_t1; + +select count(*) from part_list_t1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 8 +(1 row) + +select count(*) from part_list_t1 tablesample bernoulli ( 99.9 ) REPEATABLE (1) where id > 5; + count +------- + 3 +(1 row) + +select count(*) from part_list_t1 partition (age_10) tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 2 +(1 row) + +select count(*) from part_list_t1 partition for (20) tablesample system ( 99.9 ) REPEATABLE (1); + count +------- + 3 +(1 row) + + +--- 二级分区表 +create table pt_range_hash_test( + pid number(10), + pname varchar2(30), + sex varchar2(10), + create_date date +) partition by range(create_date) + subpartition by hash(pid) subpartitions 4( + partition p1 values less than(to_date('2020-01-01', 'YYYY-MM-DD')) , + partition p2 values less than(to_date('2021-01-01', 'YYYY-MM-DD')) , + partition p3 values less than(to_date('2022-01-01', 'YYYY-MM-DD')) , + partition p4 values less than(maxvalue) + ); + +insert into pt_range_hash_test(pid, pname, sex, create_date) values(1, '瑶瑶', 'WOMAN', to_date('2018-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(2, '壮壮', 'MAN', to_date('2019-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(3, '晴晴', 'WOMAN', to_date('2020-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(4, '琳琳', 'WOMAN', to_date('2020-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(5, '强强', 'MAN', to_date('2021-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(6, '团团', 'WOMAN', to_date('2022-01-01', 'YYYY-MM-DD')); + +analyze pt_range_hash_test; + +select count(*) from pt_range_hash_test tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 6 +(1 row) + +select count(*) from pt_range_hash_test tablesample bernoulli ( 99.9 ) REPEATABLE (1) where pid < 4; + count +------- + 3 +(1 row) + +select count(*) from pt_range_hash_test partition (P2) tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 2 +(1 row) + +select count(*) from pt_range_hash_test subpartition for(to_date('2020-01-01', 'YYYY-MM-DD'),3) tablesample system ( 99.9 ) REPEATABLE (1); + count +------- + 1 +(1 row) + + +-- 物化视图 +CREATE TABLE base_table +( + base_table_id INTEGER, + base_table_field NUMERIC(10,4) +); + +insert into base_table values(1,2); +insert into base_table values(3,4); +insert into base_table values(5,6); + +CREATE MATERIALIZED VIEW master_view1 AS + SELECT + base_table_id AS id, + base_table_field AS field + FROM base_table; + +analyze base_table; +analyze master_view1; + + +SELECT count(*) FROM master_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 3 +(1 row) + +SELECT avg(id) FROM master_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + avg +-------------------- + 3.0000000000000000 +(1 row) + +SELECT sum(id) FROM master_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + sum +----- + 9 +(1 row) + + +SELECT count(*) FROM master_view1 tablesample system (99.9) REPEATABLE (1); + count +------- + 3 +(1 row) + +SELECT avg(id) FROM master_view1 tablesample system (99.9) REPEATABLE (1); + avg +-------------------- + 3.0000000000000000 +(1 row) + +SELECT sum(id) FROM master_view1 tablesample system (99.9) REPEATABLE (1); + sum +----- + 9 +(1 row) + + +-- 普通视图 +CREATE OR REPLACE VIEW master_view2 AS + SELECT + base_table_id AS id, + base_table_field AS field + FROM base_table; + +SELECT count(*) FROM master_view2 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 3 +(1 row) + +SELECT count(*) FROM master_view2 tablesample system (99.9) REPEATABLE (1); + count +------- + 3 +(1 row) + + +CREATE OR REPLACE VIEW dependent_view1 AS + SELECT + id AS dependent_id, + field AS dependent_field + FROM master_view2; + +SELECT count(*) FROM dependent_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + count +------- + 3 +(1 row) + +SELECT count(*) FROM dependent_view1 tablesample system (99.9) REPEATABLE (1); + count +------- + 3 +(1 row) + + +-- 连接视图 +CREATE OR REPLACE VIEW join_view1 AS + SELECT + a.id AS join_id, + base_table_field AS join_field + FROM test a join base_table b on a.id = b.base_table_id; + +explain (costs off) SELECT count(*) FROM join_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + QUERY PLAN +--------------------------------------------------------------- + Aggregate + -> Merge Join + Merge Cond: (a.id = b.base_table_id) + -> Index Only Scan using test_pkey on test a + -> Sort + Sort Key: b.base_table_id + -> Sample Scan on base_table b + Sampling: bernoulli (99.9) REPEATABLE (1) +(8 rows) + +SELECT count(*) FROM join_view1 tablesample system (99.9); + count +------- + 3 +(1 row) + + +CREATE OR REPLACE VIEW join_view1 AS + SELECT + a.id AS join_id, + base_table_field AS join_field + FROM base_table b join test a on b.base_table_id = a.id; + +explain (costs off) SELECT count(*) FROM join_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + QUERY PLAN +--------------------------------------------------------------- + Aggregate + -> Merge Join + Merge Cond: (a.id = b.base_table_id) + -> Index Only Scan using test_pkey on test a + -> Sort + Sort Key: b.base_table_id + -> Sample Scan on base_table b + Sampling: bernoulli (99.9) REPEATABLE (1) +(8 rows) + +SELECT count(*) FROM join_view1 tablesample system (99.9); + count +------- + 3 +(1 row) + + +CREATE OR REPLACE VIEW join_view2 AS + SELECT + b.base_table_id AS nest_join_id, + join_field AS nest_join_field + FROM join_view1 a join base_table b on a.join_id = b.base_table_id; + +explain (costs off) SELECT count(*) FROM join_view2 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +ERROR: Cannot sample a join view without a key-preserved table +SELECT count(*) FROM join_view2 tablesample system (99.9); +ERROR: Cannot sample a join view without a key-preserved table + +CREATE OR REPLACE VIEW join_view2 AS + SELECT + b.id AS nest_join_id, + join_field AS nest_join_field + FROM join_view1 a join test b on a.join_id = b.id; + +explain (costs off) SELECT count(*) FROM join_view2 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + QUERY PLAN +--------------------------------------------------------------------- + Aggregate + -> Merge Join + Merge Cond: (b.base_table_id = b.id) + -> Merge Join + Merge Cond: (a.id = b.base_table_id) + -> Index Only Scan using test_pkey on test a + -> Sort + Sort Key: b.base_table_id + -> Sample Scan on base_table b + Sampling: bernoulli (99.9) REPEATABLE (1) + -> Index Only Scan using test_pkey on test b +(11 rows) + +SELECT count(*) FROM join_view2 tablesample system (99.9) REPEATABLE (1); + count +------- + 3 +(1 row) + + +CREATE TABLE base_table2 +( + base_table_id INTEGER, + base_table_field NUMERIC(10,4) +); + +insert into base_table2 values(1,1); +insert into base_table2 values(2,2); +insert into base_table2 values(3,3); + +analyze base_table2; + +CREATE OR REPLACE VIEW join_view3 AS + SELECT + a.base_table_id AS id, + b.some_text AS some_text, + c.base_table_field AS field + FROM base_table a join test b on a.base_table_id = b.id + join base_table2 c on a.base_table_id = c.base_table_id; + +explain (costs off) SELECT count(*) FROM join_view3 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +ERROR: Cannot sample a join view without a key-preserved table +SELECT count(*) FROM join_view3 tablesample system (99.9) REPEATABLE (1); +ERROR: Cannot sample a join view without a key-preserved table + +ALTER TABLE base_table ADD CONSTRAINT xx PRIMARY KEY (base_table_id); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "xx" for table "base_table" +explain (costs off) SELECT count(*) FROM join_view3 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + QUERY PLAN +--------------------------------------------------------------------- + Aggregate + -> Merge Join + Merge Cond: (b.id = a.base_table_id) + -> Merge Join + Merge Cond: (b.id = c.base_table_id) + -> Index Only Scan using test_pkey on test b + -> Sort + Sort Key: c.base_table_id + -> Sample Scan on base_table2 c + Sampling: bernoulli (99.9) REPEATABLE (1) + -> Sort + Sort Key: a.base_table_id + -> Seq Scan on base_table a +(13 rows) + +SELECT count(*) FROM join_view3 tablesample system (99.9) REPEATABLE (1); + count +------- + 2 +(1 row) + + +ALTER TABLE base_table DROP CONSTRAINT xx; +ALTER TABLE base_table2 ADD CONSTRAINT yy PRIMARY KEY(base_table_id); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "yy" for table "base_table2" +explain (costs off) SELECT count(*) FROM join_view3 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + QUERY PLAN +--------------------------------------------------------------- + Aggregate + -> Merge Join + Merge Cond: (b.id = a.base_table_id) + -> Merge Join + Merge Cond: (b.id = c.base_table_id) + -> Index Only Scan using test_pkey on test b + -> Sort + Sort Key: c.base_table_id + -> Seq Scan on base_table2 c + -> Sort + Sort Key: a.base_table_id + -> Sample Scan on base_table a + Sampling: bernoulli (99.9) REPEATABLE (1) +(13 rows) + +SELECT count(*) FROM join_view3 tablesample system (99.9) REPEATABLE (1); + count +------- + 2 +(1 row) + + +reset search_path; +drop schema tablesample_schema5 cascade; +NOTICE: drop cascades to 11 other objects +DETAIL: drop cascades to table tablesample_schema5.test +drop cascades to table tablesample_schema5.part_list_t1 +drop cascades to table tablesample_schema5.pt_range_hash_test +drop cascades to table tablesample_schema5.base_table +drop cascades to materialized view tablesample_schema5.master_view1 +drop cascades to view tablesample_schema5.master_view2 +drop cascades to view tablesample_schema5.dependent_view1 +drop cascades to view tablesample_schema5.join_view1 +drop cascades to view tablesample_schema5.join_view2 +drop cascades to table tablesample_schema5.base_table2 +drop cascades to view tablesample_schema5.join_view3 + diff --git a/src/test/regress/expected/test_b_format_collate.out b/src/test/regress/expected/test_b_format_collate.out index 75248e4fee242bc1940e984ccfd7d6aa89db640f..cc6e856ce5ec0637f4c46a1fbab0c28711b9649c 100644 --- a/src/test/regress/expected/test_b_format_collate.out +++ b/src/test/regress/expected/test_b_format_collate.out @@ -2636,6 +2636,22 @@ select distinct c3 from test_utf8mb4_bin; fxlP7sW8vA9hcYdKqRHLwDzRSaAjV1VrMZFYRsmjb9JpsIPdGu7Gpi6OzaOqmR (1 row) +set group_concat_max_len = 2; +drop table if exists t1; +create table t1(a char(32) character set 'utf8' collate utf8_general_ci) character set 'utf8' collate 'utf8_general_ci'; +insert into t1 values('律师事务部中心(中文汉字匹配)'); +select * from (select group_concat(a) ab from t1) where ab like '%中文%'; + ab +---- +(0 rows) + +set group_concat_max_len = default; +select * from (select group_concat(a) ab from t1) where ab like '%中文%'; + ab +------------------------------ + 律师事务部中心(中文汉字匹配) +(1 row) + -- test alter table convert to SET b_format_behavior_compat_options = 'enable_multi_charset'; drop table if exists test_convert_to; diff --git a/src/test/regress/expected/test_b_format_collate2.out b/src/test/regress/expected/test_b_format_collate2.out new file mode 100644 index 0000000000000000000000000000000000000000..23ed4523c5a93887ee7452e62c06e769387aad68 --- /dev/null +++ b/src/test/regress/expected/test_b_format_collate2.out @@ -0,0 +1,114 @@ +CREATE DATABASE test_collate_A4 with dbcompatibility 'b' ENCODING='SQL_ASCII' LC_COLLATE='C' LC_CTYPE='C'; +\c test_collate_A4 +set b_format_behavior_compat_options = 'default_collation,enable_multi_charset'; +create or replace function pg_catalog.get_index_columns(OUT namespace name, OUT indexrelid oid, OUT indrelid oid, OUT indisunique bool, OUT indisusable bool, OUT seq_in_index int2, OUT attrnum int2, OUT collation int2) returns setof record +as $$ +declare +query_str text; +item int2; +row_data record; +begin +query_str := 'select n.nspname, i.indexrelid, i.indrelid, i.indisunique, i.indisusable, i.indkey, i.indoption, i.indnkeyatts + from pg_catalog.pg_index i + left join pg_class c on c.oid = i.indexrelid + left join pg_catalog.pg_namespace n on n.oid = c.relnamespace + where n.nspname <> ''pg_catalog'' + and n.nspname <> ''db4ai'' + and n.nspname <> ''information_schema'' + and n.nspname !~ ''^pg_toast'''; +for row_data in EXECUTE(query_str) LOOP + for item in 0..row_data.indnkeyatts - 1 loop + namespace := row_data.nspname; + indexrelid := row_data.indexrelid; + indrelid := row_data.indrelid; + indisunique := row_data.indisunique; + indisusable := row_data.indisusable; + seq_in_index := item + 1; + attrnum := row_data.indkey[item]; + collation := row_data.indoption[item]; + return next; + end loop; +end loop; +end; $$ +LANGUAGE 'plpgsql'; +create view public.index_statistic as +select + i.namespace as "namespace", + (select relname from pg_class tc where tc.oid = i.indrelid) as "table", + not i.indisunique as "non_unique", + c.relname as "key_name", + i.seq_in_index as "seq_in_index", + a.attname as "column_name", + (case when m.amcanorder + then ( + case when i.collation & 1 then 'D' else 'A' END + ) else null end + ) as "collation", + (select + (case when ts.stadistinct = 0 + then NULL else ( + case when ts.stadistinct > 0 then ts.stadistinct else ts.stadistinct * tc.reltuples * -1 end + ) end + ) + from pg_class tc + left join pg_statistic ts on tc.oid = ts.starelid + where + tc.oid = i.indrelid + and ts.staattnum = i.attrnum + ) as "cardinality", + null as "sub_part", + null as "packed", + (case when a.attnotnull then '' else 'YES' end) as "null", + m.amname as "index_type", + (case when i.indisusable then '' else 'disabled' end) as "comment", + (select description from pg_description where objoid = i.indexrelid) as "index_comment" +from + (select * from get_index_columns()) i + left join pg_class c on c.oid = i.indexrelid + left join pg_attribute a on a.attrelid = i.indrelid + and a.attnum = i.attrnum + left join pg_am m on m.oid = c.relam +order by + c.relname; +CREATE OR REPLACE FUNCTION pg_catalog.pg_get_nonstrict_basic_value(typename text) +RETURNS text +AS +$$ +BEGIN + IF typename = 'timestamp' then + return 'now'; + elsif typename = 'time' or typename = 'timetz' or typename = 'interval' or typename = 'reltime' then + return '00:00:00'; + elsif typename = 'date' then + return '1970-01-01'; + elsif typename = 'smalldatetime' then + return '1970-01-01 08:00:00'; + elsif typename = 'abstime' then + return '1970-01-01 08:00:00+08'; + elsif typename = 'uuid' then + return '00000000-0000-0000-0000-000000000000'; + elsif typename = 'bool' then + return 'false'; + elsif typename = 'point' or typename = 'polygon' then + return '(0,0)'; + elsif typename = 'path' then + return '((0,0))'; + elsif typename = 'circle' then + return '(0,0),0'; + elsif typename = 'lseg' or typename = 'box' then + return '(0,0),(0,0)'; + elsif typename = 'tinterval' then + return '["1970-01-01 00:00:00+08" "1970-01-01 00:00:00+08"]'; + else + return '0 or empty'; + end if; +end; +$$ +LANGUAGE plpgsql; +CREATE VIEW public.pg_type_nonstrict_basic_value AS + SELECT + t.typname As typename, + pg_get_nonstrict_basic_value(t.typname) As basic_value + FROM pg_type t; +\c postgres +DROP DATABASE IF EXISTS test_collate_A4; diff --git a/src/test/regress/expected/type_replace.out b/src/test/regress/expected/type_replace.out index 2f8ba2fe62b3fb4305441158ce34376c72c5608c..0c4a80710e54b32602bdcdd8c9de99fe1656a947 100644 --- a/src/test/regress/expected/type_replace.out +++ b/src/test/regress/expected/type_replace.out @@ -89,15 +89,15 @@ begin end; / create or replace type typ1 as table of varchar; -NOTICE: proc1(_varchar[]) depends on this type +NOTICE: proc1(typ1) depends on this type -- case 2.3 原类型为其他类型 create type enum1 AS ENUM ('one', 'two', 'three'); create or replace type enum1 AS table of varchar; ERROR: type already exists but not a table of type drop schema test_type_replace cascade; NOTICE: drop cascades to 5 other objects -DETAIL: drop cascades to type _varchar[] -drop cascades to type _varchar[] -drop cascades to type _varchar[] -drop cascades to function proc1(_varchar[]) +DETAIL: drop cascades to type typ1 +drop cascades to type shell1 +drop cascades to type _typ1 +drop cascades to function proc1(typ1) drop cascades to type enum1 diff --git a/src/test/regress/expected/vector_procedure.out b/src/test/regress/expected/vector_procedure.out index 7fba8feb1faf529a4bca2bf608baab5b4286558d..c60ef5e0374076399cad929fa5634ece9342283f 100644 --- a/src/test/regress/expected/vector_procedure.out +++ b/src/test/regress/expected/vector_procedure.out @@ -45,5 +45,5 @@ drop schema force_vector_engine cascade; NOTICE: drop cascades to 4 other objects DETAIL: drop cascades to type pro_tblof_ty_015 drop cascades to table pro_tblof_tbl_015 -drop cascades to type _pro_tblof_ty_015[] +drop cascades to type pro_tblof_015 drop cascades to function pro_tblof_pro_015(integer,integer) diff --git a/src/test/regress/input/cgin_select.source b/src/test/regress/input/cgin_select.source index 1b6b5e18c78ee9ca24acae24a99e1cb389b6b1ea..7509868ef34ed49063f61924649887fe212f7ad3 100644 --- a/src/test/regress/input/cgin_select.source +++ b/src/test/regress/input/cgin_select.source @@ -4,15 +4,14 @@ CREATE DATABASE db_gin_utf8_col TEMPLATE template0 encoding 'UTF8'; SET ENABLE_SEQSCAN=OFF; SET ENABLE_INDEXSCAN=OFF; SET ENABLE_BITMAPSCAN=ON; -SET ENABLE_FAST_QUERY_SHIPPING=OFF; --- import data -create table import_data_col(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text) distribute by hash (id); +create table import_data_col(id int, strType varchar(10), numType varchar(20), textType text); copy import_data_col from '@abs_srcdir@/data/gin_data_1000.txt'; --- import data then create index -create table gin_test_data_col(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text) with(orientation=column) distribute by hash (id); -insert into gin_test_data_col select 1, chepai, shenfenzheng, duanxin from import_data_col; +create table gin_test_data_col(id int, strType varchar(10), numType varchar(20), textType text) with(orientation=column); +insert into gin_test_data_col select 1, strType, numType, textType from import_data_col; --- 6 times insert into gin_test_data_col select * from gin_test_data_col; insert into gin_test_data_col select * from gin_test_data_col; @@ -21,21 +20,21 @@ insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --- create index -create index chepai_idx_col on gin_test_data_col using gin(to_tsvector('ngram', chepai)) with (fastupdate=on); -create index shenfenzheng_idx_col on gin_test_data_col using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); -create index duanxin_idx_col on gin_test_data_col using gin(to_tsvector('ngram', duanxin)) with (fastupdate=on); +create index strType_idx_col on gin_test_data_col using gin(to_tsvector('ngram', strType)) with (fastupdate=on); +create index numType_idx_col on gin_test_data_col using gin(to_tsvector('ngram', numType)) with (fastupdate=on); +create index textType_idx_col on gin_test_data_col using gin(to_tsvector('ngram', textType)) with (fastupdate=on); --- select -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); -select count(*) from gin_test_data_col where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '5:*'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tz'); +select count(*) from gin_test_data_col where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '5:*'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); --- gin data page split -create table gin_test_data_col_1(id int, shenfenzheng varchar(20)) with(orientation=column) distribute by hash (id); -insert into gin_test_data_col_1 select id, shenfenzheng from gin_test_data_col; +create table gin_test_data_col_1(id int, numType varchar(20)) with(orientation=column); +insert into gin_test_data_col_1 select id, numType from gin_test_data_col; --- 7 times insert into gin_test_data_col_1 select * from gin_test_data_col_1; insert into gin_test_data_col_1 select * from gin_test_data_col_1; @@ -45,14 +44,14 @@ insert into gin_test_data_col_1 select * from gin_test_data_col_1; --insert into gin_test_data_col_1 select * from gin_test_data_col_1; --insert into gin_test_data_col_1 select * from gin_test_data_col_1; vacuum freeze gin_test_data_col_1; -create index shenfenzheng_idx_col_1 on gin_test_data_col_1 using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); +create index numType_idx_col_1 on gin_test_data_col_1 using gin(to_tsvector('ngram', numType)) with (fastupdate=on); delete from gin_test_data_col_1; vacuum gin_test_data_col_1; --- import data with index truncate gin_test_data_col; vacuum full gin_test_data_col; -insert into gin_test_data_col select 1, chepai, shenfenzheng, duanxin from import_data_col; +insert into gin_test_data_col select 1, strType, numType, textType from import_data_col; --- 6 times insert into gin_test_data_col select * from gin_test_data_col; insert into gin_test_data_col select * from gin_test_data_col; @@ -61,13 +60,13 @@ insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --- select -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); -select count(*) from gin_test_data_col where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '5:*'); -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tz'); +select count(*) from gin_test_data_col where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '5:*'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); --- vacuum vacuum gin_test_data_col; @@ -75,3 +74,4 @@ delete from gin_test_data_col; vacuum gin_test_data_col; truncate gin_test_data_col; vacuum full gin_test_data_col; + diff --git a/src/test/regress/input/gin_select.source b/src/test/regress/input/gin_select.source index 52d6e15ee0166bb9856c136484eee540e10e3412..a8676b8a30eba0b44c0bd00fe2d25f95639404e7 100644 --- a/src/test/regress/input/gin_select.source +++ b/src/test/regress/input/gin_select.source @@ -6,12 +6,12 @@ SET ENABLE_INDEXSCAN=OFF; SET ENABLE_BITMAPSCAN=ON; --- import data -create table import_data(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text); +create table import_data(id int, strType varchar(10), numType varchar(20), textType text); copy import_data from '@abs_srcdir@/data/gin_data_1000.txt'; --- import data then create index -create table gin_test_data(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text); -insert into gin_test_data select 1, chepai, shenfenzheng, duanxin from import_data; +create table gin_test_data(id int, strType varchar(10), numType varchar(20), textType text); +insert into gin_test_data select 1, strType, numType, textType from import_data; --- 6 times insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; @@ -20,20 +20,20 @@ insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --- create index -create index chepai_idx on gin_test_data using gin(to_tsvector('ngram', chepai)) with (fastupdate=on); -create index shenfenzheng_idx on gin_test_data using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); -create index duanxin_idx on gin_test_data using gin(to_tsvector('ngram', duanxin)) with (fastupdate=on); +create index strType_idx on gin_test_data using gin(to_tsvector('ngram', strType)) with (fastupdate=on); +create index numType_idx on gin_test_data using gin(to_tsvector('ngram', numType)) with (fastupdate=on); +create index textType_idx on gin_test_data using gin(to_tsvector('ngram', textType)) with (fastupdate=on); --- select -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); -select count(*) from gin_test_data where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tZ'); +select count(*) from gin_test_data where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); --- gin data page split -create table gin_test_data_1(id int, shenfenzheng varchar(20)); -insert into gin_test_data_1 select id, shenfenzheng from gin_test_data; +create table gin_test_data_1(id int, numType varchar(20)); +insert into gin_test_data_1 select id, numType from gin_test_data; --- 7 times insert into gin_test_data_1 select * from gin_test_data_1; --insert into gin_test_data_1 select * from gin_test_data_1; @@ -43,14 +43,14 @@ insert into gin_test_data_1 select * from gin_test_data_1; --insert into gin_test_data_1 select * from gin_test_data_1; --insert into gin_test_data_1 select * from gin_test_data_1; vacuum freeze gin_test_data_1; -create index shenfenzheng_idx_1 on gin_test_data_1 using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); +create index numType_idx_1 on gin_test_data_1 using gin(to_tsvector('ngram', numType)) with (fastupdate=on); delete from gin_test_data_1; vacuum gin_test_data_1; --- import data with index truncate gin_test_data; vacuum full gin_test_data; -insert into gin_test_data select 1, chepai, shenfenzheng, duanxin from import_data; +insert into gin_test_data select 1, strType, numType, textType from import_data; --- 6 times insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; @@ -59,12 +59,12 @@ insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --- select -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); -select count(*) from gin_test_data where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tZ'); +select count(*) from gin_test_data where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); --- vacuum vacuum gin_test_data; @@ -72,3 +72,4 @@ delete from gin_test_data; vacuum gin_test_data; truncate gin_test_data; vacuum full gin_test_data; + diff --git a/src/test/regress/input/partition_expr_key.source b/src/test/regress/input/partition_expr_key.source index 00d439a3012884b6eb166c70d5cc7048aa69ceb2..f8fa9eb6832c7f07b9fef9d495b93a9212144c88 100644 --- a/src/test/regress/input/partition_expr_key.source +++ b/src/test/regress/input/partition_expr_key.source @@ -381,6 +381,23 @@ insert into t values (null,1); -- The null value is expected to be inserted into the last partition. select count(*) from t partition (p_2017); select count(*) from t partition (p_others); + +-- test exprkey across partitions +create table test_exprkey_move_part( + a int, + b int +) +partition by range(a+100) +( + partition p0 values less than(1000), + partition p1 values less than(2000) +); +insert into test_exprkey_move_part values(888, 1); +update test_exprkey_move_part set a=1000 where a=888; +select * from test_exprkey_move_part; +update test_exprkey_move_part set a=1001 where a=1000; +select * from test_exprkey_move_part; + \c regression drop database if exists part_expr_key_db; diff --git a/src/test/regress/make_fastcheck_ss_postgresql.conf b/src/test/regress/make_fastcheck_ss_postgresql.conf index f182af69e12d2b47b5bd25a1a4c818ac09020348..d6a92553dacdea2895a9247cf2bcab67ac77a36d 100644 --- a/src/test/regress/make_fastcheck_ss_postgresql.conf +++ b/src/test/regress/make_fastcheck_ss_postgresql.conf @@ -38,4 +38,3 @@ enable_stateless_pooler_reuse = on sql_beta_feature = 'a_style_coerce' enable_global_syscache = on log_min_messages = FATAL -ss_enable_reform = off diff --git a/src/test/regress/output/cgin_select.source b/src/test/regress/output/cgin_select.source index 7db865c2130ff12312b9520efe8c0429eebe34ff..71af72dd2e8bd14ca2f902f4dcbff119a773b109 100644 --- a/src/test/regress/output/cgin_select.source +++ b/src/test/regress/output/cgin_select.source @@ -3,13 +3,12 @@ CREATE DATABASE db_gin_utf8_col TEMPLATE template0 encoding 'UTF8'; SET ENABLE_SEQSCAN=OFF; SET ENABLE_INDEXSCAN=OFF; SET ENABLE_BITMAPSCAN=ON; -SET ENABLE_FAST_QUERY_SHIPPING=OFF; --- import data -create table import_data_col(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text) distribute by hash (id); +create table import_data_col(id int, strType varchar(10), numType varchar(20), textType text); copy import_data_col from '@abs_srcdir@/data/gin_data_1000.txt'; --- import data then create index -create table gin_test_data_col(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text) with(orientation=column) distribute by hash (id); -insert into gin_test_data_col select 1, chepai, shenfenzheng, duanxin from import_data_col; +create table gin_test_data_col(id int, strType varchar(10), numType varchar(20), textType text) with(orientation=column); +insert into gin_test_data_col select 1, strType, numType, textType from import_data_col; --- 6 times insert into gin_test_data_col select * from gin_test_data_col; insert into gin_test_data_col select * from gin_test_data_col; @@ -18,55 +17,55 @@ insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --- create index -create index chepai_idx_col on gin_test_data_col using gin(to_tsvector('ngram', chepai)) with (fastupdate=on); -create index shenfenzheng_idx_col on gin_test_data_col using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); -create index duanxin_idx_col on gin_test_data_col using gin(to_tsvector('ngram', duanxin)) with (fastupdate=on); +create index strType_idx_col on gin_test_data_col using gin(to_tsvector('ngram', strType)) with (fastupdate=on); +create index numType_idx_col on gin_test_data_col using gin(to_tsvector('ngram', numType)) with (fastupdate=on); +create index textType_idx_col on gin_test_data_col using gin(to_tsvector('ngram', textType)) with (fastupdate=on); --- select -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); count ------- - 8 + 16 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tz'); count ------- - 16 + 72 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); +select count(*) from gin_test_data_col where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); count ------- - 2936 + 40 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); count ------- - 760 + 704 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); count ------- - 7240 + 7296 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '5:*'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '5:*'); count ------- - 6288 + 4488 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); count ------- 8 (1 row) --- gin data page split -create table gin_test_data_col_1(id int, shenfenzheng varchar(20)) with(orientation=column) distribute by hash (id); -insert into gin_test_data_col_1 select id, shenfenzheng from gin_test_data_col; +create table gin_test_data_col_1(id int, numType varchar(20)) with(orientation=column); +insert into gin_test_data_col_1 select id, numType from gin_test_data_col; --- 7 times insert into gin_test_data_col_1 select * from gin_test_data_col_1; insert into gin_test_data_col_1 select * from gin_test_data_col_1; @@ -76,13 +75,13 @@ insert into gin_test_data_col_1 select * from gin_test_data_col_1; --insert into gin_test_data_col_1 select * from gin_test_data_col_1; --insert into gin_test_data_col_1 select * from gin_test_data_col_1; vacuum freeze gin_test_data_col_1; -create index shenfenzheng_idx_col_1 on gin_test_data_col_1 using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); +create index numType_idx_col_1 on gin_test_data_col_1 using gin(to_tsvector('ngram', numType)) with (fastupdate=on); delete from gin_test_data_col_1; vacuum gin_test_data_col_1; --- import data with index truncate gin_test_data_col; vacuum full gin_test_data_col; -insert into gin_test_data_col select 1, chepai, shenfenzheng, duanxin from import_data_col; +insert into gin_test_data_col select 1, strType, numType, textType from import_data_col; --- 6 times insert into gin_test_data_col select * from gin_test_data_col; insert into gin_test_data_col select * from gin_test_data_col; @@ -91,43 +90,43 @@ insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --insert into gin_test_data_col select * from gin_test_data_col; --- select -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); count ------- - 8 + 16 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); +select count(*) from gin_test_data_col where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tz'); count ------- - 16 + 72 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); +select count(*) from gin_test_data_col where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); count ------- - 2936 + 40 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); count ------- - 760 + 704 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); count ------- - 7240 + 7296 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '5:*'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '5:*'); count ------- - 6288 + 4488 (1 row) -select count(*) from gin_test_data_col where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data_col where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); count ------- 8 diff --git a/src/test/regress/output/cstore_drop_column_replicated.source b/src/test/regress/output/cstore_drop_column_replicated.source index f91592625db5678f29791f5c5c7aa00f629dcbae..6b262be9b234562dbb90d5007caec4003d101346 100644 --- a/src/test/regress/output/cstore_drop_column_replicated.source +++ b/src/test/regress/output/cstore_drop_column_replicated.source @@ -222,6 +222,7 @@ select count(*) from cstore_part_table where c3 < 5; (1 row) alter table cstore_part_table truncate partition cstore_part_table_p0; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(*) from cstore_part_table where c3 < 5; count ------- @@ -455,6 +456,7 @@ select * from cstore_part_table order by c1,c3; (10 rows) alter table cstore_part_table truncate partition cstore_part_table_p4; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from cstore_part_table partition (cstore_part_table_p4); c3 | c1 ----+---- @@ -476,6 +478,7 @@ alter table ord_table add column c1 text default 100; alter table ord_table drop column c2; insert into ord_table(c1,c3) values(generate_series(1,6),generate_series(1,6)); alter table cstore_part_table exchange partition(cstore_part_table_p4) with table ord_table with validation; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from cstore_part_table partition (cstore_part_table_p4) order by c3; c3 | c1 ----+---- diff --git a/src/test/regress/output/gin_select.source b/src/test/regress/output/gin_select.source index 46643687264173f58de5059c8d7181f3f376f15e..90f99231d9f5940a40663fa732b461cfd191f0bf 100644 --- a/src/test/regress/output/gin_select.source +++ b/src/test/regress/output/gin_select.source @@ -4,11 +4,11 @@ SET ENABLE_SEQSCAN=OFF; SET ENABLE_INDEXSCAN=OFF; SET ENABLE_BITMAPSCAN=ON; --- import data -create table import_data(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text); -copy import_data from '/usr3/data1/jiangyan/openGauss-server/src/test/regress/data/gin_data_1000.txt'; +create table import_data(id int, strType varchar(10), numType varchar(20), textType text); +copy import_data from '@abs_srcdir@/data/gin_data_1000.txt'; --- import data then create index -create table gin_test_data(id int, chepai varchar(10), shenfenzheng varchar(20), duanxin text); -insert into gin_test_data select 1, chepai, shenfenzheng, duanxin from import_data; +create table gin_test_data(id int, strType varchar(10), numType varchar(20), textType text); +insert into gin_test_data select 1, strType, numType, textType from import_data; --- 6 times insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; @@ -17,49 +17,49 @@ insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --- create index -create index chepai_idx on gin_test_data using gin(to_tsvector('ngram', chepai)) with (fastupdate=on); -create index shenfenzheng_idx on gin_test_data using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); -create index duanxin_idx on gin_test_data using gin(to_tsvector('ngram', duanxin)) with (fastupdate=on); +create index strType_idx on gin_test_data using gin(to_tsvector('ngram', strType)) with (fastupdate=on); +create index numType_idx on gin_test_data using gin(to_tsvector('ngram', numType)) with (fastupdate=on); +create index textType_idx on gin_test_data using gin(to_tsvector('ngram', textType)) with (fastupdate=on); --- select -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); count ------- - 2 + 4 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tZ'); count ------- - 4 + 18 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); +select count(*) from gin_test_data where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); count ------- - 734 + 10 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); count ------- - 190 + 176 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); count ------- - 1810 + 1824 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); count ------- 2 (1 row) --- gin data page split -create table gin_test_data_1(id int, shenfenzheng varchar(20)); -insert into gin_test_data_1 select id, shenfenzheng from gin_test_data; +create table gin_test_data_1(id int, numType varchar(20)); +insert into gin_test_data_1 select id, numType from gin_test_data; --- 7 times insert into gin_test_data_1 select * from gin_test_data_1; --insert into gin_test_data_1 select * from gin_test_data_1; @@ -69,13 +69,13 @@ insert into gin_test_data_1 select * from gin_test_data_1; --insert into gin_test_data_1 select * from gin_test_data_1; --insert into gin_test_data_1 select * from gin_test_data_1; vacuum freeze gin_test_data_1; -create index shenfenzheng_idx_1 on gin_test_data_1 using gin(to_tsvector('ngram', shenfenzheng)) with (fastupdate=on); +create index numType_idx_1 on gin_test_data_1 using gin(to_tsvector('ngram', numType)) with (fastupdate=on); delete from gin_test_data_1; vacuum gin_test_data_1; --- import data with index truncate gin_test_data; vacuum full gin_test_data; -insert into gin_test_data select 1, chepai, shenfenzheng, duanxin from import_data; +insert into gin_test_data select 1, strType, numType, textType from import_data; --- 6 times insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; @@ -84,37 +84,37 @@ insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --insert into gin_test_data select * from gin_test_data; --- select -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', 'LIU'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'BRM'); count ------- - 2 + 4 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', chepai) @@ to_tsquery('ngram', '湘F'); +select count(*) from gin_test_data where to_tsvector('ngram', strType) @@ to_tsquery('ngram', 'tZ'); count ------- - 4 + 18 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', duanxin) @@ to_tsquery('ngram', '苏文'); +select count(*) from gin_test_data where to_tsvector('ngram', textType) @@ to_tsquery('ngram', '曹瞒'); count ------- - 734 + 10 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '58'); count ------- - 190 + 176 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '!58'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '!58'); count ------- - 1810 + 1824 (1 row) -select count(*) from gin_test_data where to_tsvector('ngram', shenfenzheng) @@ to_tsquery('ngram', '325682195604186793'); +select count(*) from gin_test_data where to_tsvector('ngram', numType) @@ to_tsquery('ngram', '711658601'); count ------- 2 diff --git a/src/test/regress/output/hw_cstore_partition.source b/src/test/regress/output/hw_cstore_partition.source index 96ff6c713327703cd7dcd324ea68ad5265c41b55..b8edbf7c87d582b7957857eef66bc8b3b10acc5f 100644 --- a/src/test/regress/output/hw_cstore_partition.source +++ b/src/test/regress/output/hw_cstore_partition.source @@ -236,6 +236,7 @@ create table test_exchange_row(id int, value int); insert into test_exchange_row values(1, generate_series(10, 19)); insert into test_exchange_col select * from test_exchange_row; alter table test_exchange_partition exchange partition (p2) with table test_exchange_col; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(1) from test_exchange_partition; count ------- @@ -250,6 +251,7 @@ insert into test_exchange_col select * from test_exchange_row; alter table test_exchange_partition exchange partition (p2) with table test_exchange_col with validation; ERROR: some rows in table do not qualify for specified partition alter table test_exchange_partition exchange partition (p2) with table test_exchange_col with validation verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select count(1) from test_exchange_partition; count ------- diff --git a/src/test/regress/output/hw_partition_hash_exchange.source b/src/test/regress/output/hw_partition_hash_exchange.source index 84164dc26f98d3810647eafd0f882a6cc6b33938..fa787ccfccd1efcec2ac5bb274b5ca8d86765459 100755 --- a/src/test/regress/output/hw_partition_hash_exchange.source +++ b/src/test/regress/output/hw_partition_hash_exchange.source @@ -22,6 +22,7 @@ select * from test_exchange_func_ht; (1 row) alter table test_exchange_func_ht exchange partition (p2) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ord; a --- @@ -93,6 +94,7 @@ select * from test_exchange_func_ht partition for (1); (1 row) alter table test_exchange_func_ht exchange partition for (1) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht partition for (1); a --- @@ -310,6 +312,7 @@ partition by hash(a) PARTITION p2 ); alter table test_exchange_constraint_ht exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_ht; --a-2 @@ -347,6 +350,7 @@ partition by hash(a) PARTITION p2 ); alter table test_exchange_constraint_ht exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_ht; --a-4-2 @@ -371,6 +375,7 @@ partition by hash(a) PARTITION p2 ); alter table test_exchange_constraint_ht exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_ht; --b-2 @@ -398,6 +403,7 @@ partition by hash(a) ); NOTICE: CREATE TABLE / UNIQUE will create implicit index "test_exchange_constraint_ht_a_key" for table "test_exchange_constraint_ht" alter table test_exchange_constraint_ht exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_ht; --c-2 @@ -426,6 +432,7 @@ partition by hash(a) ); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_exchange_constraint_ht_pkey" for table "test_exchange_constraint_ht" alter table test_exchange_constraint_ht exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_ht; --d-2 @@ -454,6 +461,7 @@ partition by hash(a) PARTITION p2 ); alter table test_exchange_constraint_ht exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_ht; drop table test_exchange_constraint_ref; @@ -499,6 +507,7 @@ partition by hash(a) PARTITION p2 ); alter table test_exchange_constraint_ht exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_ht; --f-2 @@ -647,6 +656,7 @@ create index test_exchange_index_ht_b on test_exchange_index_ht (b) local; create index test_exchange_index_ht_a_1 on test_exchange_index_ht (a) local; create index test_exchange_index_ht_a_2 on test_exchange_index_ht (a) local; alter table test_exchange_index_ht exchange partition (p1) with table test_exchange_index_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_index_ord; drop table test_exchange_index_ht; -- 7. validation check @@ -689,6 +699,7 @@ partition by hash(a) insert into test_exchange_validation_ord values (1), (10); --SUCCESS alter table test_exchange_validation_ht exchange partition (p1) with table test_exchange_validation_ord without validation; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_validation_ord; drop table test_exchange_validation_ht; /* @@ -840,6 +851,7 @@ select a from test_exchange_index_ht where a=1; (1 row) alter table test_exchange_index_ht exchange partition (p1) with table test_exchange_index_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select a from test_exchange_index_ht partition (p1); a --- @@ -939,6 +951,7 @@ select p.relname, t.spcname from pg_partition p, pg_tablespace t where p.reltabl (1 row) alter table test_exchange_tablespace_ht exchange partition (p1) with table test_exchange_tablespace_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --check tablespace has exchanged select c.relname, t.spcname from pg_class c, pg_tablespace t where c.reltablespace=t.oid and c.relname='test_exchange_tablespace_ord'; relname | spcname @@ -998,6 +1011,7 @@ select p.relname, t.spcname from pg_partition p, pg_tablespace t where p.reltabl (1 row) alter table test_exchange_tablespace_ht exchange partition (p1) with table test_exchange_tablespace_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --check tablespace has exchanged select c.relname, t.spcname from pg_class c, pg_tablespace t where c.reltablespace=t.oid and c.relname='test_exchange_tablespace_ord_a'; relname | spcname @@ -1028,14 +1042,18 @@ partition by hash(a) PARTITION test_exchange_verbose_ht_p3 ); alter table test_exchange_verbose_ht exchange partition (test_exchange_verbose_ht_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table test_exchange_verbose_ht exchange partition (test_exchange_verbose_ht_p1) with table test_exchange_verbose_ord with validation verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --ERROR alter table test_exchange_verbose_ht exchange partition (test_exchange_verbose_ht_p1) with table test_exchange_verbose_ord without validation verbose; ERROR: syntax error at or near "verbose" LINE 1: ... table test_exchange_verbose_ord without validation verbose; ^ alter table test_exchange_verbose_ht exchange partition for (5) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table test_exchange_verbose_ht exchange partition for (5) with table test_exchange_verbose_ord with validation verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --ERROR alter table test_exchange_verbose_ht exchange partition for (5) with table test_exchange_verbose_ord without validation verbose; ERROR: syntax error at or near "verbose" @@ -1054,6 +1072,7 @@ partition by hash(a) ); insert into test_exchange_verbose_ord values(generate_series(1, 6)); alter table test_exchange_verbose_ht exchange partition (test_exchange_verbose_ht_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_verbose_ord order by 1; a --- @@ -1106,6 +1125,7 @@ create index test_exchange_verbose_ord_index on test_exchange_verbose_ord (b); create index test_exchange_verbose_ht_index on test_exchange_verbose_ht (b) local; insert into test_exchange_verbose_ord values (-1, generate_series(1, 6)); alter table test_exchange_verbose_ht exchange partition (test_exchange_verbose_ht_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index set enable_seqscan=off; explain(ANALYZE false,VERBOSE false, COSTS false,BUFFERS false,TIMING false) select b from test_exchange_verbose_ht where b=5; QUERY PLAN @@ -1134,6 +1154,7 @@ update test_exchange_verbose_ord set b=3 where b=4; delete from test_exchange_verbose_ord where b=2; delete from test_exchange_verbose_ord where b=3; alter table test_exchange_verbose_ht exchange partition (test_exchange_verbose_ht_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(ANALYZE false,VERBOSE false, COSTS false,BUFFERS false,TIMING false) select b from test_exchange_verbose_ht where b=1; QUERY PLAN ----------------------------------------------------------------------- @@ -1659,6 +1680,7 @@ select * from test_exchange_func_ht partition (p2); (1 row) alter table test_exchange_func_ht exchange partition (p1) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ord; a --- @@ -1748,6 +1770,7 @@ select * from test_exchange_func_ht partition (p2); (1 row) alter table test_exchange_func_ht exchange partition for (3) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ord; a --- @@ -1810,9 +1833,13 @@ partition by hash(a) PARTITION p9 ); alter table test_exchange_func_ht exchange partition (p3) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table test_exchange_func_ht exchange partition (p5) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table test_exchange_func_ht exchange partition (p7) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table test_exchange_func_ht exchange partition (p9) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht; a | b | c ---+---+--- @@ -1854,12 +1881,14 @@ select * from test_exchange_func_ht partition(p1); (13 rows) alter table test_exchange_func_ht exchange partition for (9) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht partition(p1); a | b | c ---+---+--- (0 rows) alter table test_exchange_func_ht exchange partition for (9) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht partition(p1); a | b | c ----+---+--- @@ -1896,12 +1925,14 @@ select * from test_exchange_func_ht partition(p5); (12 rows) alter table test_exchange_func_ht exchange partition for (2) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht partition(p5); a | b | c ---+---+--- (0 rows) alter table test_exchange_func_ht exchange partition for (2) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht partition(p5); a | b | c -----+---+--- @@ -1940,12 +1971,14 @@ select * from test_exchange_func_ht partition(p9); (15 rows) alter table test_exchange_func_ht exchange partition for (17) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht partition(p9); a | b | c ---+---+--- (0 rows) alter table test_exchange_func_ht exchange partition for (17) with table test_exchange_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ht partition(p9); a | b | c ----+---+--- diff --git a/src/test/regress/output/hw_partition_interval.source b/src/test/regress/output/hw_partition_interval.source index 36cff6c67af39cc6965de8c789799a4952de73ea..63a35973cda25a1768995c3ebaa260a3b7b06f72 100644 --- a/src/test/regress/output/hw_partition_interval.source +++ b/src/test/regress/output/hw_partition_interval.source @@ -122,6 +122,7 @@ select * from interval_normal_date partition (sys_p3) order by logdate; -- drop range partition which is not next to interval range. ALTER TABLE interval_normal_date DROP PARTITION interval_normal_date_p2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- see about the info of the partitioned table in pg_partition select relname, parttype, partstrategy, boundaries from pg_partition where parentid = (select oid from pg_class where relname = 'interval_normal_date') @@ -138,6 +139,7 @@ select relname, parttype, partstrategy, boundaries from pg_partition -- drop interval range partition ALTER TABLE interval_normal_date DROP PARTITION sys_p2; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- see the info of the partitioned table in pg_partition, only reduce a interval range partition instance. select relname, parttype, partstrategy, boundaries from pg_partition where parentid = (select oid from pg_class where relname = 'interval_normal_date') @@ -153,6 +155,7 @@ select relname, parttype, partstrategy, boundaries from pg_partition -- drop range partition which is next to interval range. ALTER TABLE interval_normal_date DROP PARTITION interval_normal_date_p3; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- the interval parttition will changed to range partition select relname, parttype, partstrategy, boundaries from pg_partition where parentid = (select oid from pg_class where relname = 'interval_normal_date') @@ -273,6 +276,7 @@ select * from interval_normal_date partition (sys_p6) order by logdate; -- -- truncate a range partition ALTER TABLE interval_normal_date truncate PARTITION interval_normal_date_p1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_date partition (interval_normal_date_p1) order by logdate; logdate --------- @@ -280,6 +284,7 @@ select * from interval_normal_date partition (interval_normal_date_p1) order by -- truncate a interval partition ALTER TABLE interval_normal_date truncate PARTITION sys_p4; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from interval_normal_date partition (sys_p4) order by logdate; logdate --------- @@ -301,6 +306,7 @@ ALTER TABLE interval_normal_date SPLIT PARTITION sys_p1 AT ('2020-04-01 00:00:00 PARTITION sys_p1_1, PARTITION sys_p1_2 ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index -- ---- add partition is not supported; -- diff --git a/src/test/regress/output/hw_partition_list_exchange.source b/src/test/regress/output/hw_partition_list_exchange.source index 388fc9c473a3821c0ce6c7facbcabb22ecb78ba0..a97ebf790d0eadc1176cf8d545519981888c433f 100755 --- a/src/test/regress/output/hw_partition_list_exchange.source +++ b/src/test/regress/output/hw_partition_list_exchange.source @@ -22,6 +22,7 @@ select * from test_exchange_func_lt; (1 row) alter table test_exchange_func_lt exchange partition (p1) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ord; a --- @@ -87,6 +88,7 @@ select * from test_exchange_func_lt; (1 row) alter table test_exchange_func_lt exchange partition for (1) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ord; a --- @@ -301,6 +303,7 @@ partition by list(a) PARTITION p2 VALUES (3, 4, 5) ); alter table test_exchange_constraint_lt exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_lt; --a-2 @@ -338,6 +341,7 @@ partition by list(a) PARTITION p2 VALUES (3, 4, 5) ); alter table test_exchange_constraint_lt exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_lt; --a-4-2 @@ -362,6 +366,7 @@ partition by list(a) PARTITION p2 VALUES (3, 4, 5) ); alter table test_exchange_constraint_lt exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_lt; --b-2 @@ -389,6 +394,7 @@ partition by list(a) ); NOTICE: CREATE TABLE / UNIQUE will create implicit index "test_exchange_constraint_lt_a_key" for table "test_exchange_constraint_lt" alter table test_exchange_constraint_lt exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_lt; --c-2 @@ -417,6 +423,7 @@ partition by list(a) ); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_exchange_constraint_lt_pkey" for table "test_exchange_constraint_lt" alter table test_exchange_constraint_lt exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_lt; --d-2 @@ -445,6 +452,7 @@ partition by list(a) PARTITION p2 VALUES (3, 4, 5) ); alter table test_exchange_constraint_lt exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_lt; drop table test_exchange_constraint_ref; @@ -490,6 +498,7 @@ partition by list(a) PARTITION p2 VALUES (3, 4, 5) ); alter table test_exchange_constraint_lt exchange partition (p1) with table test_exchange_constraint_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_constraint_ord; drop table test_exchange_constraint_lt; --f-2 @@ -638,6 +647,7 @@ create index test_exchange_index_lt_b on test_exchange_index_lt (b) local; create index test_exchange_index_lt_a_1 on test_exchange_index_lt (a) local; create index test_exchange_index_lt_a_2 on test_exchange_index_lt (a) local; alter table test_exchange_index_lt exchange partition (p1) with table test_exchange_index_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_index_ord; drop table test_exchange_index_lt; -- 7. validation check @@ -680,6 +690,7 @@ partition by list(a) insert into test_exchange_validation_ord values (1), (10); --SUCCESS alter table test_exchange_validation_lt exchange partition (p1) with table test_exchange_validation_ord without validation; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index drop table test_exchange_validation_ord; drop table test_exchange_validation_lt; /* @@ -795,6 +806,7 @@ select a from test_exchange_index_ord where a=1; (0 rows) alter table test_exchange_index_lt exchange partition (p2) with table test_exchange_index_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(verbose on, costs off) select a from test_exchange_index_ord where a=3; QUERY PLAN ------------------------------------------------------ @@ -856,6 +868,7 @@ select p.relname, t.spcname from pg_partition p, pg_tablespace t where p.reltabl (1 row) alter table test_exchange_tablespace_lt exchange partition (p1) with table test_exchange_tablespace_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --check tablespace has exchanged select c.relname, t.spcname from pg_class c, pg_tablespace t where c.reltablespace=t.oid and c.relname='test_exchange_tablespace_ord'; relname | spcname @@ -915,6 +928,7 @@ select p.relname, t.spcname from pg_partition p, pg_tablespace t where p.reltabl (1 row) alter table test_exchange_tablespace_lt exchange partition (p1) with table test_exchange_tablespace_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --check tablespace has exchanged select c.relname, t.spcname from pg_class c, pg_tablespace t where c.reltablespace=t.oid and c.relname='test_exchange_tablespace_ord_a'; relname | spcname @@ -945,14 +959,18 @@ partition by list(a) PARTITION test_exchange_verbose_lt_p3 VALUES (5, 6) ); alter table test_exchange_verbose_lt exchange partition (test_exchange_verbose_lt_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table test_exchange_verbose_lt exchange partition (test_exchange_verbose_lt_p1) with table test_exchange_verbose_ord with validation verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --ERROR alter table test_exchange_verbose_lt exchange partition (test_exchange_verbose_lt_p1) with table test_exchange_verbose_ord without validation verbose; ERROR: syntax error at or near "verbose" LINE 1: ... table test_exchange_verbose_ord without validation verbose; ^ alter table test_exchange_verbose_lt exchange partition for (5) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index alter table test_exchange_verbose_lt exchange partition for (5) with table test_exchange_verbose_ord with validation verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index --ERROR alter table test_exchange_verbose_lt exchange partition for (5) with table test_exchange_verbose_ord without validation verbose; ERROR: syntax error at or near "verbose" @@ -971,6 +989,7 @@ partition by list(a) ); insert into test_exchange_verbose_ord values(generate_series(1, 6)); alter table test_exchange_verbose_lt exchange partition (test_exchange_verbose_lt_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_verbose_ord order by 1; a --- @@ -1030,6 +1049,7 @@ create index test_exchange_verbose_ord_index on test_exchange_verbose_ord (b); create index test_exchange_verbose_lt_index on test_exchange_verbose_lt (b) local; insert into test_exchange_verbose_ord values (-1, generate_series(1, 6)); alter table test_exchange_verbose_lt exchange partition (test_exchange_verbose_lt_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index set enable_seqscan=off; explain(ANALYZE false,VERBOSE false, COSTS false,BUFFERS false,TIMING false) select b from test_exchange_verbose_lt where b=5; QUERY PLAN @@ -1058,6 +1078,7 @@ update test_exchange_verbose_ord set b=3 where b=4; delete from test_exchange_verbose_ord where b=2; delete from test_exchange_verbose_ord where b=3; alter table test_exchange_verbose_lt exchange partition (test_exchange_verbose_lt_p1) with table test_exchange_verbose_ord verbose; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index explain(ANALYZE false,VERBOSE false, COSTS false,BUFFERS false,TIMING false) select b from test_exchange_verbose_lt where b=1; QUERY PLAN ----------------------------------------------------------------------- @@ -1498,6 +1519,7 @@ select * from test_exchange_func_lt; (1 row) alter table test_exchange_func_lt exchange partition (p1) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ord; a --- @@ -1563,6 +1585,7 @@ select * from test_exchange_func_lt; (1 row) alter table test_exchange_func_lt exchange partition for (1) with table test_exchange_func_ord; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from test_exchange_func_ord; a --- diff --git a/src/test/regress/output/ledger_table_case.source b/src/test/regress/output/ledger_table_case.source index c2216f08512b4a7ca9e3b45bde837c6c7ddfd2c8..ef589d292882e1077b5b180f087647c954e91ea2 100644 --- a/src/test/regress/output/ledger_table_case.source +++ b/src/test/regress/output/ledger_table_case.source @@ -578,6 +578,7 @@ SELECT pg_catalog.selecthist('ledgernsp', 'partition_table'); --test split partition ALTER TABLE ledgernsp.partition_table SPLIT PARTITION P4 AT (450) into (PARTITION P5, PARTITION P6); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index INSERT INTO ledgernsp.partition_table VALUES(700, '700'); UPDATE ledgernsp.partition_table SET c = '700c' WHERE a = 700; DELETE ledgernsp.partition_table WHERE a = 700; @@ -589,6 +590,7 @@ SELECT pg_catalog.selecthist('ledgernsp', 'partition_table'); --test add partition ALTER TABLE ledgernsp.partition_table SPLIT PARTITION P6 AT (2000) into (PARTITION P7, PARTITION P8); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index ALTER TABLE ledgernsp.partition_table DROP PARTITION P8; ERROR: Unsupport to ALTER the structure of blockchain related table [partition_table]. ALTER TABLE ledgernsp.partition_table ADD PARTITION P9 VALUES LESS THAN (MAXVALUE); @@ -603,6 +605,7 @@ SELECT pg_catalog.selecthist('ledgernsp', 'partition_table'); --test merge partition ALTER TABLE ledgernsp.partition_table MERGE PARTITIONS P5,P7 INTO PARTITION P6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index SELECT pg_catalog.selecthist('ledgernsp', 'partition_table'); selecthist ------------------------------------------- diff --git a/src/test/regress/output/partition_expr_key.source b/src/test/regress/output/partition_expr_key.source index 897d161d824844155a8bab62930878c86556c46d..8f76158512c0bdfb7c03316cf05efd06400de2ae 100644 --- a/src/test/regress/output/partition_expr_key.source +++ b/src/test/regress/output/partition_expr_key.source @@ -1255,6 +1255,31 @@ select count(*) from t partition (p_others); 1 (1 row) +-- test exprkey across partitions +create table test_exprkey_move_part( + a int, + b int +) +partition by range(a+100) +( + partition p0 values less than(1000), + partition p1 values less than(2000) +); +insert into test_exprkey_move_part values(888, 1); +update test_exprkey_move_part set a=1000 where a=888; +select * from test_exprkey_move_part; + a | b +------+--- + 1000 | 1 +(1 row) + +update test_exprkey_move_part set a=1001 where a=1000; +select * from test_exprkey_move_part; + a | b +------+--- + 1001 | 1 +(1 row) + \c regression drop database if exists part_expr_key_db; drop database if exists part_expr_key_db1; diff --git a/src/test/regress/output/plpgsql_reset_session.source b/src/test/regress/output/plpgsql_reset_session.source index be19443b59a89719088ebfc9485b8ee4705f153f..fee7de8942c39e4f20ec07b47d12fc2fc4351934 100644 --- a/src/test/regress/output/plpgsql_reset_session.source +++ b/src/test/regress/output/plpgsql_reset_session.source @@ -118,7 +118,7 @@ INFO: v1.last is true drop procedure proc094; drop package pkg094; NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to function public.p1(_timestamp[]) +--?.* drop cascades to function public.p2() drop table tytbl094; -- test global syscache @@ -173,7 +173,7 @@ end pkg096; call pkg096.p2(); INFO: c1 is {123455,ABCDEF,012345} CONTEXT: SQL statement "CALL p3(c1=>c1)" -PL/pgSQL function p1(_blob[],_blob[]) line 2 at PERFORM +--?.* SQL statement "CALL pkg096.p1(c1=>r1,c2=>r2)" PL/pgSQL function p2() line 9 at PERFORM INFO: c1 is {123455,ABCDEF,012345} @@ -201,7 +201,7 @@ INFO: r2 is {123455,ABCDEF,012345,678910} \! @abs_bindir@/gsql -r -p @portstring@ -d regression -c "call pkg096.p2();"; INFO: c1 is {123455,ABCDEF,012345} CONTEXT: SQL statement "CALL p3(c1=>c1)" -PL/pgSQL function p1(_blob[],_blob[]) line 2 at PERFORM +--?.* SQL statement "CALL pkg096.p1(c1=>r1,c2=>r2)" PL/pgSQL function p2() line 9 at PERFORM INFO: c1 is {123455,ABCDEF,012345} @@ -228,6 +228,6 @@ INFO: r2 is {123455,ABCDEF,012345,678910} drop package pkg096; NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to function public.p1(_blob[],_blob[]) +--?.* drop cascades to function public.p2() -drop cascades to function public.p3(_blob[]) +--?.* diff --git a/src/test/regress/output/recovery_2pc_tools.source b/src/test/regress/output/recovery_2pc_tools.source index fe71a564e9305681db89e0496ffa90c55f692c65..d1ca08e1f3e0fbf73a103589f080aff454405367 100644 --- a/src/test/regress/output/recovery_2pc_tools.source +++ b/src/test/regress/output/recovery_2pc_tools.source @@ -394,6 +394,7 @@ select name,vartype,unit,min_val,max_val from pg_settings where name <> 'qunit_c hadr_recovery_time_target | integer | | 0 | 3600 hadr_super_user_record_path | string | | | ha_module_debug | bool | | | + handle_toast_in_autovac | bool | | | hashagg_table_size | integer | | 0 | 1073741823 hba_file | string | | | hll_default_expthresh | int64 | | -1 | 7 @@ -650,7 +651,6 @@ select name,vartype,unit,min_val,max_val from pg_settings where name <> 'qunit_c ss_enable_dss | bool | | | ss_enable_ondemand_realtime_build | bool | | | ss_enable_ondemand_recovery | bool | | | - ss_enable_reform | bool | | | ss_enable_scrlock | bool | | | ss_enable_scrlock_sleep_mode | bool | | | ss_enable_ssl | bool | | | diff --git a/src/test/regress/output/timecapsule_partition_ustore_test_1.source b/src/test/regress/output/timecapsule_partition_ustore_test_1.source index e8bffd08f0e2d5a3454eaf692cae1e870cbaf772..d34617c3b5817e5da4279f028d17982e5e6ad0b5 100644 --- a/src/test/regress/output/timecapsule_partition_ustore_test_1.source +++ b/src/test/regress/output/timecapsule_partition_ustore_test_1.source @@ -531,6 +531,7 @@ select pg_sleep(4); insert into t_timecapsule_test_tmp select 2, now(), int8in(xidout(next_csn)) from gs_get_next_xid_csn(); ALTER TABLE PARTITION_TABLE_001 TRUNCATE PARTITION PARTITION_TABLE_001_1; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from PARTITION_TABLE_001 timecapsule csn findCsn(2); ERROR: The table definition of "partition_table_001" has been changed. select pg_sleep(4); @@ -541,6 +542,7 @@ select pg_sleep(4); insert into t_timecapsule_test_tmp select 3, now(), int8in(xidout(next_csn)) from gs_get_next_xid_csn(); ALTER TABLE PARTITION_TABLE_001 MERGE PARTITIONS PARTITION_TABLE_001_1,PARTITION_TABLE_001_2 INTO PARTITION PARTITION_TABLE_001_6; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from PARTITION_TABLE_001 timecapsule csn findCsn(3); ERROR: The table definition of "partition_table_001" has been changed. select pg_sleep(4); @@ -554,6 +556,7 @@ alter table PARTITION_TABLE_001 split PARTITION PARTITION_TABLE_001_5 into ( partition PARTITION_TABLE_001_5_1 values less than (80,80,900,900.2), partition PARTITION_TABLE_001_5_2 values less than (100,100,1000,1100.2) ); +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from PARTITION_TABLE_001 timecapsule csn findCsn(4); ERROR: The table definition of "partition_table_001" has been changed. select pg_sleep(4); @@ -574,6 +577,7 @@ select pg_sleep(4); insert into t_timecapsule_test_tmp select 6, now(), int8in(xidout(next_csn)) from gs_get_next_xid_csn(); ALTER TABLE PARTITION_TABLE_001 DROP PARTITION PARTITION_TABLE_001_4; +NOTICE: Command without UPDATE GLOBAL INDEX will disable global index select * from PARTITION_TABLE_001 timecapsule csn findCsn(6); ERROR: The table definition of "partition_table_001" has been changed. select pg_sleep(4); diff --git a/src/test/regress/output/trigger_dump.source b/src/test/regress/output/trigger_dump.source index e8c2a9d1926008f8be990b7d52ff29406d186f33..253887234a0feba46ccf9a6c75f02f8cd740d75e 100644 --- a/src/test/regress/output/trigger_dump.source +++ b/src/test/regress/output/trigger_dump.source @@ -61,7 +61,7 @@ insert into old_dump values(2,2); ERROR: permission denied for relation tab_dump DETAIL: N/A CONTEXT: SQL statement "insert into tab_dump values(new.id,new.c1)" -PL/pgSQL function tri_dump_old_dump_inlinefunc() line 2 at SQL statement +PL/pgSQL function tri_dump_old_dump_inlinefunc_1() line 2 at SQL statement \c test2_dump --insert insert into old_dump values(2,2); @@ -84,7 +84,7 @@ insert into old_dump values(2,2); ERROR: permission denied for relation tab_dump DETAIL: N/A CONTEXT: SQL statement "insert into tab_dump values(new.id,new.c1)" -PL/pgSQL function tri_dump_old_dump_inlinefunc() line 2 at SQL statement +PL/pgSQL function tri_dump_old_dump_inlinefunc_1() line 2 at SQL statement \c regression drop database test_dump; drop database test1_dump; diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index 2bddcfe01a84b88ec4ce65deb3a066ce84fbb056..a46154a1444cadd603f5c0a1b7a8dd09d633cf5e 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -723,7 +723,7 @@ test: sqlbypass_partition_prepare # Please fell free to execute each case independently test: srf_fusion srf_fusion_basic srf_fusion_agg -test: string_digit_to_numeric tablesample_3 +test: string_digit_to_numeric tablesample_3 tablesample_4 # Another group of parallel tests # ---------- #test: collate tablesample tablesample_1 tablesample_2 matview @@ -1126,4 +1126,4 @@ test: enable_expr_fusion_flatten # test for on update timestamp and generated column test: on_update_session1 on_update_session2 -test: ts_gb18030_utf8 \ No newline at end of file +test: ts_gb18030_utf8 diff --git a/src/test/regress/parallel_schedule0A b/src/test/regress/parallel_schedule0A index ed813acef5af728b13fbd9de43cd32f58bd1296e..0792fa344ad0d31f9625f7122b5639e78be930d7 100644 --- a/src/test/regress/parallel_schedule0A +++ b/src/test/regress/parallel_schedule0A @@ -98,7 +98,7 @@ test: event_dump_audit test: single_node_sha #test b format collation -test: test_b_format_collate charset_b_format +test: test_b_format_collate charset_b_format test_b_format_collate2 # test subpartition test: hw_subpartition_createtable hw_subpartition_scan hw_subpartition_select hw_subpartition_split hw_subpartition_truncate hw_subpartition_update hw_subpartition_gpi hw_subpartition_analyze_vacuum hw_subpartition_alter_table hw_subpartition_index hw_subpartition_add_drop_partition hw_subpartition_tablespace hw_subpartition_ddl_index hw_subpartition_size @@ -122,7 +122,7 @@ test: single_node_tablespace #test startwith...connect by test: sw_prepare -test: sw_basic sw_icbc sw_siblings sw_bugfix-1 sw_bugfix-2 sw_by_rownum_level +test: sw_basic sw_icbc sw_siblings sw_bugfix-1 sw_bugfix-2 sw_by_rownum_level sw_prior test: sw_clearup # test customer base environment hint @@ -476,4 +476,6 @@ test: alter_table_modify alter_table_modify_ustore alter_table_modify_ltt alter_ # test for empty string in A format database test: accept_empty_str not_accept_empty_str pg_empty_str accept_empty_copy not_accept_empty_copy -#test: with +#test: gin/cgin +test: cgin_select +test: gin_select diff --git a/src/test/regress/parallel_schedule0B b/src/test/regress/parallel_schedule0B index c23b89934577826abb1f69eab3276d9f1a536d4a..abb385c517e75cca17f92bebd22e32b471ff807d 100644 --- a/src/test/regress/parallel_schedule0B +++ b/src/test/regress/parallel_schedule0B @@ -243,7 +243,7 @@ test: sqlbypass_partition_prepare # Please fell free to execute each case independently test: srf_fusion srf_fusion_basic srf_fusion_agg -test: string_digit_to_numeric tablesample_3 +test: string_digit_to_numeric tablesample_3 tablesample_4 # Another group of parallel tests # ---------- #test: collate tablesample tablesample_1 tablesample_2 matview diff --git a/src/test/regress/single_check.sh b/src/test/regress/single_check.sh index 203eeda9492cc1f63f0f4000c46acad90cc618bd..2e8e3f3c52747c78789f0860091eb5c024c14377 100755 --- a/src/test/regress/single_check.sh +++ b/src/test/regress/single_check.sh @@ -141,6 +141,7 @@ function real_regresscheck_ss() { set_hotpatch_env set_common_env $1 $2 + set_cm_env if [ -d $TEMP_INSTALL ];then rm -rf $TEMP_INSTALL @@ -316,6 +317,11 @@ function check_enum() cd $old_path } +function set_cm_env() +{ + export CM_CONFIG_PATH=$ROOT_CODE_PATH/src/test/ss/cm_config.ini +} + function set_common_env() { export CODE_BASE=$ROOT_CODE_PATH/${OPENGS} diff --git a/src/test/regress/sql/alter_table_modify.sql b/src/test/regress/sql/alter_table_modify.sql index 64398e99f47b36ccef9a62a4d6003e4b5a86ea25..1730d035089893f8c6334d0eb54dfabf292f5b49 100644 --- a/src/test/regress/sql/alter_table_modify.sql +++ b/src/test/regress/sql/alter_table_modify.sql @@ -1345,6 +1345,18 @@ SELECT * FROM "test_modify_view_f1f2F3"; DROP VIEW "test_modify_view_f1f2F3"; DROP TABLE test_at_modify_view_column CASCADE; +-- test MODIFY after ADD COLUMN DEFAULT +CREATE TABLE test_modify_after_add ( + c1 INT, + value_column INT +); +insert into test_modify_after_add values (1,2); +ALTER TABLE test_modify_after_add ADD COLUMN c2 TIMESTAMP(5) default '2025-11-11 11:11:11'; +select * from test_modify_after_add; +ALTER TABLE test_modify_after_add MODIFY column c2 TIMESTAMP(5); +select * from test_modify_after_add; +DROP TABLE test_modify_after_add; + -- END RESET CURRENT_SCHEMA; DROP SCHEMA atbdb_schema CASCADE; diff --git a/src/test/regress/sql/autonomous_cursor.sql b/src/test/regress/sql/autonomous_cursor.sql index e65efb5df2746cab023323942713d33421864b82..959cb1b85ec3b975c6b38dcd8063c8f2defc045a 100644 --- a/src/test/regress/sql/autonomous_cursor.sql +++ b/src/test/regress/sql/autonomous_cursor.sql @@ -1536,6 +1536,68 @@ $$; drop function f1(); +create table source(c1 int,c2 varchar2(100)); +insert into source values(1,'aa'); +insert into source values(2,'bb'); +create table target(c1 int,c2 varchar2(100)); + +declare + cursor cur is + select c1,c2 from source; +begin + for data in cur loop + INSERT INTO target values(data.c1,data.c2); + end loop; +end; +/ + +declare + cursor cur is + select c1,c2 from source; +begin + for data in cur loop + INSERT INTO target values data; + end loop; +end; +/ + +declare +begin + for cur in (select c1,c2 from source) loop + insert into target values cur; + commit; + end loop; +end; +/ + +set behavior_compat_options = 'allow_procedure_compile_check'; +delete from target; + +declare + cursor cur is + select c1,c2 from source; +begin + for data in cur loop + INSERT INTO target values data; + end loop; +end; +/ + +select * from target order by c1; +delete from target; + +declare +begin + for cur in (select c1,c2 from source) loop + insert into target values cur; + end loop; +end; +/ + +select * from target order by c1; +drop table source; +drop table target; +reset behavior_compat_options; -- clean drop schema pl_auto_ref cascade; diff --git a/src/test/regress/sql/create_seg_table.sql b/src/test/regress/sql/create_seg_table.sql index c7f105e162405952080d2ee09f941518f952d2d1..e2f6c098a75287d978a9ebf3e66aa80eea918e35 100644 --- a/src/test/regress/sql/create_seg_table.sql +++ b/src/test/regress/sql/create_seg_table.sql @@ -9,12 +9,14 @@ show enable_segment; create table tab_segment(a int); create table tab_segment_off(a int) with(segment=off); create table tab_segment_on(a int) with(segment=on); +create table tab_segment_compress(a int) with(compresstype=2,compress_chunk_size=512,compress_level=1); \d+ tab_segment; \d+ tab_segment_off; \d+ tab_segment_on; drop table tab_segment; drop table if exists tab_segment_off; drop table if exists tab_segment_on; +drop table if exists tab_segment_compress; select pg_sleep(1); show enable_segment; alter system set enable_segment = off; diff --git a/src/test/regress/sql/event_trigger.sql b/src/test/regress/sql/event_trigger.sql index ec4a5d4a95b528c1f23ba5f4779a4dd426d6cefd..45eb0c7b3094076832249fd12a1c9e10f1497fda 100644 --- a/src/test/regress/sql/event_trigger.sql +++ b/src/test/regress/sql/event_trigger.sql @@ -550,6 +550,9 @@ revoke all on LANGUAGE sql from event_trigger_us; revoke all on TYPE event_trigger_tp from event_trigger_us; revoke all on schema event_trigger_sc from event_trigger_us; revoke all on function ddl_command_test() from event_trigger_us; + +alter table event_trigger_tt alter column a type bigint; + -- clean drop sequence event_trigger_ss; drop domain event_trigger_dm; diff --git a/src/test/regress/sql/gpi_set_index_unusable.sql b/src/test/regress/sql/gpi_set_index_unusable.sql index feb94b8e8d3fae0da6838f85d2fbcca8156064fe..ba15740e44001677cf17655777e63bebeaff0217 100644 --- a/src/test/regress/sql/gpi_set_index_unusable.sql +++ b/src/test/regress/sql/gpi_set_index_unusable.sql @@ -223,4 +223,121 @@ set enable_bitmapscan=on; set enable_seqscan=on; drop table if exists test_drop_llt; --- End. Clean up +--astore +CREATE TABLE web_returns_p_a +( + sk_date INTEGER, + cm_num INTEGER, + nv_num INTEGER, + cn_name INTEGER +) +with (STORAGE_TYPE=ASTORE) +PARTITION BY RANGE(sk_date) +( + PARTITION P1 VALUES LESS THAN(1), + PARTITION P2 VALUES LESS THAN(2), + PARTITION P3 VALUES LESS THAN(3), + PARTITION P4 VALUES LESS THAN(4), + PARTITION P5 VALUES LESS THAN(5), + PARTITION P6 VALUES LESS THAN(6), + PARTITION P7 VALUES LESS THAN(7), + PARTITION P8 VALUES LESS THAN(8), + PARTITION P9 VALUES LESS THAN(9), + PARTITION Pmax VALUES LESS THAN(MAXVALUE) +); + +insert into web_returns_p_a values (1,1,1,1); +insert into web_returns_p_a values (2,2,2,2); +insert into web_returns_p_a values (3,3,3,3); +insert into web_returns_p_a values (4,4,4,4); +insert into web_returns_p_a values (5,5,5,5); +insert into web_returns_p_a values (6,6,6,6); +insert into web_returns_p_a values (7,7,7,7); +insert into web_returns_p_a values (8,8,8,8); +insert into web_returns_p_a values (9,9,9,9); + +create index idx_cm_num_a on web_returns_p_a(cm_num) global; +create index idx_nv_num_a on web_returns_p_a(nv_num) local; +create unique index idx_uq_a on web_returns_p_a(sk_date) global; + +set behavior_compat_options = 'update_unusable_unique_index_on_iud'; +alter table web_returns_p_a drop partition p2; +insert into web_returns_p_a values (1,1,1,1); +insert into web_returns_p_a values (1,1,1,1); +update web_returns_p_a set sk_date = 1 where true; +set enable_opfusion = off; +insert into web_returns_p_a values (1,1,1,1); +insert into web_returns_p_a values (1,1,1,1); +update web_returns_p_a set sk_date = 1 where true; +set enable_opfusion = on; +alter index idx_uq_a rebuild; +alter table web_returns_p_a drop partition p3; +reset behavior_compat_options; +insert into web_returns_p_a values (2,2,2,2); +insert into web_returns_p_a values (2,2,2,2); +reset behavior_compat_options; + +-- ustore +CREATE TABLE web_returns_p_u +( + sk_date INTEGER, + cm_num INTEGER, + nv_num INTEGER, + cn_name INTEGER +) +with (STORAGE_TYPE=ASTORE) +PARTITION BY RANGE(sk_date) +( + PARTITION P1 VALUES LESS THAN(1), + PARTITION P2 VALUES LESS THAN(2), + PARTITION P3 VALUES LESS THAN(3), + PARTITION P4 VALUES LESS THAN(4), + PARTITION P5 VALUES LESS THAN(5), + PARTITION P6 VALUES LESS THAN(6), + PARTITION P7 VALUES LESS THAN(7), + PARTITION P8 VALUES LESS THAN(8), + PARTITION P9 VALUES LESS THAN(9), + PARTITION Pmax VALUES LESS THAN(MAXVALUE) +); + +insert into web_returns_p_u values (1,1,1,1); +insert into web_returns_p_u values (2,2,2,2); +insert into web_returns_p_u values (3,3,3,3); +insert into web_returns_p_u values (4,4,4,4); +insert into web_returns_p_u values (5,5,5,5); +insert into web_returns_p_u values (6,6,6,6); +insert into web_returns_p_u values (7,7,7,7); +insert into web_returns_p_u values (8,8,8,8); +insert into web_returns_p_u values (9,9,9,9); + +create index idx_cm_num_u on web_returns_p_u(cm_num) global; +create index idx_nv_num_u on web_returns_p_u(nv_num) local; +create unique index idx_uq_u on web_returns_p_u(sk_date) global; + +set behavior_compat_options = 'update_unusable_unique_index_on_iud'; +alter table web_returns_p_u drop partition p2; +insert into web_returns_p_u values (1,1,1,1); +insert into web_returns_p_u values (1,1,1,1); +update web_returns_p_u set sk_date = 1 where true; +set enable_opfusion = off; +insert into web_returns_p_u values (1,1,1,1); +insert into web_returns_p_u values (1,1,1,1); +update web_returns_p_u set sk_date = 1 where true; +set enable_opfusion = on; +alter index idx_uq_u rebuild; + +alter table web_returns_p_u drop partition p3; +reset behavior_compat_options; +insert into web_returns_p_u values (2,2,2,2); +insert into web_returns_p_u values (2,2,2,2); + +drop index idx_cm_num_a; +drop index idx_nv_num_a; +drop index idx_uq_a; +drop table web_returns_p_a; +drop index idx_cm_num_u; +drop index idx_nv_num_u; +drop index idx_uq_u; +drop table web_returns_p_u; + +-- End. Clean u diff --git a/src/test/regress/sql/hw_cursor_part4.sql b/src/test/regress/sql/hw_cursor_part4.sql index ed3c0167bed41144d46a7fdb968bd637ca3a7293..d465451d54713407baf39b505adf1e0322e4ab96 100644 --- a/src/test/regress/sql/hw_cursor_part4.sql +++ b/src/test/regress/sql/hw_cursor_part4.sql @@ -295,5 +295,86 @@ END; CALL TEST_CRS_RPT_EMPTYSOR(0); CALL TEST_CRS_RPT_EMPTYSOR(1); +--test strong cursor +create table tb1(a int); +create table tb2(a int, b text); +insert into tb1 values(1); +insert into tb2 values(1,'one'),(2,'two'); + +declare + type cur1 is ref cursor return record; + var cur1; +begin + open var for select * from tb1; +end; +/ + +declare + type cur1 is ref cursor return; +begin + null; +end; +/ + +declare + type cur1 is ref cursor return int[]; +begin + null; +end; +/ + +create type typ1_rec as (a int, b text); +declare + type cur1 is ref cursor return typ1_rec; +begin + null; +end; +/ +drop type typ1_rec; + +--use in function +create or replace function func1() return int as +declare + type cur1 is ref cursor return tb1%rowtype; + var cur1; + res int; +begin + open var for select * from tb1; + fetch var into res; + return res; +end; +/ +call func1(); +drop function func1; + +--use in package +create or replace package pkg1 as + type typ1 is record(a int, b text); + type cur1 is ref cursor return typ1; + procedure proc1(a inout cur1); +end pkg1; +/ + +create or replace package body pkg1 as + procedure proc1(a inout cur1) is + declare + var cur1; + res record; + begin + open var for select * from tb2; + fetch var into res; + raise info 'res = %',res; + end; +end pkg1; +/ + +declare + var pkg1.cur1; +begin + pkg1.proc1(var); +end; +/ +drop package pkg1; + DROP schema hw_cursor_part4 CASCADE; diff --git a/src/test/regress/sql/hw_package.sql b/src/test/regress/sql/hw_package.sql index 34da3c4cfbbecbde2257bb07da9895d47a8ba59d..7dd49bcfec11286375c84db3440512eea1a4c439 100644 --- a/src/test/regress/sql/hw_package.sql +++ b/src/test/regress/sql/hw_package.sql @@ -2303,6 +2303,53 @@ end pck3; create user package_user password 'gauss@123'; alter package pck3 owner to package_user; +-- test methods schema not consistent with object +create schema multi_schema_001; +-- failed +create or replace package public.multi_shema_package is +var1 int:=1; --公有变量 +var2 int:=2; +procedure multi_schema_001.testpro1(var3 int); --公有存储过程,可以被外部调用 +end multi_shema_package; +/ +-- failed +create or replace package multi_schema_001.multi_shema_package is +var1 int:=1; --公有变量 +var2 int:=2; +procedure public.testpro1(var3 int); --公有存储过程,可以被外部调用 +end multi_shema_package; +/ +-- succeed +create or replace package multi_schema_001.multi_shema_package is +var1 int:=1; --公有变量 +var2 int:=2; +procedure multi_schema_001.testpro1(var3 int); --公有存储过程,可以被外部调用 +end multi_shema_package; +/ +-- failed +create or replace package body multi_schema_001.multi_shema_package is +var3 int:=3; +var4 int:=4; +procedure public.testpro1(var3 int) +is +begin +end; +end multi_shema_package; +/ +-- succeed +create or replace package body multi_schema_001.multi_shema_package is +var3 int:=3; +var4 int:=4; +procedure multi_schema_001.testpro1(var3 int) +is +begin +end; +end multi_shema_package; +/ +-- clean +drop package multi_schema_001.multi_shema_package; +drop schema multi_schema_001; + drop package pck1; drop package pck2; drop package pck3; diff --git a/src/test/regress/sql/hw_to_timestamp.sql b/src/test/regress/sql/hw_to_timestamp.sql index e557ac6a0e3c32fb3a4b8b67929c4127f1c88d49..2f7c46ba2e21eaf5397a9766004aed9176dce830 100644 --- a/src/test/regress/sql/hw_to_timestamp.sql +++ b/src/test/regress/sql/hw_to_timestamp.sql @@ -278,4 +278,5 @@ SELECT to_date('1992-01-01 12:34:56.500000000000'); SELECT to_date('19920101123456'); SELECT to_date('19920101123456.5848954380543'); SELECT to_date('19920101123456.5000000000000'); -SELECT to_date('19920101123456.4999999999999'); \ No newline at end of file +SELECT to_date('19920101123456.4999999999999'); +SELECT to_date('202201 ', 'yyyymm'); diff --git a/src/test/regress/sql/ignore/ignore_unique_constraints.sql b/src/test/regress/sql/ignore/ignore_unique_constraints.sql index 3cadd434076ba5ae80b5a6deea2ca581da0f8afe..c0455cca3fc6f61159fcbb0c0814b4781fb5a0f7 100644 --- a/src/test/regress/sql/ignore/ignore_unique_constraints.sql +++ b/src/test/regress/sql/ignore/ignore_unique_constraints.sql @@ -217,5 +217,29 @@ insert /*+ ignore_error */ into t_column_orien values(null); update /*+ ignore_error */ t_column_orien set c1 = null where c1 = 2; update /*+ ignore_error */ t_column_orien set c1 = 1 where c1 = 2; +--test under opfusion+prepare +set enable_opfusion = on; +set enable_bitmapscan to off; +set enable_seqscan to off; + +create table t_ignore_0037(c1 int primary key, c2 number(5,2)); +create index i_test on t_ignore_0037(c2); +analyze t_ignore_0037; +prepare insert_ignore(int,number(5,2)) as insert /*+ ignore_error */ into t_ignore_0037 values(1,2); +explain(costs off) execute insert_ignore(0, 123.12); +execute insert_ignore(0, 123.12); +execute insert_ignore(0, 123.12); + +insert into t_ignore_0037 values(3,1); +insert into t_ignore_0037 values(4,1); + +prepare update_ignore(int) as update /*+ ignore_error */ t_ignore_0037 set c1=$1 where c2=1; +explain(costs off) execute update_ignore(0); +execute update_ignore(0); +execute update_ignore(0); +reset enable_bitmapscan; +reset enable_seqscan; +DEALLOCATE all; + \c postgres drop database if exists sql_ignore_unique_test; \ No newline at end of file diff --git a/src/test/regress/sql/invisible_index.sql b/src/test/regress/sql/invisible_index.sql index bd283270a83f0625681f057fd1e3bbdeea094412..2ff1d829188e068b2280033920459d9cb2c2434b 100644 --- a/src/test/regress/sql/invisible_index.sql +++ b/src/test/regress/sql/invisible_index.sql @@ -2,11 +2,25 @@ create schema invisible_index; set search_path to 'invisible_index'; -create table t1 (a int, b int, constraint key_a primary key(a) visible); --error - -create table t1 (a int, b int, constraint key_a primary key(a)); -alter table t1 alter index key_a invisible; --error -alter table t1 add constraint key_b unique (b) visible; --error +create table t1 (a int, b int, constraint key1 primary key(a) visible); +alter table t1 alter index key1 invisible; +alter table t1 add constraint key2 unique (b) visible; + +create table t2 (a int, b int, constraint key3 primary key(a) invisible); +alter table t2 alter index key3 visible; +alter table t2 add constraint key4 unique (b) invisible; + +create table t3 (a int, b int); +create index key5 on t3(a) visible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; +alter index key5 invisible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; + +create table t4 (a int, b int); +create index key6 on t4(a) invisible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; +alter index key6 visible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; reset search_path; drop schema invisible_index cascade; @@ -21,6 +35,18 @@ alter table t1 alter index key_b visible, alter index key_b invisible; select indkey, indisvisible from pg_index where indrelid = 't1'::regclass order by indkey; +create table t3 (a int, b int); +create index key5 on t3(a) visible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; +alter index key5 invisible; +select indkey, indisvisible from pg_index where indrelid = 't3'::regclass order by indkey; + +create table t4 (a int, b int); +create index key6 on t4(a) invisible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; +alter index key6 visible; +select indkey, indisvisible from pg_index where indrelid = 't4'::regclass order by indkey; + insert into t1 values (generate_series(1, 100), generate_series(1, 100)); analyze t1; diff --git a/src/test/regress/sql/multi_update.sql b/src/test/regress/sql/multi_update.sql index ece4cbf3e047831213a46a5e9db2b928af71b1d0..ea8c483347d9150c17e18d4bb51592656436b9e7 100644 --- a/src/test/regress/sql/multi_update.sql +++ b/src/test/regress/sql/multi_update.sql @@ -695,5 +695,22 @@ drop table t1; drop view v1; drop table t2; +-- except no core +set query_dop = 6; +drop table if exists t_t_mutil_t1; +drop table if exists t_t_mutil_t2; +drop table if exists t_t_mutil_t3; +create table t_t_mutil_t1(col1 int,col2 int); +create table t_t_mutil_t2(col1 int,col2 int); +create table t_t_mutil_t3(col1 int,col2 int); +insert into t_t_mutil_t1 values(generate_series(1,1000000),generate_series(1,1000000)); +insert into t_t_mutil_t2 values(generate_series(1,1000000),generate_series(1,1000000)); +insert into t_t_mutil_t3 values(generate_series(1,1000000),generate_series(1,1000000)); +explain(costs off, verbose) update/*+nestloop(a b)*/ t_t_mutil_t1 a,t_t_mutil_t2 b set b.col1=5,a.col2=4 where a.col1=b.col1; +drop table if exists t_t_mutil_t1; +drop table if exists t_t_mutil_t2; +drop table if exists t_t_mutil_t3; +reset query_dop; + \c regression drop database multiupdate; diff --git a/src/test/regress/sql/mysql_delimiter_ustore.sql b/src/test/regress/sql/mysql_delimiter_ustore.sql new file mode 100644 index 0000000000000000000000000000000000000000..3993f9172c17480a1a42ea8dabd5e8811f0a6da1 --- /dev/null +++ b/src/test/regress/sql/mysql_delimiter_ustore.sql @@ -0,0 +1,135 @@ +-- B db compatibility case +drop database if exists my_test; +create database my_test dbcompatibility 'B'; +\c my_test + +--Test default delimiter +select 1; + +--Test delimiter aa +delimiter aa; +select 1aa +select 1aaselect 1;aa +select kaa +delimiter ;aa + +--Test delimiter // +delimiter //; +select 1// +delimiter ;// + +--Test delimiter length +delimiter "" +delimiter '' +delimiter aaaaaaaaaaaaaaaa +delimiter "aaaaaaaaaaaaaaaa" +delimiter aaaaaaaaaaaaaaa +delimiter ; + +--Test delimiter % +delimiter %; +select 1% +delimiter ;% + +--Test delimiter 'Mysql' +delimiter 'Mysql'; +select 1Mysql +delimiter ;Mysql + +--Test other +delimiter sds; +delimiter aasds +select 1aasds +delimiter ;aasds + +-- +delimiter asd ss; +select 1asd +delimiter ;asd + +delimiter bb +delimiter aa +select 1aa +delimiter ; + +delimiter de +delimiter abcde +select 1abcde +delimiter zz sdsd aasds +delimiter kkasda "sdsd" sdsda +select 1kkasda +delimiter +delimiter "sdsd sd" +select 1"sdsd sd" +delimiter ; + +-- test delimiter use in create procedure situation +-- report gram error in server ,not subprogram end error, success in plugin +create table test_table (dot_no int) with (storage_type = ustore); +insert into test_table values(1); +insert into test_table values(NULL); + +delimiter // + +create procedure test91() +begin + declare rec_curs_value int; + declare curs_dot cursor for select dot_no from test_table; + open curs_dot; + fetch curs_dot into rec_curs_value; + while rec_curs_value is not null do + fetch curs_dot into rec_curs_value; + end while; + close curs_dot; +end; +// +delimiter ; + + +delimiter // + +create procedure test92() +begin + declare rec_curs_value int; + declare curs_dot cursor for select dot_no from test_table; + open curs_dot; + fetch curs_dot into rec_curs_value; + while rec_curs_value is null do + fetch curs_dot into rec_curs_value; + end while; + close curs_dot; +end; +// + +delimiter ; + + +-- test deterministic error + +create function fun2(age1 int)return int DETERMINISTIC +NOT SHIPPABLE NOT FENCED EXTERNAL SECURITY INVOKER +AS +declare +a1 int; +begin +return a1; +end; +/ + +select fun2(1); + +-- test create procedure select error +create table t1 (a int) with (storage_type = ustore); + +insert into t1 values (1),(2); + +-- server should has gram error,plugin pass +create procedure pro_test() select a from t1; + +-- server should has gram error, plugin pass; +create procedure pro_test2() select a as b from t1; + + + +\c regression +drop database my_test; diff --git a/src/test/regress/sql/mysql_trigger.sql b/src/test/regress/sql/mysql_trigger.sql index 62debccbb4a7bcc061e89bf9f8be41c2475fe80d..3056e80be6e123f63f3133a6ff777a7605a731c7 100644 --- a/src/test/regress/sql/mysql_trigger.sql +++ b/src/test/regress/sql/mysql_trigger.sql @@ -567,6 +567,52 @@ end; alter trigger testscm.animals_trigger2 on animals_scm rename to animals_trigger2_1; drop trigger testscm.animals_trigger2_1 on animals_scm; set search_path to public; + +--bugfix for name long +drop table if exists T_ignore_case_in_dquotes_use_case0007; +drop table if exists T_ignore_case_in_dquotes_use_case0007_1; +create table T_ignore_case_in_dquotes_use_case0007(col1 int,col2 varchar(20)); +create table T_ignore_case_in_dquotes_use_case0007_1(col1 int,col2 varchar(20)); + +create trigger Tri_ignore_case_in_dquotes_use_case0007 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + +create trigger Tri_ignore_case_in_dquotes_use_case0008 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + +create trigger Tri_ignore_case_in_dquotes_use_case0009 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + + +create trigger Tri_ignore_case_in_dquotes_use_case0011 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + +insert into T_ignore_case_in_dquotes_use_case0007 values(11,'test'); + +select * from T_ignore_case_in_dquotes_use_case0007; + +select * from T_ignore_case_in_dquotes_use_case0007_1; + -- 1.5 cleanup \c regression drop database testdb_m; @@ -620,6 +666,7 @@ for each row execute procedure food_insert_func(); alter trigger testscm_no.animals_trigger2 on testscm.animals_scm rename to animals_trigger2_1; drop trigger testscm_no.animals_trigger2; + -- 2.2 cleanup \c regression drop database testdb; \ No newline at end of file diff --git a/src/test/regress/sql/orderby_in_subselect.sql b/src/test/regress/sql/orderby_in_subselect.sql new file mode 100644 index 0000000000000000000000000000000000000000..aa1910ea82f4181cf7348ab6fc1e5a985ed2fcc3 --- /dev/null +++ b/src/test/regress/sql/orderby_in_subselect.sql @@ -0,0 +1,70 @@ +DROP TABLE if exists zytest1; +DROP TABLE if exists zytest2; +DROP TABLE if exists zytest3; + +CREATE TABLE zytest1 +(aid NUMERIC, +name varchar(20) +); + +CREATE TABLE zytest2 +(bid NUMERIC, +des varchar(20), +zid NUMERIC --zytest1.aid +); + +CREATE TABLE zytest3 +(aid NUMERIC, ----zytest1.aid +numb NUMERIC -- +); + +INSERT INTO zytest1 values(1,'NAME1'); +INSERT INTO zytest1 values(2,'NAME2'); +INSERT INTO zytest1 values(3,'NAME3'); +INSERT INTO zytest1 values(4,'NAME4'); +INSERT INTO zytest1 values(5,'NAME5'); +INSERT INTO zytest1 values(6,'NAME6'); + +INSERT INTO zytest2 values(1,'des1',1); +INSERT INTO zytest2 values(2,'des2',2); +INSERT INTO zytest2 values(3,'des3',3); +INSERT INTO zytest2 values(4,'des4',4); +INSERT INTO zytest2 values(5,'des5',5); +INSERT INTO zytest2 values(6,'des6',6); + +INSERT INTO zytest3 values(1,1); +INSERT INTO zytest3 values(2,2); +INSERT INTO zytest3 values(3,3); +INSERT INTO zytest3 values(1,4); +INSERT INTO zytest3 values(2,5); +INSERT INTO zytest3 values(3,6); + +SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +ORDER BY bid +) +WHERE nsum IS NOT NULL OR nsum>5; + +explain (analyze, costs off, timing off) SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +ORDER BY bid +) +WHERE nsum IS NOT NULL OR nsum>5; + +SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +) +WHERE nsum IS NOT NULL OR nsum>5 ORDER BY bid; + +explain (analyze, costs off, timing off) SELECT * +FROM ( +SELECT bid,COALESCE((SELECT SUM(numb) FROM zytest3 WHERE aid = zid),0) nsum +FROM zytest2 +) +WHERE nsum IS NOT NULL OR nsum>5 ORDER BY bid; diff --git a/src/test/regress/sql/out_param_func.sql b/src/test/regress/sql/out_param_func.sql index def6c25c9a406e32706435ec2087ddeb4bf64e48..225643664fae7864ad0113847d3b07a96968d940 100644 --- a/src/test/regress/sql/out_param_func.sql +++ b/src/test/regress/sql/out_param_func.sql @@ -922,6 +922,16 @@ select pck1.f1(10,(1,'a',2)); select *from pck1.f1(10,(1,'a',2)); call pck1.f1(10,(1,'a',2)); +-- test expect no core +drop function if exists v_func1; +create FUNCTION v_func1(c4 variadic integer[]) RETURN int is +BEGIN +raise notice 'c4 = %', c4; +return 1; +END; +/ +select v_func1(1, 2, 3); +drop function v_func1; --clean reset behavior_compat_options; diff --git a/src/test/regress/sql/plpgsql_depend/plpgsql_pkg_dependency.sql b/src/test/regress/sql/plpgsql_depend/plpgsql_pkg_dependency.sql index 605af9f4a29f4e90547df1690fac915e235b010f..19a9b92eb46404021a5a4c0838da0c0b5178f90b 100644 --- a/src/test/regress/sql/plpgsql_depend/plpgsql_pkg_dependency.sql +++ b/src/test/regress/sql/plpgsql_depend/plpgsql_pkg_dependency.sql @@ -3,6 +3,7 @@ create schema plpgsql_pkg_dependency; set current_schema = plpgsql_pkg_dependency; set behavior_compat_options = 'plpgsql_dependency'; +-- test 1 create or replace package test_package_depend2_pkg is type t is record (col1 int, col2 text); procedure p1(param test_package_depend3_pkg.t); @@ -35,6 +36,55 @@ call test_package_depend3_pkg.p1((1,'a')); drop package if exists test_package_depend2_pkg; drop package if exists test_package_depend3_pkg; +-- test 2 +create or replace package pkg1 is +type x is record(tt int); +procedure a(zz pkg2.x); +end pkg1; +/ +create or replace package body pkg1 is +procedure a(zz pkg2.x) is +begin +null; +end; +end pkg1; +/ + +create or replace package pkg2 is +type x is record(tt int); +procedure a(zz pkg1.x); +end pkg2; +/ +create or replace package body pkg2 is +procedure a( zz pkg1.x) is +begin +null; +end; +end pkg2; +/ + +\parallel on 2 +begin +perform pkg1.a(row(1)); +perform pg_sleep(1.5); +perform pkg2.a(row(1)); +perform pg_sleep(2.5); +end; +/ + +begin +perform pg_sleep(0.5); +perform pkg2.a(row(1)); +perform pg_sleep(2.5); +perform pkg1.a(row(1)); +perform pg_sleep(2.5); +end; +/ +\parallel off + +drop package if exists pkg1; +drop package if exists pkg2; + -- clean drop schema plpgsql_pkg_dependency cascade; -reset behavior_compat_options; \ No newline at end of file +reset behavior_compat_options; diff --git a/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql b/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql index 2543465212b207b38feaa81de04fab3347059e74..ba1724b273d5a7957e0c7ab0c1b9e9b3f5e5b279 100644 --- a/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql +++ b/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql @@ -256,6 +256,32 @@ drop type r1; drop table stu; drop procedure test_proc; +-- test 7 +set behavior_compat_options = 'plpgsql_dependency'; +create or replace package pkg1 is +type tttt is record (col1 int, col2 text); +procedure p1(param pkg2.tqqq); +end pkg1; +/ +create or replace package pkg2 is +type tqqq is record (col1 int, col2 text, col3 varchar); +procedure p1(param pkg1.tttt); +end pkg2; +/ +create or replace package body pkg2 is +procedure p1(param pkg1.tttt) is +begin +RAISE INFO 'call param: %', param; +end; +end pkg2; +/ + +call pkg2.p1((1,'a')); +set behavior_compat_options =''; +drop package pkg1; +set behavior_compat_options = 'plpgsql_dependency'; +drop package pkg2; + -- clean drop schema plpgsql_recompile_new cascade; drop schema plpgsql_recompile cascade; diff --git a/src/test/regress/sql/plpgsql_package_type.sql b/src/test/regress/sql/plpgsql_package_type.sql index 38b22eba2503a239396aa7494143da8666fcaaa9..83c4af4ff1b9f83eecbd421aa8ad5b7ff3bfba76 100644 --- a/src/test/regress/sql/plpgsql_package_type.sql +++ b/src/test/regress/sql/plpgsql_package_type.sql @@ -1122,6 +1122,40 @@ procedure p1; end pak1 ; / +set behavior_compat_options='allow_procedure_compile_check'; +create table int_4(a NUMBER, b VARCHAR2(5)); +insert into int_4(a, b) values(3,'johan'); +create or replace package pck3_1 is +var1 RECORD; +procedure ppp1; +procedure ppp2(a int); +end pck3_1; +/ + +create or replace package body pck3_1 is +procedure ppp1() is +query_str text; +begin +ppp2(9); +raise info '(ppp1)var1: %', var1.a; +end; + +procedure ppp2(a int) is +query_str text; +begin + query_str := 'select a,b from int_4'; + FOR var1 IN EXECUTE(query_str) LOOP + raise info '[ppp2]var1: %', var1.a; + END LOOP; + var1.a:=8+var1.a; + raise info '[ppp2]var1: %', var1.a; +end; +end pck3_1; +/ +call pck3_1.ppp1(); +drop table int_4 cascade; +set behavior_compat_options=''; + -------------------------------------------------- ------------------ END OF TESTS ------------------ -------------------------------------------------- @@ -1129,7 +1163,7 @@ drop package pak1; drop package p_test2; drop package plpgsql_packagetype1.p_test2; drop package plpgsql_packagetype1.p_test1; - +drop package pck3_1; -- clean up -- drop schema if exists plpgsql_packagetype2 cascade; drop schema if exists plpgsql_packagetype1 cascade; diff --git a/src/test/regress/sql/plpgsql_table_opengauss.sql b/src/test/regress/sql/plpgsql_table_opengauss.sql index ff62e0c05229e4ae55aee15abb0c9116c7b96551..323898b37488e7cb1094133c4cc374d31e0fdd25 100644 --- a/src/test/regress/sql/plpgsql_table_opengauss.sql +++ b/src/test/regress/sql/plpgsql_table_opengauss.sql @@ -769,6 +769,20 @@ end; / call func2(); +-- test pg_get_function_result and pg_get_function_arguments +create type ty_test is(col1 int,col2 char(10),col3 varchar2(10)); +create type tyt_test is table of ty_test; +CREATE OR REPLACE PROCEDURE sp_tyt(i_tyt in tyt_test, o_tyt out tyt_test) +AS DECLARE +begin +o_tyt := i_tyt; +end; +/ +\df plpgsql_table_opengauss.sp_tyt +drop procedure sp_tyt; +drop type tyt_test; +drop type ty_test; + drop type typeA; drop type typeB; drop type s_type cascade; diff --git a/src/test/regress/sql/reduce_orderby.sql b/src/test/regress/sql/reduce_orderby.sql index 412cf5aa66d1d1b652c979884e3b0ec943488ea1..d55d3463e360bd7b6e6c3ea5f55855dac19fc8d0 100644 --- a/src/test/regress/sql/reduce_orderby.sql +++ b/src/test/regress/sql/reduce_orderby.sql @@ -35,6 +35,50 @@ explain (costs off) select t1.a from reduce_orderby_t1 t1 where t1.b in (select --drop table drop table reduce_orderby_t1; drop table reduce_orderby_t2; + +CREATE TABLE orders (user_id int, order_id int, order_date date, quantity int, revenue float, product text); +INSERT INTO orders VALUES +(1, 1, '2021-03-05', 1, 15, 'books'), +(1, 2, '2022-03-07', 1, 3, 'music'), +(1, 3, '2022-06-15', 1, 900, 'travel'), +(1, 4, '2021-11-17', 2, 25, 'books'), +(2, 5, '2022-08-03', 2, 32, 'books'), +(2, 6, '2021-04-12', 2, 4, 'music'), +(2, 7, '2021-06-29', 3, 9, 'books'), +(2, 8, '2022-11-03', 1, 8, 'music'), +(3, 9, '2022-11-07', 1, 575, 'food'), +(3, 10, '2022-11-20', 2, 95, 'food'), +(3, 11, '2022-11-20', 1, 95, 'food'), +(4, 12, '2022-11-20', 2, 95, 'books'), +(4, 13, '2022-11-21', 1, 95, 'food'), +(4, 14, '2022-11-23', 4, 17, 'books'), +(5, 15, '2022-11-20', 1, 95, 'food'), +(5, 16, '2022-11-25', 2, 95, 'books'), +(5, 17, '2022-11-29', 1, 95, 'food'); + +explain (costs off) SELECT avg(o.quantity) AS avg_quantity, +sum(o.revenue) AS total_revenue +FROM ( +SELECT DISTINCT ON (user_id) +user_id, product +FROM orders +ORDER BY user_id, order_date +) init +JOIN orders o USING (user_id, product) +WHERE init.product = 'books'; + +SELECT avg(o.quantity) AS avg_quantity, +sum(o.revenue) AS total_revenue +FROM ( +SELECT DISTINCT ON (user_id) +user_id, product +FROM orders +ORDER BY user_id, order_date +) init +JOIN orders o USING (user_id, product) +WHERE init.product = 'books'; + +drop table orders; --drop schema reset current_schema; drop schema reduce_orderby cascade; diff --git a/src/test/regress/sql/single_node_triggers.sql b/src/test/regress/sql/single_node_triggers.sql index 0dd9398d673c92aa24ddef085878b5edfd96f371..ef0e06fe9eea877acf3d7b279289fdb6dd8eedf7 100644 --- a/src/test/regress/sql/single_node_triggers.sql +++ b/src/test/regress/sql/single_node_triggers.sql @@ -1198,3 +1198,48 @@ drop table t1; drop table t2; drop function t1_tri_func; drop schema part_bri_warnning; + +create schema test_schema_for_trigger; +set current_schema to test_schema_for_trigger; +--触发器测试 +--测试时用到的package +CREATE OR REPLACE PACKAGE func_test_pkg1 AS + -- integer 类型的变量 + int_val INTEGER := 0; + + -- record 类型的定义 + TYPE rec_type IS RECORD ( + msg VARCHAR2(100) + ); + + PROCEDURE proc1; +END func_test_pkg1; +/ +CREATE OR REPLACE PACKAGE BODY func_test_pkg1 AS + PROCEDURE proc1 AS + BEGIN + RAISE NOTICE 'In func_test_pkg1.proc1()'; + END proc1; +END func_test_pkg1; +/ + +CREATE TABLE trg_test(id int, name text); +create or replace function global_cache_trigger_test() + return TRIGGER as + begin + func_test_pkg1.int_val = func_test_pkg1.int_val + 1; + raise notice 'func_test_pkg1.int_val=%',func_test_pkg1.int_val; + return new; +end; +/ + +CREATE TRIGGER trigger_global_cache_trigger_test +AFTER INSERT ON trg_test +FOR EACH ROW +EXECUTE PROCEDURE global_cache_trigger_test(); + +insert into trg_test values(1,'引用package中的变量'); +insert into trg_test values(1,'引用package中的变量'); + +drop package func_test_pkg1; +drop schema test_schema_for_trigger cascade; \ No newline at end of file diff --git a/src/test/regress/sql/sw_bugfix-1.sql b/src/test/regress/sql/sw_bugfix-1.sql index b651d654173fffcda862953a1828385677fe32fe..73b8a05b20704cbf31b8998b0ebd5de63a298a9c 100644 --- a/src/test/regress/sql/sw_bugfix-1.sql +++ b/src/test/regress/sql/sw_bugfix-1.sql @@ -522,3 +522,24 @@ select max(name) from test3 connect by parentid = prior id group by sys_connect_ drop table test3; drop table test2; drop table test1; + +drop table if exists left_table; +drop table if exists right_table; +create table left_table(id int); +create table right_table(id int); + +declare +i int:=0; +begin +for i in 1..5 loop +insert into left_table values(i); +insert into right_table values(i+1); +end loop; +commit; +end; +/ + +select left_table.id as id1,right_table.id as id2 from left_table,right_table where left_table.id+1=right_table.id start with left_table.id=1 connect by prior right_table.id=left_table.id; + +drop table left_table; +drop table right_table; \ No newline at end of file diff --git a/src/test/regress/sql/sw_bugfix-2.sql b/src/test/regress/sql/sw_bugfix-2.sql index ae91aaa597e4c9859b11feeaad22667de4893bfa..d98ff79005179a596cf0a268f07510313d9c1c10 100644 --- a/src/test/regress/sql/sw_bugfix-2.sql +++ b/src/test/regress/sql/sw_bugfix-2.sql @@ -642,6 +642,37 @@ SELECT * FROM RLTEST CONNECT BY NOCYCLE PRIOR B=A AND (MOD(ROWNUM+1,2) = 0); SELECT * FROM RLTEST CONNECT BY PRIOR B=A OR (LEVEL < 1 OR ROWNUM < 2); SELECT * FROM RLTEST CONNECT BY PRIOR B=A AND (LEVEL=1 OR B<10) AND (ROWNUM<3 OR PRIOR A=B); SELECT * FROM RLTEST CONNECT BY PRIOR B=A OR (MOD(ROWNUM+1,2) = 0); + +-- test for multi table join used with pseudo col in where clause +delete from rltest; +INSERT INTO RLTEST VALUES('1','2'),('2','3'),('3','1'); +explain select * from rltest r1,rltest r2 where r1.a<=connect_by_isleaf+level+connect_by_iscycle+connect_by_root(r1.a) start with r1.a=1 connect by nocycle prior r2.b=r1.a; +select * from rltest r1,rltest r2 where r1.a<=connect_by_isleaf+level+connect_by_iscycle+connect_by_root(r1.a) start with r1.a=1 connect by nocycle prior r2.b=r1.a; + +-- test cross reference in start with nested query +create table test_t1(a1 int,b1 int); +create table test_t2(a2 int,b2 int); +create table test_t3(a3 int,b3 int); +insert into test_t1 values(1,2),(2,3),(3,1); +insert into test_t2 values(1,2),(2,3),(3,1); +insert into test_t3 values(1,2),(2,3),(3,1); +explain select * from test_t1 left join test_t2 on a1=a2 where exists (select 1 from test_t3 where a1+a2 is not null connect by level<2) connect by level<2; +drop table test_t1; +drop table test_t2; +drop table test_t3; + +-- test sys funcs in multi table join +select sys_connect_by_path(r1.a,'->') from rltest r1, rltest r2 where r1.a=r2.a connect by level<2; +select connect_by_root(r1.a) from rltest r1, rltest r2 where r1.a=r2.a connect by level<2; +-- test for where push down +create table sin_col_tbl(a int); +SELECT 1 +FROM sin_col_tbl, + rltest +WHERE (sin_col_tbl.a+rltest.b) IS NOT NULL +START WITH 1=1 +CONNECT BY level<2 and prior rltest.b=rltest.a; +drop table sin_col_tbl; DROP TABLE RLTEST; create table nocycle_tbl(id int, lid int, name text); insert into nocycle_tbl values (1,3,'A'),(2,1,'B'),(3,2,'C'),(4,2,'D'),(5,3,'E'); @@ -809,4 +840,29 @@ connect by and sy_pf.org_rela_type = 'ADMINISTRATION'; drop synonym sy_pf; -drop table pf_org_rela_test; \ No newline at end of file +drop table pf_org_rela_test; + +drop table if exists sw_test; + +-- test join clause in where split and push down into start with/connect by clause +drop table if exists sw_tb_1; +create table sw_tb_1(a int,b int,c int,d int); +create table sw_tb_2(a int,b int,c int,d int); +create table sw_tb_3(a int, b int, c int, d int); +insert into sw_tb_1 values(1,1,1,1); +insert into sw_tb_1 values(2,2,2,2); +insert into sw_tb_1 values(3,3,3,3); +insert into sw_tb_1 values(4,4,4,4); +insert into sw_tb_2 values(1,1,1,1); +insert into sw_tb_2 values(2,2,2,2); +insert into sw_tb_2 values(3,3,3,3); +insert into sw_tb_2 values(4,4,4,4); +select * from sw_tb_1,sw_tb_2 where sw_tb_1.c=sw_tb_2.d start with sw_tb_1.a>2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; +select * from sw_tb_1,sw_tb_2 where (sw_tb_1.a=sw_tb_2.b or sw_tb_1.a not in (select 3)) and sw_tb_1.c=sw_tb_2.d start with sw_tb_1.a>2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; +select * from sw_tb_1,sw_tb_2 where sw_tb_1.a !=3 or sw_tb_1.c=sw_tb_2.d start with sw_tb_1.a>2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; +select * from sw_tb_1,sw_tb_2 where (sw_tb_1.a+sw_tb_1.b=sw_tb_2.b or sw_tb_1.a=sw_tb_2.c) and (sw_tb_1.b=sw_tb_2.a or (substr(sw_tb_1.b,2)=substr(sw_tb_2.b,2) and sw_tb_1.b is null)) or (sw_tb_1.c=sw_tb_2.d or sw_tb_1.b!=2) start with sw_tb_1.a=2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; +explain select * from sw_tb_1,sw_tb_2 where (sw_tb_1.a+sw_tb_1.b=sw_tb_2.b or sw_tb_1.a=sw_tb_2.c) and (sw_tb_1.b=sw_tb_2.a or (substr(sw_tb_1.b,2)=substr(sw_tb_2.b,2) and sw_tb_1.b is null)) or (sw_tb_1.c=sw_tb_2.d or sw_tb_1.b!=2) start with sw_tb_1.a=2 connect by nocycle prior sw_tb_1.d=sw_tb_2.c; +explain select * from sw_tb_3 where exists (select * from sw_tb_1, sw_tb_2 where sw_tb_1.a + sw_tb_2.a = sw_tb_3.a connect by level < 2); +drop table sw_tb_1; +drop table sw_tb_2; +drop table sw_tb_3; \ No newline at end of file diff --git a/src/test/regress/sql/sw_prior.sql b/src/test/regress/sql/sw_prior.sql new file mode 100644 index 0000000000000000000000000000000000000000..e97638d72acb5bc3f42ffd5a8c6e2ee7c93e43c0 --- /dev/null +++ b/src/test/regress/sql/sw_prior.sql @@ -0,0 +1,705 @@ +-- base test +DROP TABLE IF EXISTS table_name; +CREATE TABLE table_name(node1, node2) AS +SELECT 'A1', 'B1' UNION ALL +SELECT 'A1', 'B2' UNION ALL +SELECT 'A2', 'B1' UNION ALL +SELECT 'A2', 'B3' UNION ALL +SELECT 'B1', 'K5' UNION ALL +SELECT 'B1', 'I2' UNION ALL +SELECT 'A3', 'G7' UNION ALL +SELECT 'A3', 'H9' UNION ALL +SELECT 'B2', 'J1' UNION ALL +SELECT 'B2', 'K5' UNION ALL +SELECT 'H9', 'L7' ; + +SELECT +CASE LEVEL WHEN 2 THEN PRIOR node1 ELSE node1 END AS node0, +CASE LEVEL WHEN 2 THEN node1 ELSE node2 END AS node1, +CASE LEVEL WHEN 2 THEN node2 END AS node2 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + +SELECT +CASE LEVEL WHEN 2 THEN PRIOR PRIOR node1 ELSE node1 END AS node0, +CASE LEVEL WHEN 2 THEN node1 ELSE node2 END AS node1, +CASE LEVEL WHEN 2 THEN node2 END AS node2 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + +SELECT +CASE LEVEL WHEN 2 THEN PRIOR(PRIOR node1) ELSE node1 END AS node0, +CASE LEVEL WHEN 2 THEN node1 ELSE node2 END AS node1, +CASE LEVEL WHEN 2 THEN node2 END AS node2 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + +SELECT +PRIOR 1 +FROM table_name; + +SELECT +PRIOR 1 +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + +SELECT +PRIOR 'test' +FROM table_name; + +SELECT +PRIOR 'test' +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + +SELECT +PRIOR repeat('test') +FROM table_name; + +SELECT +PRIOR repeat('test') +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + +SELECT +PRIOR NULL +FROM table_name; + +SELECT +PRIOR NULL +FROM table_name +WHERE LEVEL = 2 +OR (LEVEL = 1 AND CONNECT_BY_ISLEAF = 1) +START WITH node1 LIKE 'A%' +CONNECT BY PRIOR node2 = node1; + +-- test about data type +DROP TABLE IF EXISTS test_type_table; +CREATE TABLE test_type_table +( + pid int, + id int, + name text, + "int1" tinyint, + "int2" smallint, + "int4" integer, + "int8" bigint, + "float4" float4, + "float8" float8, + "numeric" decimal(20, 6), + "bit5" bit(5), + "boolean" boolean, + "date" date, + "time" time, + "timetz" timetz, + "timestamp" timestamp, + "timestamptz" timestamptz, + "char" char(20), + "varchar" varchar(100), + "blob" blob, + "text" text +); + +INSERT INTO test_type_table VALUES +(0, 1, 'top_father', 1, 1, 1, 1, 1.1, 1.1, 1.1, b'00001', true, '2024-01-01', '00:00:01', '00:00:01', '2024-01-01 00:00:01', '2024-01-01 00:00:01', 'top_father', 'top_father', '0A', 'top_father'), +(1, 2, 'second_father1', 2, 2, 2, 2, 1.2, 1.2, 1.2, b'00010', false, '2024-01-02', '00:00:02', '00:00:02', '2024-01-02 00:00:02', '2024-01-02 00:00:02', 'second_father1', 'second_father1', '0B', 'second_father1'), +(1, 3, 'second_father2', 3, 3, 3, 3, 1.3, 1.3, 1.3, b'00100', true, '2024-01-03', '00:00:03', '00:00:03', '2024-01-03 00:00:03', '2024-01-03 00:00:03', 'second_father2', 'second_father2', '0C', 'second_father2'), +(2, 4, 'third_father1', 4, 4, 4, 4, 1.4, 1.4, 1.4, b'01000', false, '2024-01-04', '00:00:04', '00:00:04', '2024-01-04 00:00:04', '2024-01-04 00:00:04', 'third_father1', 'third_father1', '0D', 'third_father1'), +(3, 5, 'third_father2', 5, 5, 5, 5, 1.5, 1.5, 1.5, b'10000', true, '2024-01-05', '00:00:05', '00:00:05', '2024-01-05 00:00:05', '2024-01-05 00:00:05', 'third_father2', 'third_father2', '0E', 'third_father2'); + +SELECT +PRIOR name AS father_name, +PRIOR "int1" AS father_int1, +name AS current_name, +"int1" AS current_int1 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "int2" AS father_int2, +name AS current_name, +"int2" AS current_int2 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "int4" AS father_int4, +name AS current_name, +"int4" AS current_int4 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "int8" AS father_int8, +name AS current_name, +"int8" AS current_int8 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "float4" AS father_float4, +name AS current_name, +"float4" AS current_float4 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "float8" AS father_float8, +name AS current_name, +"float8" AS current_float8 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "numeric" AS father_numeric, +name AS current_name, +"numeric" AS current_numeric +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "bit5" AS father_bit5, +name AS current_name, +"bit5" AS current_bit5 +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "boolean" AS father_boolean, +name AS current_name, +"boolean" AS current_boolean +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "date" AS father_date, +name AS current_name, +"date" AS current_date +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "time" AS father_time, +name AS current_name, +"time" AS current_time +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "timetz" AS father_timetz, +name AS current_name, +"timetz" AS current_timetz +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "timestamp" AS father_timestamp, +name AS current_name, +"timestamp" AS current_timestamp +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "timestamptz" AS father_timestamptz, +name AS current_name, +"timestamptz" AS current_timestamptz +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "char" AS father_char, +name AS current_name, +"char" AS current_char +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "varchar" AS father_varchar, +name AS current_name, +"varchar" AS current_varchar +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "blob" AS father_blob, +name AS current_name, +"blob" AS current_blob +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "text" AS father_text, +name AS current_name, +"text" AS current_text +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +-- test about WHERE clause +SELECT +PRIOR name AS father_name, +PRIOR "int1" AS father_int1, +name AS current_name, +"int1" AS current_int1 +FROM test_type_table WHERE PRIOR "int1" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "int2" AS father_int2, +name AS current_name, +"int2" AS current_int2 +FROM test_type_table WHERE PRIOR "int2" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "int4" AS father_int4, +name AS current_name, +"int4" AS current_int4 +FROM test_type_table WHERE PRIOR "int4" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "int8" AS father_int8, +name AS current_name, +"int8" AS current_int8 +FROM test_type_table WHERE PRIOR "int8" > 1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "float4" AS father_float4, +name AS current_name, +"float4" AS current_float4 +FROM test_type_table WHERE PRIOR "float4" > 1.1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "float8" AS father_float8, +name AS current_name, +"float8" AS current_float8 +FROM test_type_table WHERE PRIOR "float8" > 1.1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "numeric" AS father_numeric, +name AS current_name, +"numeric" AS current_numeric +FROM test_type_table WHERE PRIOR "numeric" > 1.1 +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "bit5" AS father_bit5, +name AS current_name, +"bit5" AS current_bit5 +FROM test_type_table WHERE "bit5" > b'00001' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "boolean" AS father_boolean, +name AS current_name, +"boolean" AS current_boolean +FROM test_type_table WHERE PRIOR "boolean" +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "date" AS father_date, +name AS current_name, +"date" AS current_date +FROM test_type_table WHERE PRIOR "date" > '2024-01-01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "time" AS father_time, +name AS current_name, +"time" AS current_time +FROM test_type_table WHERE PRIOR "time" > '00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "timetz" AS father_timetz, +name AS current_name, +"timetz" AS current_timetz +FROM test_type_table WHERE PRIOR "timetz" > '00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "timestamp" AS father_timestamp, +name AS current_name, +"timestamp" AS current_timestamp +FROM test_type_table WHERE PRIOR "timestamp" > '2024-01-01 00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "timestamptz" AS father_timestamptz, +name AS current_name, +"timestamptz" AS current_timestamptz +FROM test_type_table WHERE PRIOR "timestamptz" > '2024-01-01 00:00:01' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "char" AS father_char, +name AS current_name, +"char" AS current_char +FROM test_type_table WHERE PRIOR "char" LIKE '%second%' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "varchar" AS father_varchar, +name AS current_name, +"varchar" AS current_varchar +FROM test_type_table WHERE PRIOR "varchar" LIKE '%second%' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "blob" AS father_blob, +name AS current_name, +"blob" AS current_blob +FROM test_type_table WHERE PRIOR "blob" > '0A' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +SELECT +PRIOR name AS father_name, +PRIOR "text" AS father_text, +name AS current_name, +"text" AS current_text +FROM test_type_table WHERE PRIOR "text" LIKE '%second%' +START WITH id = 1 +CONNECT BY PRIOR id = pid; + +-- test about GROUP BY clause +SELECT +PRIOR "int1", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int1"; + +SELECT +PRIOR "int2", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int2"; + +SELECT +PRIOR "int4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int4"; + +SELECT +PRIOR "int8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int8"; + +SELECT +PRIOR "float4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float4"; + +SELECT +PRIOR "float8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float8"; + +SELECT +PRIOR "numeric", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "numeric"; + +SELECT +PRIOR "bit5", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "bit5"; + +SELECT +PRIOR "boolean", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "boolean"; + +SELECT +PRIOR "date", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "date"; + +SELECT +PRIOR "time", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "time"; + +SELECT +PRIOR "timetz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timetz"; + +SELECT +PRIOR "timestamp", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamp"; + +SELECT +PRIOR "timestamptz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamptz"; + +SELECT +PRIOR "char", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "char"; + +SELECT +PRIOR "varchar", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "varchar"; + +SELECT +PRIOR "blob", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "blob"; + +SELECT +PRIOR "text", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "text"; + +-- test about HAVING clause +SELECT +PRIOR "int1", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int1" HAVING PRIOR "int1" > 1; + +SELECT +PRIOR "int2", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int2" HAVING PRIOR "int2" > 1; + +SELECT +PRIOR "int4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int4" HAVING PRIOR "int4" > 1; + +SELECT +PRIOR "int8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "int8" HAVING PRIOR "int8" > 1; + +SELECT +PRIOR "float4", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float4" HAVING PRIOR "float4" > 1.1; + +SELECT +PRIOR "float8", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "float8" HAVING PRIOR "float8" > 1.1; + +SELECT +PRIOR "numeric", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "numeric" HAVING PRIOR "numeric" > 1.1; + +SELECT +PRIOR "bit5", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "bit5" HAVING PRIOR "bit5" > b'00001'; + +SELECT +PRIOR "boolean", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "boolean" HAVING PRIOR "boolean"; + +SELECT +PRIOR "date", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "date" HAVING PRIOR "date" > '2024-01-01'; + +SELECT +PRIOR "time", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "time" HAVING PRIOR "time" > '00:00:01'; + +SELECT +PRIOR "timetz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timetz" HAVING PRIOR "timetz" > '00:00:01'; + +SELECT +PRIOR "timestamp", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamp" HAVING PRIOR "timestamp" > '2024-01-01 00:00:01'; + +SELECT +PRIOR "timestamptz", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "timestamptz" HAVING PRIOR "timestamptz" > '2024-01-01 00:00:01'; + +SELECT +PRIOR "char", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "char" HAVING PRIOR "char" LIKE '%second%'; + +SELECT +PRIOR "varchar", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "varchar" HAVING PRIOR "varchar" LIKE '%second%'; + +SELECT +PRIOR "blob", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "blob" HAVING PRIOR "blob" > '0A'; + +SELECT +PRIOR "text", +COUNT(ID) +FROM test_type_table +START WITH id = 1 +CONNECT BY PRIOR id = pid GROUP BY PRIOR "text" HAVING PRIOR "text" LIKE '%second%'; diff --git a/src/test/regress/sql/tablesample_4.sql b/src/test/regress/sql/tablesample_4.sql new file mode 100755 index 0000000000000000000000000000000000000000..dea760cc682704a30369a49e537ddfdb61da4ced --- /dev/null +++ b/src/test/regress/sql/tablesample_4.sql @@ -0,0 +1,207 @@ +create schema tablesample_schema5; +set current_schema = tablesample_schema5; + +-- 创建普通表 +CREATE TABLE test ( + id int PRIMARY KEY, + some_timestamp timestamptz, + some_text text +); +-- 插入数据 +INSERT INTO test (id, some_timestamp, some_text) + SELECT + i, + now() - random() * '1 year'::INTERVAL, + 'depesz #' || i + FROM + generate_series(1,100) i; +-- 分析表的块(页)数 +analyze test; +-- 测试SAMPLE子句 +SELECT count(*) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT avg(id) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT sum(id) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (1); +-- 测试SAMPLE BLOCK子句 +SELECT count(*) FROM test tablesample system (99.9) REPEATABLE(1); +SELECT avg(id) FROM test tablesample system (99.9) REPEATABLE (1); +SELECT sum(id) FROM test tablesample system (99.9) REPEATABLE (1); +-- 添加其他过滤条件 +SELECT count(*) FROM test tablesample bernoulli ( 99.9 ) REPEATABLE (105) limit 5; +SELECT count(*) FROM test tablesample system ( 99.9 ) REPEATABLE (105) where id < 5; +SELECT count(*) FROM test tablesample system ( 99.9 ) REPEATABLE (105) limit 5; + +-- 分区表 +--- 一级分区表 +create table part_list_t1( +id number, +name varchar2(20), +age int) +partition by list(age)( +partition age_10 values(10) , +partition age_20 values(20), +partition age_default values(default)); + +insert into part_list_t1 values (1,'aa',10); +insert into part_list_t1 values (2,'bb',10); +insert into part_list_t1 values (3,'cc',20); +insert into part_list_t1 values (4,'dd',20); +insert into part_list_t1 values (5,'ee',20); +insert into part_list_t1 values (6,'ff',30); +insert into part_list_t1 values (7,'gg',100); +insert into part_list_t1 values (8,'hh',110); + +analyze part_list_t1; + +select count(*) from part_list_t1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +select count(*) from part_list_t1 tablesample bernoulli ( 99.9 ) REPEATABLE (1) where id > 5; +select count(*) from part_list_t1 partition (age_10) tablesample bernoulli ( 99.9 ) REPEATABLE (1); +select count(*) from part_list_t1 partition for (20) tablesample system ( 99.9 ) REPEATABLE (1); + +--- 二级分区表 +create table pt_range_hash_test( + pid number(10), + pname varchar2(30), + sex varchar2(10), + create_date date +) partition by range(create_date) + subpartition by hash(pid) subpartitions 4( + partition p1 values less than(to_date('2020-01-01', 'YYYY-MM-DD')) , + partition p2 values less than(to_date('2021-01-01', 'YYYY-MM-DD')) , + partition p3 values less than(to_date('2022-01-01', 'YYYY-MM-DD')) , + partition p4 values less than(maxvalue) + ); + +insert into pt_range_hash_test(pid, pname, sex, create_date) values(1, '瑶瑶', 'WOMAN', to_date('2018-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(2, '壮壮', 'MAN', to_date('2019-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(3, '晴晴', 'WOMAN', to_date('2020-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(4, '琳琳', 'WOMAN', to_date('2020-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(5, '强强', 'MAN', to_date('2021-01-01', 'YYYY-MM-DD')); +insert into pt_range_hash_test(pid, pname, sex, create_date) values(6, '团团', 'WOMAN', to_date('2022-01-01', 'YYYY-MM-DD')); + +analyze pt_range_hash_test; + +select count(*) from pt_range_hash_test tablesample bernoulli ( 99.9 ) REPEATABLE (1); +select count(*) from pt_range_hash_test tablesample bernoulli ( 99.9 ) REPEATABLE (1) where pid < 4; +select count(*) from pt_range_hash_test partition (P2) tablesample bernoulli ( 99.9 ) REPEATABLE (1); +select count(*) from pt_range_hash_test subpartition for(to_date('2020-01-01', 'YYYY-MM-DD'),3) tablesample system ( 99.9 ) REPEATABLE (1); + +-- 物化视图 +CREATE TABLE base_table +( + base_table_id INTEGER, + base_table_field NUMERIC(10,4) +); + +insert into base_table values(1,2); +insert into base_table values(3,4); +insert into base_table values(5,6); + +CREATE MATERIALIZED VIEW master_view1 AS + SELECT + base_table_id AS id, + base_table_field AS field + FROM base_table; + +analyze base_table; +analyze master_view1; + + +SELECT count(*) FROM master_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT avg(id) FROM master_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT sum(id) FROM master_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); + +SELECT count(*) FROM master_view1 tablesample system (99.9) REPEATABLE (1); +SELECT avg(id) FROM master_view1 tablesample system (99.9) REPEATABLE (1); +SELECT sum(id) FROM master_view1 tablesample system (99.9) REPEATABLE (1); + +-- 普通视图 +CREATE OR REPLACE VIEW master_view2 AS + SELECT + base_table_id AS id, + base_table_field AS field + FROM base_table; + +SELECT count(*) FROM master_view2 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM master_view2 tablesample system (99.9) REPEATABLE (1); + +CREATE OR REPLACE VIEW dependent_view1 AS + SELECT + id AS dependent_id, + field AS dependent_field + FROM master_view2; + +SELECT count(*) FROM dependent_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM dependent_view1 tablesample system (99.9) REPEATABLE (1); + +-- 连接视图 +CREATE OR REPLACE VIEW join_view1 AS + SELECT + a.id AS join_id, + base_table_field AS join_field + FROM test a join base_table b on a.id = b.base_table_id; + +explain (costs off) SELECT count(*) FROM join_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM join_view1 tablesample system (99.9); + +CREATE OR REPLACE VIEW join_view1 AS + SELECT + a.id AS join_id, + base_table_field AS join_field + FROM base_table b join test a on b.base_table_id = a.id; + +explain (costs off) SELECT count(*) FROM join_view1 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM join_view1 tablesample system (99.9); + +CREATE OR REPLACE VIEW join_view2 AS + SELECT + b.base_table_id AS nest_join_id, + join_field AS nest_join_field + FROM join_view1 a join base_table b on a.join_id = b.base_table_id; + +explain (costs off) SELECT count(*) FROM join_view2 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM join_view2 tablesample system (99.9); + +CREATE OR REPLACE VIEW join_view2 AS + SELECT + b.id AS nest_join_id, + join_field AS nest_join_field + FROM join_view1 a join test b on a.join_id = b.id; + +explain (costs off) SELECT count(*) FROM join_view2 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM join_view2 tablesample system (99.9) REPEATABLE (1); + +CREATE TABLE base_table2 +( + base_table_id INTEGER, + base_table_field NUMERIC(10,4) +); + +insert into base_table2 values(1,1); +insert into base_table2 values(2,2); +insert into base_table2 values(3,3); + +analyze base_table2; + +CREATE OR REPLACE VIEW join_view3 AS + SELECT + a.base_table_id AS id, + b.some_text AS some_text, + c.base_table_field AS field + FROM base_table a join test b on a.base_table_id = b.id + join base_table2 c on a.base_table_id = c.base_table_id; + +explain (costs off) SELECT count(*) FROM join_view3 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM join_view3 tablesample system (99.9) REPEATABLE (1); + +ALTER TABLE base_table ADD CONSTRAINT xx PRIMARY KEY (base_table_id); +explain (costs off) SELECT count(*) FROM join_view3 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM join_view3 tablesample system (99.9) REPEATABLE (1); + +ALTER TABLE base_table DROP CONSTRAINT xx; +ALTER TABLE base_table2 ADD CONSTRAINT yy PRIMARY KEY(base_table_id); +explain (costs off) SELECT count(*) FROM join_view3 tablesample bernoulli ( 99.9 ) REPEATABLE (1); +SELECT count(*) FROM join_view3 tablesample system (99.9) REPEATABLE (1); + +reset search_path; +drop schema tablesample_schema5 cascade; + diff --git a/src/test/regress/sql/test_b_format_collate.sql b/src/test/regress/sql/test_b_format_collate.sql index 707151063ce5ec5e2b238dfd3eded1c9ce2aedac..037923fa88ae6de6de3b960286b05131e722355d 100644 --- a/src/test/regress/sql/test_b_format_collate.sql +++ b/src/test/regress/sql/test_b_format_collate.sql @@ -656,6 +656,14 @@ select count(*) from test_utf8mb4_bin group by c2, c3; select distinct c2 from test_utf8mb4_bin; select distinct c3 from test_utf8mb4_bin; +set group_concat_max_len = 2; +drop table if exists t1; +create table t1(a char(32) character set 'utf8' collate utf8_general_ci) character set 'utf8' collate 'utf8_general_ci'; +insert into t1 values('律师事务部中心(中文汉字匹配)'); +select * from (select group_concat(a) ab from t1) where ab like '%中文%'; +set group_concat_max_len = default; +select * from (select group_concat(a) ab from t1) where ab like '%中文%'; + -- test alter table convert to SET b_format_behavior_compat_options = 'enable_multi_charset'; drop table if exists test_convert_to; diff --git a/src/test/regress/sql/test_b_format_collate2.sql b/src/test/regress/sql/test_b_format_collate2.sql new file mode 100644 index 0000000000000000000000000000000000000000..abe1544b76bb8dcbf8903a72a2f1dfbfcd63de16 --- /dev/null +++ b/src/test/regress/sql/test_b_format_collate2.sql @@ -0,0 +1,123 @@ +CREATE DATABASE test_collate_A4 with dbcompatibility 'b' ENCODING='SQL_ASCII' LC_COLLATE='C' LC_CTYPE='C'; +\c test_collate_A4 + +set b_format_behavior_compat_options = 'default_collation,enable_multi_charset'; + +create or replace function pg_catalog.get_index_columns(OUT namespace name, OUT indexrelid oid, OUT indrelid oid, OUT indisunique bool, OUT indisusable bool, OUT seq_in_index int2, OUT attrnum int2, OUT collation int2) returns setof record +as $$ +declare +query_str text; +item int2; +row_data record; +begin +query_str := 'select n.nspname, i.indexrelid, i.indrelid, i.indisunique, i.indisusable, i.indkey, i.indoption, i.indnkeyatts + from pg_catalog.pg_index i + left join pg_class c on c.oid = i.indexrelid + left join pg_catalog.pg_namespace n on n.oid = c.relnamespace + where n.nspname <> ''pg_catalog'' + and n.nspname <> ''db4ai'' + and n.nspname <> ''information_schema'' + and n.nspname !~ ''^pg_toast'''; +for row_data in EXECUTE(query_str) LOOP + for item in 0..row_data.indnkeyatts - 1 loop + namespace := row_data.nspname; + indexrelid := row_data.indexrelid; + indrelid := row_data.indrelid; + indisunique := row_data.indisunique; + indisusable := row_data.indisusable; + seq_in_index := item + 1; + attrnum := row_data.indkey[item]; + collation := row_data.indoption[item]; + return next; + end loop; +end loop; +end; $$ +LANGUAGE 'plpgsql'; + +create view public.index_statistic as +select + i.namespace as "namespace", + (select relname from pg_class tc where tc.oid = i.indrelid) as "table", + not i.indisunique as "non_unique", + c.relname as "key_name", + i.seq_in_index as "seq_in_index", + a.attname as "column_name", + (case when m.amcanorder + then ( + case when i.collation & 1 then 'D' else 'A' END + ) else null end + ) as "collation", + (select + (case when ts.stadistinct = 0 + then NULL else ( + case when ts.stadistinct > 0 then ts.stadistinct else ts.stadistinct * tc.reltuples * -1 end + ) end + ) + from pg_class tc + left join pg_statistic ts on tc.oid = ts.starelid + where + tc.oid = i.indrelid + and ts.staattnum = i.attrnum + ) as "cardinality", + null as "sub_part", + null as "packed", + (case when a.attnotnull then '' else 'YES' end) as "null", + m.amname as "index_type", + (case when i.indisusable then '' else 'disabled' end) as "comment", + (select description from pg_description where objoid = i.indexrelid) as "index_comment" +from + (select * from get_index_columns()) i + left join pg_class c on c.oid = i.indexrelid + left join pg_attribute a on a.attrelid = i.indrelid + and a.attnum = i.attrnum + left join pg_am m on m.oid = c.relam +order by + c.relname; + + +CREATE OR REPLACE FUNCTION pg_catalog.pg_get_nonstrict_basic_value(typename text) +RETURNS text +AS +$$ +BEGIN + IF typename = 'timestamp' then + return 'now'; + elsif typename = 'time' or typename = 'timetz' or typename = 'interval' or typename = 'reltime' then + return '00:00:00'; + elsif typename = 'date' then + return '1970-01-01'; + elsif typename = 'smalldatetime' then + return '1970-01-01 08:00:00'; + elsif typename = 'abstime' then + return '1970-01-01 08:00:00+08'; + elsif typename = 'uuid' then + return '00000000-0000-0000-0000-000000000000'; + elsif typename = 'bool' then + return 'false'; + elsif typename = 'point' or typename = 'polygon' then + return '(0,0)'; + elsif typename = 'path' then + return '((0,0))'; + elsif typename = 'circle' then + return '(0,0),0'; + elsif typename = 'lseg' or typename = 'box' then + return '(0,0),(0,0)'; + elsif typename = 'tinterval' then + return '["1970-01-01 00:00:00+08" "1970-01-01 00:00:00+08"]'; + else + return '0 or empty'; + end if; +end; +$$ +LANGUAGE plpgsql; + +CREATE VIEW public.pg_type_nonstrict_basic_value AS + SELECT + t.typname As typename, + pg_get_nonstrict_basic_value(t.typname) As basic_value + + FROM pg_type t; + + +\c postgres +DROP DATABASE IF EXISTS test_collate_A4; \ No newline at end of file diff --git a/src/test/ss/build_ss_database.sh b/src/test/ss/build_ss_database.sh index 8f2bf56e8ae80038282be7d8d3d68133623b69a9..035c7360a645b22eeab6a00b6fd0a80658e7d9d8 100644 --- a/src/test/ss/build_ss_database.sh +++ b/src/test/ss/build_ss_database.sh @@ -50,7 +50,6 @@ alter_dms_open() for node in $@ do echo -e "\nautovacuum=false" >> ${node}/postgresql.conf - echo -e "\nss_enable_reform = off" >> ${node}/postgresql.conf echo "${node}:" cat ${node}/postgresql.conf | grep ss_enable_dms done diff --git a/src/test/ss/build_ss_database_common.sh b/src/test/ss/build_ss_database_common.sh index c060ce0ffb8c926d5c0f6a8c8c2e92460f588aa9..e8710404563341db045cae9927920fcfb03d586b 100644 --- a/src/test/ss/build_ss_database_common.sh +++ b/src/test/ss/build_ss_database_common.sh @@ -56,7 +56,6 @@ assign_hatest_parameter() { for node in $@ do - echo -e "ss_enable_reform = on" >> ${node}/postgresql.conf echo -e "log_min_messages = log" >> ${node}/postgresql.conf echo -e "logging_module = 'on(ALL)'" >> ${node}/postgresql.conf echo -e "ss_log_level = 255" >> ${node}/postgresql.conf diff --git a/src/test/ss/ss_database_build_env.sh b/src/test/ss/ss_database_build_env.sh index afe6e21fc491908999e6b354aff79bb9f9d7cfb4..4ff2585317b71d0294337830aa8bc3db771c2257 100644 --- a/src/test/ss/ss_database_build_env.sh +++ b/src/test/ss/ss_database_build_env.sh @@ -66,7 +66,6 @@ assign_dms_parameter() for node in $@ do echo -e "\nautovacuum=false" >> ${node}/postgresql.conf - echo -e "\nss_enable_reform=on" >> ${node}/postgresql.conf echo -e "\nss_enable_ssl = 0" >> ${node}/postgresql.conf echo -e "\nlog_min_messages = warning" >> ${node}/postgresql.conf echo -e "\nlogging_module ='on(ALL)'" >> ${node}/postgresql.conf diff --git a/src/test/subscription/testcase/bugs.sh b/src/test/subscription/testcase/bugs.sh index 0286f2491bdfd913c8d5335179119edc865829f3..f80baab35b8c54c76dc431e3fb274ac3535ed4bf 100644 --- a/src/test/subscription/testcase/bugs.sh +++ b/src/test/subscription/testcase/bugs.sh @@ -237,6 +237,48 @@ partition p_default values less than (maxvalue) echo "$failed_keyword when check if not sync insert-data during splitting partition" exit 1 fi + + # BUG7: fix redo ddl logical message core when recovery_max_workers > 1 + exec_sql $case_db $sub_node1_port "DROP SUBSCRIPTION IF EXISTS tap_sub;DROP TABLE testTab1 cascade" + exec_sql $case_db $pub_node1_port "DROP PUBLICATION IF EXISTS tap_pub;DROP TABLE testTab1 cascade" + + restart_guc "pub_datanode1" "recovery_max_workers = 4" + restart_guc "pub_datanode2" "recovery_max_workers = 4" + + echo "create publication." + exec_sql $case_db $pub_node1_port "CREATE PUBLICATION tap_pub FOR ALL TABLES with(publish='insert,update,delete',ddl='all')" + exec_sql $case_db $pub_node1_port "create table t1 (a int);" + + poll_query_until $case_db $pub_node2_port "SELECT count(*) FROM t1" "0" "Timed out while waiting for pub_node2 to sync" + + restart_guc "pub_datanode1" "recovery_max_workers = 1" + restart_guc "pub_datanode2" "recovery_max_workers = 1" + + # BUG8: fix publisher choose relation incorrectly if there are more than one relation in different schemas with the same name. + exec_sql $case_db $sub_node1_port "DROP SUBSCRIPTION IF EXISTS tap_sub;DROP TABLE testTab1 cascade" + exec_sql $case_db $pub_node1_port "DROP PUBLICATION IF EXISTS tap_pub;DROP TABLE testTab1 cascade" + + exec_sql $case_db $pub_node1_port "create table logical_tb1(id int primary key,name varchar(20));" + exec_sql $case_db $pub_node1_port "create schema test_sche;create table test_sche.logical_tb1(id int primary key,id1 int);" + exec_sql $case_db $sub_node1_port "create schema test_sche;create table test_sche.logical_tb1(id int primary key,id1 int);" + + echo "create publication and subscription." + publisher_connstr="port=$pub_node1_port host=$g_local_ip dbname=$case_db user=$username password=$passwd" + exec_sql $case_db $pub_node1_port "CREATE PUBLICATION tap_pub FOR TABLE test_sche.logical_tb1;" + exec_sql $case_db $sub_node1_port "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr' PUBLICATION tap_pub" + + wait_for_subscription_sync $case_db $sub_node1_port + + exec_sql $case_db $pub_node1_port "insert into test_sche.logical_tb1(id,id1) values(1,111),(2,222);" + wait_for_catchup $case_db $pub_node1_port "tap_sub" + + if [ "$(exec_sql $case_db $sub_node1_port "SELECT * FROM test_sche.logical_tb1")" = "1|111 +2|222" ]; then + echo "check if table sync success" + else + echo "$failed_keyword when check if table sync" + exit 1 + fi } function tear_down() {